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" wrote
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*
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" wrote
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 );
}
}
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








"Steven Schveighoffer" <schveiguy yahoo.com>