|
This thread is locked; no one can reply to it. |
1
2
|
Callback Problem |
Thomas Fjellstrom
Member #476
June 2000
|
1. I don't believe pthreads EXISTS on DOS or DS. -- |
axilmar
Member #1,204
April 2001
|
Kitty Cat said: Depends on the system. Allegro can run single-threaded on Linux (AFAIK), and has to run single-threaded on DOS. If one is interested in running the program in DOS, then the app must be coded in a special way so as that DOS is handled appropriately. It is not very difficult to use #ifdef to include different APIs according to platform. Orz said: Would adding a pthreads lock to the callback change anything on any specific platform? Yes. It would make the program correct in those platforms that input is handled by a different thread. Orz said: Is this the manner in which Allegro intends its callbacks to be used? Allegro has many DOSisms. Any modern library would not use the concept of interrupt to service input, but the concept of input queue. Unfortunately for us, Allegro does not do that, so there are two solutions: 1) fix Allegro to provide a mouse queue, like the keyboard queue. I have done #2 in my GUI code. Orz said: What is the cost of adding additional locking? It's minimal, because critical sections are used. Orz said: In order for it to change something, the callback functions would have to be running concurrently with themselves on some platform. Nope, you got it wrong here. The lock will not synchronize the input threads, because there is only one input thread. The lock will synchronize the input thread and the main thread. Orz said: If you use Allegro's built-in locking mechanisms (_enter_critical() and _exit_critical())... well, I don't know what the drawbacks are - Allegro's built-in locking mechanisms are undocumented so far as I can tell, so I presume you're not intended to use them for normal Allegro programs. Exactly. Orz said: If you use platform-specific locking mechanisms, the obvious cost is in portability. It's no big deal to do so; just a couple of #ifdefs. Orz said: If you use pthreads or another threading API with implementations for a variety of platforms, the obvious cost is the standard cost for adding dependancies - it makes it harder for arbitrary Allegro users to get your code running - they have to get the library themselves, and figure out how to install it and link with it. This cost is greatly reduced if you are the only one likely to compile your code. (additionally, I suspect that using pthreads calls inside a DOS interrupt is a bad idea) The cost of debugging multithreaded programs far outweights the cost of installing and linking with a library. Here is a very interesting link with the following quote: No variable or structure should be accessed from multiple threads without being accessed in a thread-safe fashion. Obviously the guy has great experience with threads and Windows, so if you don't accept my comment, please accept his. |
Kitty Cat
Member #2,815
October 2002
|
Quote: If one is interested in running the program in DOS, then the app must be coded in a special way so as that DOS is handled appropriately. Not if its coded properly. As long as you use Allegro properly, and don't rely on platform-specific behavior (eg. how callbacks are implemented), it'll work. However, people tend to become lax because "it's not needed right now for my target platform(s)" and thus don't bother with proper code. Quote: It is not very difficult to use #ifdef to include different APIs according to platform. And given that this will be layered on top of the new API in the future, what'll you do if all platforms, instead of just DOS, are then more sensitive to improper code? You'll pretty much lock it out of being able to use the compatibility layer of newer versions and require Allegro 4.2 only. -- |
axilmar
Member #1,204
April 2001
|
Quote: Not if its coded properly. The only 'coded properly' technique with multiple threads is to use synchronization. Didn't you read the link I posted? |
Kitty Cat
Member #2,815
October 2002
|
Quote: The only 'coded properly' technique with multiple threads is to use synchronization. Yes, I fully agree with that. I'm talking about Allegro's callbacks, though. You can't assume whether Allegro's callbacks are threaded or not. -- |
orz
Member #565
August 2000
|
Quote:
1. I don't believe pthreads EXISTS on DOS or DS.
1. http://moss.csc.ncsu.edu/~mueller/pthreads/ Quote: The cost of debugging multithreaded programs far outweights the cost of installing and linking with a library.Here [flounder.com] is a very interesting link with the following quote: [bold]No variable or structure should be accessed from multiple threads without being accessed in a thread-safe fashion.[/bold]
You conspicuously omitted the next line "Note that this applies only to variables where concurrent access can produce incorrect results". He then links to an example of his where he recommends using just volatile variables. Quote: Nope, you got it wrong here. The lock will not synchronize the input threads, because there is only one input thread. The lock will synchronize the input thread and the main thread.
There are three different locking scenarios we're looking at here in this thread: In that particular case, you were apparently talking about type B, while I was talking about type A. It is my position that locking types A and B are pointless. I think everyone is in agreement that type C is necessary if and only if the program is multithreaded (not counting Allegro-created threads that the user code knows nothing about). However, I'm beginning to suspect that you might be right. After reading through a bunch of x86, PPC, and C docs, it looks like the ordering may not be guaranteed between multiple CPUs under the circumstances in which the callbacks execute on various platforms unless extra effort is made. That's somewhat scary though, as this appears to be what Allegro does internally... possibly I've been up to long, but to my current interpretation, not only is this code slightly flawed in a multi-CPU environment, but so is Allegro keyboard handling on WIN32 and OSX. And I'm not too sure about the Linux version either... executing in the SIGIO handler protects it somewhat, but only if the reading thread is the original thread, and it can also execute in a timer callback instead, or from the main thread if simulate_keypress is called... Will think more tomorrow. Hopefully. edit: fixed typo and changed #3 at the top |
axilmar
Member #1,204
April 2001
|
Quote: Yes, I fully agree with that. I'm talking about Allegro's callbacks, though. You can't assume whether Allegro's callbacks are threaded or not. Well, if the game/library needs to behave correctly in the 90% of the computers out there (i.e. those that run Windows), you need to code threads properly. Quote:
You conspicuously omitted the next line "Note that this applies only to variables where concurrent access can produce incorrect results". He then links to an example of his where he recommends using just volatile variables. Incrementing an integer is not thread-safe, period. If you read the whole thing, you would have seen the analysis of the assembly code. You are just asking for trouble especially when the integer is an index to a buffer. Quote: However, I'm beginning to suspect that you might be right. No sh1t, Sherlock! :-) CPUs have gone multicore, you have forgotten that??? |
orz
Member #565
August 2000
|
Quote: Incrementing an integer is not thread-safe, period. If you read the whole thing, you would have seen the analysis of the assembly code. You seem to be ignoring the point of that: when a variable is only written to by one thread, the atomicity of the entire read-modify-write operation becomes irrelevant. Only the atomicity of the write operation itself is relevant, because the variable cannot be modified asynchronously to that code (because only one thread modifies it). And the write is generally atomic, provided that the integer is aligned (caveats: not true on 386sx when paired with a 32 bit compiler, some 8 bit CPU/compiler combinations, a few other arcane places... but to get even a remotely possible failure you have to find a platform that uses one of the handful of CPUs on which that's not true, uses multiple CPUs concurrently, and runs Allegro programs; you'd have an easier time finding a system that uses 10 bit bytes). Quote: You are just asking for trouble especially when the integer is an index to a buffer. That is the part I'm agreeing with now - that using the variable as an index into a changing buffer is unsafe. According to my current understanding, this code has the capacity to return garbage input (though it almost never will). It could be fixed with threading libraries, platform specific locking mechanisms, or more exotic coding methods. However, I think that the Allegro internals have the same flaw in them, so you suffer from this flaw regardless... Quote: CPUs have gone multicore, you have forgotten that??? I remembered the multicore part, but did not realize that Intel and others had weakened their memory coherency policies (I expected at least PRAM consistency for writes to volatile variables). And I presumed that Allegro would arrange things in such a way that its input callbacks were usable in a safe manner without extra dependencies or extraordinary effort. edit: ARRGHH! The code is correct on some platforms only. x86/*: Allegro and this code both work, because of strong memory coherency guarantees on normal x86 systems. non-x86/linux: Allegro and this code probably work correctly, if the user code is totally single-threaded. Merely having only one thread talk to allegro is not enough though - it must also be the thread that handles signals. On x86 specifically the issue is (I think) irrelevant though because of the x86/* strong coherency guarantees. However, the buf.lock mechanism should be kept, because in (very rare) cases the callback can become reentrant. PPC/macOSX: Allegro and this code are both incorrect on this platform. PPC/macOS9 and x86/DOS: Allegro and this code are correct, because (I think) the code all executes in interrupt context anyway. |
axilmar
Member #1,204
April 2001
|
Quote: That is the part I'm agreeing with now - that using the variable as an index into a changing buffer is unsafe.
Quote: ARRGHH! You went into all this trouble just to prove what others said from the beginning? :-) |
orz
Member #565
August 2000
|
Quote: You went into all this trouble just to prove what others said from the beginning? :-) And to submit a bug report : ) |
|
1
2
|