View Full Version : How can I start a new thread?
Soundbytes
02-24-2010, 03:48 AM
Hi all,
I am currently porting all my stuff to the IPlug framework.
Everything worked out remarkably well so far but now I am afraid I am stuck with a multithreading problem.
My Synth uses a multisample that is loaded from disk on user request.
The data is a couple of megabytes in size and I need to have a separate thread for the sample loader to avoid audio dropouts while the data is read.
Question: Is there a recommended way to create/start/stop a thread in WDL that works fine on all supported OS platforms?
I tried to find out how the plugin grapics thread is created but could not figure it out so far. Any hints are most welcome. Thanks!
Andreas
I haven't used it yet, but swell has code in there for emulating the windows thread stuff on OSX using pthreads. Take a look in swell/swell.c there's CreateThread() etc.
So you should be able to write windows code and have it run on OSX too.
I'd be very interested in hearing how you get on...
Soundbytes
02-24-2010, 07:39 AM
Thanks! That looks exactly like what I was looking for (+ it answers a couple of questions that I was about to ask)
junioreq
02-25-2010, 01:33 AM
http://dl.dropbox.com/u/1933049/click.PNG
..
Sorry, It was eating me up all day, I had to :)
~Rob.
Soundbytes
02-25-2010, 09:17 AM
Here is a first version of my threading class. It works fine in windows but unfortunately does not compile in OS X. It uses the GetExitCodeThread() WIN32 API function that is not supported by swell. Is there an alternative way to check the thread status that can be implemented with IPlug/swell?
I need to know the thread status because otherwise the thread object might be destroyed before the tread is properly exited.
Any hints are most welcome. Thanks!
The sb_thread class encapsulates all the complicated stuff and makes thread management available through simple start() and end functions().
Usage is quite straightforward - All You have to do is inhertit from that class and implent the doStuff() member function that runs within the daughter thread.
Note that the thread function does not have to be a global function or a static member function. This is all sorted out by the thread object.
This implementation is lock free. Instead it uses atomic shared variables to send commands and to signal the state of the thread.
have fun
Andreas
As an example here is dummy sample loader that uses the sb_thread object.
I would recommend to add the sample loader (or your customized thread object) as a member object to the plugin class.
start() can be called in Plugin::Resume(). (do not bloat the Plugin constructor by calling loader.start() there.)
There is no need to explicitly end the daughter thread. This is taken care of by the Plugin destructor.
//-- sb_dummySampleLoader declaration------------------------------
class sb_dummySampleLoader : public sb_thread // inherit!
{
public:
sb_dummySampleLoader() : sampleIdx(0), sampleLoadDone(false) {isVirtual = false;}
~sb_dummySampleLoader(){isVirtual = true;}
// This function is called by the main thread to trigger a
// sample swap in the loader thread.
void setNewSampleIdx( int newSampleIdx );
// thread function - must be implemented.
void doStuff();
// all variables used by both threads need to be declared volatile
// _and_ they must be atomic (only then the communication can be lock free.)
volatile bool sampleLoadDone;
volatile int sampleIdx;
};
//-- sb_dummySampleLoader implementation --------------------------
void setNewSampleIdx( int newSampleIdx )
{
if( sampleIdx != newSampleIdx ){
sampleIdx = newSampleIdx;
// Signal to the loader thread that there is some work to do.
sampleLoadDone = false;
// TODO: mute the audio process - access to the
// sample table is not possible now.
}
}
void sb_dummySampleLoader::doStuff()
{
while(true){
// do stuff
if (!sampleLoadDone){
//
// Load new sample[sampleIdx]
//
MessageBox(
NULL,
"New Sample Now Loading.\n(err, not quite yet.)",
"IPlug Example Synth",
0);
sampleLoadDone = true; // was set false by the request.
}
Sleep(200);
if(switchOff) break;
}
}
Here is the sb_thread function that does the magic:
//-- sbThread declaration ----------------------------------------
class sb_thread
{
public:
sb_thread() : hnd(NULL), switchOff(true), isVirtual(true) {}
~sb_thread(){
end();
}
void start();
void end();
protected:
volatile bool isVirtual;
volatile bool switchOff;
virtual void doStuff() = 0;
private:
static DWORD WINAPI threadProc( LPVOID pItem_ );
HANDLE hnd;
DWORD exitCode;
};
//-- sb_thread implementation ----------------------------------
void sb_thread::start(){
// create the new thread only once
if (hnd == 0){
// reset state variables
exitCode = 0;
switchOff = false;
hnd = CreateThread( NULL, 0, threadProc, this, 0, NULL);
}
}
void sb_thread::end(){
switchOff = true;
// wait until thread is finished!
// This is crucial since otherwise it is not guaranteed that
// all objects created by the daughter thread are destroyed.
// (that is when end() is called from ~sb_thread().)
if (hnd != 0){
WaitForSingleObject(hnd ,INFINITE);
CloseHandle(hnd);
hnd = 0;
}
}
DWORD WINAPI sb_thread::threadProc( LPVOID pThis_ ){
sb_thread* pThis = (sb_thread*)pThis_;
if(!pThis->isVirtual) pThis->doStuff();
return 1;
}
Here is a first version of my threading class. It works fine in windows but unfortunately does not compile in OS X. It uses the GetExitCodeThread() WIN32 API function that is not supported by swell. Is there an alternative way to check the thread status that can be implemented with IPlug/swell?
I need to know the thread status because otherwise the thread object might be destroyed before the tread is properly exited.
Any hints are most welcome. Thanks!
I don't know much about threads, but I think WaitForSingleObject(hdn, 0) does what you want.
Jeffos
02-25-2010, 10:09 AM
yes, this is what I do in order to stop a thread properly (here "m_quit" breaks a threading loop):
if (m_thread)
{
m_quit=true;
WaitForSingleObject(m_thread,INFINITE);
CloseHandle(m_thread);
m_thread=0;
}
both WaitForSingleObject and CloseHandle seems mapped in swell.h but I can't tell much more about OSX..
[edit] "INFINITE" = 0xFFFFFFFF !
Soundbytes
02-25-2010, 12:55 PM
I am stuck again. I implemented the proposed changes and still the plugin does not compile as OS X AU. In fact it seems that the definitions and defines from swell.h are not recognized all together.
Initially I had thought that swell.h was already included with the Xcode project. Then I included swell.h explicitly within myPlugin.h with no success either. Finally I copied the main.h from the swell demo project and included that. Still none of the swell wrapped functions and data types is recognized. what am I doing wrong? Thanks!
Andreas
You will need to include swell.h in the files that use the emulated functions at least.
What are the errors you are getting exactly?
Soundbytes
02-26-2010, 05:07 AM
You will need to include swell.h in the files that use the emulated functions at least.
What are the errors you are getting exactly?
I thought they were compiler errors however on looking closer I found that I got linker errors. The fix was easy then. I just had to include the missing source files with the Xcode project. :-)
I thought it might be that, but then I thought that stuff was compiled with IPlug, what files did you have to add?
Soundbytes
02-27-2010, 05:58 AM
I thought it might be that, but then I thought that stuff was compiled with IPlug, what files did you have to add?
I checked the IPlug Xcode project.
It includes these swell files (in group Lice > Swell):
swell-gdi.mm
swell-misc.mm
swell-internal.h
swell.h
To make my Plugin compile I added these files to my project:
swell.cpp
swell-kb.mm
swell-menu.mm
swell-misc.mm
swell-miscdlg.mm
swell-wnd.mm
swell-appstub.mm
swell-dlg.mm
swell-gdi.mm
swell-ini.mm
I admit I did not do much research. Instead I just copied the list from the swell example app and removed those files that gave me compiler errors. I chose the files just by trial and error and did not look deeper in what's in there. At the moment I am just happy that my plugin compiles and that I did not have to spend much more time looking into the details of the swell library. (will do that later)
Andreas
Andreas
Soundbytes
03-11-2010, 03:18 PM
Hi,
I found that Cubase LE 3 did not really like my code. (it worked fine with Cubase 5 and with all other hosts that I have tried so far)
When the plugin is loaded for the first time Cubase 3 tries to do some tests. It creates a plugin instance then calls setSampleRate() (which in turn triggers an IPLug Reset() )
This is where my thread process is started. The Plugin object is now destroyed and unfortunately my thread function is then executed right after the underlying object has gone away. Bang!
I have now fixed the issue. The thread class example a few posts above contains the updated code.
Andreas
leighhunt
01-23-2017, 01:44 PM
Hi there Andreas and all concerned in this thread.
Well, it took me two evenings to accomplish, but now I am the happy user of a separate thread in a plugin I am building.
I can only begin to thank you all for your explanations, albeit from some time ago!
Kind regards,
Leigh
john jewell
03-16-2022, 02:37 PM
I need help bad. I need to post a new topic in the forum but I can't figure out how to do that.
Sibben
06-20-2022, 10:12 AM
I thought you meant a forum thread and went ”dude, you just did…”. :rolleyes:
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.