Jump to content
  • Advertisement
Sign in to follow this  
  • entries
    3
  • comments
    5
  • views
    3331

Thread synchronization = head hurts

Sign in to follow this  
alphatrak

279 views

I finally made the jump to GDNET+. I've been posting to my own site for a while now. If you want to see those posts, they're at http://www.illusivestudios.com/journal/index.php?finger=Nightshift.

The past month or so, i've been working on a sound/music engine for custom game engine using DirectX 9.

The sound engine works great in the main thread of an app, but I'd like to put the sound engine in it's own thread, so that window messages don't interfere with filling sound buffers. The problem is I'm not very good with multithreaded programming. Even though I've been programming since high school (96), I still haven't played much with threads (at least not in Windows).

Within the sound engine test app, I create a separate thread, in which all it does is check to see if all sound buffers need to be updated, and updates them if needed. (Yes, it polls.. I simply haven't gotten around to setting up notifications just yet).

The problem is that when stopping the buffer from within the main thread, DirectSound could potentially stop the buffer while it's being updated in the other thread, which makes things sound out of place if Play( ) is called again.

So I thought I could use the CRITICAL_SECTION related win32 functions, but when I press the key that calls Stop( ), sometimes it takes a good 5 seconds before the buffer actually stops playing.

I also tried writing my own "critical section" code.... so basically, in the Update and Stop functions, I do this...


// at start of both Update and Stop...
while(g_bLocked);
g_bLocked = TRUE;
...
// at end of both Update and Stop
g_bLocked = FALSE;





The problem with this is that when I call Stop, it gets stuck in the while loop and never actually stops the buffer. I think that because it's not getting back to the main message loop, the process never does a context switch to the other thread. (Again, it goes back to me not understanding threads).

Unless anyone can clue me in on what i'm doing wrong, I think how I'm gonna fix it is have a Queue object within the sound engine, and that's how it would determine what operations to perform next... so when I call Update in the thread, it will "Queue" a call to Update in the main thread. Calling Stop will also Queue up a stop event in the main thread, which will cause the sound engine to "wait" until the Update for that particular buffer is done.

The problem then becomes one of syncronizing reads and writes to the queue.

I'm not sure why the CRITICAL_SECTION related win32 functions would not work. Aren't these supposed to be pretty effecient? Makes me wonder how long the Updates are taking. I know the Updates are NOT taking 5 seconds tho [smile]


EDIT: I think I found out what I'm doing wrong with the CRITICAL_SECTION functions. I'm only calling InitializeCriticalSection once upon engine initialization, and calling DeleteCriticalSection once upon engine shutdown. Wups. Now I just need to get out of work, so I can go home and try it out.

Sign in to follow this  


5 Comments


Recommended Comments

Welcome to JOURNAL LAND! Here be some +

(har har I beat evelyn to it :D)

You could try using a mutex for your synchronization needs. The following functions are helpful -
  • CreateMutex(..)
  • WaitForSingleObject(..)
  • ReleaseMutex(..)

I can't make any comments on CRITICAL_SECTION though, other than that using a mutex incurs only slightly more overhead than CRITICAL_SECTION.

Someone else who knows more should pop in any moment now, though.

EDIT: I figured you might want to see some usage. Here's my crappy abstraction of a Win32-created thread -

#pragma once


#ifndef PAWN_TASK_WIN32THREAD
#define PAWN_TASK_WIN32THREAD

#include <windows.h>
#include <boost/function.hpp>

class Win32_Thread {
bool _busy;
HANDLE _handle;

typedef boost::function< int ( void* ) > FuncType;
FuncType _func;

static DWORD WINAPI _threadProc( void* param ) {
Win32_Thread* thread = (Win32_Thread*) param;
return thread->_func( param );
}

public:
void setBusy( bool busy ) {
_busy = busy;
}

bool isBusy() {
return _busy;
}

void suspend() {
SuspendThread( _handle );
}

void resume() {
ResumeThread( _handle );
}

void kill() {
if ( _handle )
TerminateThread( _handle, 0 );

_handle = 0;
}

void sleep( DWORD time ) {
Sleep( time );
}


Win32_Thread( FuncType ThreadProc )
: _busy( false ),
_func( ThreadProc )
{
_handle = CreateThread(
NULL,
0,
&_threadProc,
this,
0,
NULL );
}

~Win32_Thread() {
kill();

CloseHandle( _handle );
}
};

class Win32_Mutex {
HANDLE _handle;

public:

DWORD lock() {
return WaitForSingleObject( _handle, INFINITE );
}

BOOL release() {
return ReleaseMutex( _handle );
}

Win32_Mutex() {
_handle = CreateMutex( NULL, FALSE, NULL );

if ( NULL == _handle ) {
// do something :O
}
}
};

#endif

Share this comment


Link to comment
Welcome to Journal land! here be some +

Har har, indeed Mushu!....at least I use BIG words to show my appreciation to anyone commiting some pennies to this site, phftt.... [grin]

Share this comment


Link to comment
Welcome to Journal land! here be some +

Har har, indeed Mushu!....at least I use BIG words to show my appreciation to anyone commiting some pennies to this site, phftt.... [grin]

Share this comment


Link to comment
Thanks for the welcome.

Mushu,
Big thanks for the mutex code. I still couldn't get the critical section functions working as expected, but the mutex code works perfectly: The sound engine can now stop/pause/start/update the buffers all safely now.

Thanks!
-Gordon

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!