digitalmars.D - Multi-Thread Application problem
- Benjamin Schulte (18/18) Feb 04 2008 Hello,
- Steven Schveighoffer (9/35) Feb 04 2008 This seems to imply that you are doing a wait operation in your destruct...
- Benjamin Schulte (105/105) Feb 04 2008 Hi,
- Steven Schveighoffer (11/31) Feb 04 2008 What is stopping you from calling glDeleteBuffersARB from the destructor...
Hello, I'm having a problem with a problem in a multi threaded application since several days. The problem itself is easy to describe. Let's say theres are two threads. Thread A and Thread B. Thread A has to do most of the things for the application - drawing, movement, etc. (It's a game) Thread B has to do all the loading stuff. Well since OpenGL doesn't support handling drawing methods from Thread B there is a class that does simply: Thread B requests to call something and waits for Thread A to handle it - then it continues. But sometimes - without any real sense where it happens Thread A stops - and Thread B - well, Thread B waits for Thread A at the told position. However, I now wondered if it's possible that a Thread goes into the "critical mode" as soon a 'delete' is being called. like: delete abc; --> ~this( ) { // Within this there is no thread switching?? } <-- // Now we can switch again Hope you can understand what I mean >.> *not the best english*
Feb 04 2008
"Benjamin Schulte" wroteHello, I'm having a problem with a problem in a multi threaded application since several days. The problem itself is easy to describe. Let's say theres are two threads. Thread A and Thread B. Thread A has to do most of the things for the application - drawing, movement, etc. (It's a game) Thread B has to do all the loading stuff. Well since OpenGL doesn't support handling drawing methods from Thread B there is a class that does simply: Thread B requests to call something and waits for Thread A to handle it - then it continues. But sometimes - without any real sense where it happens Thread A stops - and Thread B - well, Thread B waits for Thread A at the told position. However, I now wondered if it's possible that a Thread goes into the "critical mode" as soon a 'delete' is being called. like: delete abc; --> ~this( ) { // Within this there is no thread switching?? } <-- // Now we can switch again Hope you can understand what I mean >.> *not the best english*This seems to imply that you are doing a wait operation in your destructor? This is a bad idea. Destructors are only for cleaning up system resources. Perhaps you can post your destructor code that you suspect is hanging here and we can have a look. BTW, being in the destructor in itself will not force thread switching to stop, but if the destructor is being called by the garbage collector, all threads are halted while the garbage collector runs. -Steve
Feb 04 2008
Hi, thanks for your reply. I guess this was the fact I didn't know so far. Is it for the constructor equal? But yes, I had a sleep in the deconstructor, waiting for the other thread. I then just wonder why it worked sometimes and only a few times it didn't. But maybe there's still another bug in my applcation. But here's the code - maybe there's still a way to optimize it. But I guess first I need to replace the deconstructor with a free-method deleting itself after freeing the resources. ThreadCall.doEvents( ) is being called from Thread A. class someclass { ~this( ) { // Outside-Of-Thread call ThreadCall.call( function( uint id ) { glDeleteBuffersARB( 1, cast(uint*)&id ); return 0; }, cast(uint)vboBuffer ); } } // Alias alias int function( uint ) ThreadCallPtr; /********************************************************************* * The thread call class *********************************************************************/ class ThreadCall { /********************************************************* * Call a method *********************************************************/ static uint call( ThreadCallPtr ptr, uint param ) { uint myId = getUniqueId( ); // If myId is equal to the main thread ID, we don't // have to wait until we can call this method if( myId == mainThreadId ) { // Call method return ptr( param ); } else { // Well, we have to wait for the main thread // Create call ThreadCall c = new ThreadCall; c.method = ptr; c.param = param; // Append call to event list mainSemaphore.enter( ); calls ~= c; mainSemaphore.leave( ); // Wait for call to be finished while( !c.finish ) usleep(10); // Delete my item and return its result int r = c.result; delete c; return r; } } /********************************************************* * Do all events (Called in the main thread) *********************************************************/ static void init( ) { // Get main-thread ID mainThreadId = getUniqueId( ); mainSemaphore = new Semaphore( ); } /********************************************************* * Return an unique ID describing the current thread * WARNING: OS DEPENDEND! *********************************************************/ static uint getUniqueId( ) { // Windows method return cast(uint)GetCurrentThreadId( ); } /********************************************************* * Do all events (Called in the main thread) *********************************************************/ static void doEvents( ) { mainSemaphore.enter( true ); // Go through every item foreach( ThreadCall c; calls ) { // Call method c.result = c.method( c.param ); c.finish = true; } // Clear list, cause we did all calls.length = 0; mainSemaphore.leave( ); } /********************************************************/ ThreadCallPtr method; uint param; int result; bit finish = false; static ThreadCall calls[]; static uint mainThreadId; static Semaphore mainSemaphore; };
Feb 04 2008
"Benjamin Schulte" wroteHi, thanks for your reply. I guess this was the fact I didn't know so far. Is it for the constructor equal? But yes, I had a sleep in the deconstructor, waiting for the other thread. I then just wonder why it worked sometimes and only a few times it didn't. But maybe there's still another bug in my applcation. But here's the code - maybe there's still a way to optimize it. But I guess first I need to replace the deconstructor with a free-method deleting itself after freeing the resources. ThreadCall.doEvents( ) is being called from Thread A. class someclass { ~this( ) { // Outside-Of-Thread call ThreadCall.call( function( uint id ) { glDeleteBuffersARB( 1, cast(uint*)&id ); return 0; }, cast(uint)vboBuffer ); } }What is stopping you from calling glDeleteBuffersARB from the destructor? (I'm assuming glDeleteBuffersARB is a C call). Aside from that, probably the only good way to do this is to queue the call and not wait for the result. However, it is possible that the semaphore is already locked. I remember someone having a problem with freeing resources by using a C function in a destructor, and finding that a lock was held by a suspended thread. I think this problem has been solved in Tango's GC (I could be wrong). You may want to look into that. -Steve
Feb 04 2008