• entries
3
5
• views
3331

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 Stopg_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.

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

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

bool   _busy;
HANDLE _handle;

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

static DWORD WINAPI _threadProc( void* param ) {
}

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

bool isBusy() {
return _busy;
}

void suspend() {
}

void resume() {
}

void kill() {
if ( _handle )

_handle = 0;
}

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

: _busy( false ),
{
NULL,
0,
this,
0,
NULL );
}

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



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]

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]

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

## Create an account

Register a new account