Using threads isn't possible on all platforms. This is why aRts was originally written without using threading at all. For almost all problems, for each threaded solution to the problem, there is a non-threaded solution that does the same.
For instance, instead of putting audio output in a separate thread, and
make it blocking, aRts uses non-blocking audio output, and figures out
when to write the next chunk of data using
select()
.
However, aRts (in very recent versions) at least provides support for
people who do want to implement their objects using threads. For
instance, if you already have code for an mp3
player, and the code expects the mp3
decoder to run in a separate thread, it's
usually the easiest thing to do to keep this design.
The aRts/MCOP implementation is built along sharing state between separate objects in obvious and non-obvious ways. A small list of shared state includes:
The Dispatcher object which does MCOP communication.
The Reference counting (Smartwrappers).
The IOManager which does timer and fd watches.
The ObjectManager which creates objects and dynamically loads plugins.
The FlowSystem which calls calculateBlock in the appropriate situations.
All of the above objects don't expect to be used concurrently (that is, called from separate threads at the same time). Generally there are two ways of solving this:
Require the caller of any functions on this objects to acquire a lock before using them.
Making these objects really threadsafe and/or create per-thread instances of them.
aRts follows the first approach: you will need a lock whenever you talk to any of these objects. The second approach is harder to do. A hack which tries to achieve this is available at http://space.twc.de/~stefan/kde/download/arts-mt.tar.gz, but for the current point in time, a minimalistic approach will probably work better, and cause less problems with existing applications.
You can get/release the lock with the two functions:
Generally, you don't need to acquire the lock (and you shouldn't try to do so), if it is already held. A list of conditions when this is the case is:
You receive a callback from the IOManager (timer or fd).
You get call due to some MCOP request.
You are called from the NotificationManager.
You are called from the FlowSystem (calculateBlock)
There are also some exceptions of functions. which you can only call in the main thread, and for that reason you will never need a lock to call them:
Constructor/destructor of Dispatcher/IOManager.
Dispatcher::run()
/
IOManager::run()
IOManager::processOneEvent()
But that is it. For everything else that is somehow related to aRts, you will need to get the lock, and release it again when done. Always. Here is a simple example:
class SuspendTimeThread : Arts::Thread { public: void run() { /* * you need this lock because: * - constructing a reference needs a lock (as global: will go to * the object manager, which might in turn need the GlobalComm * object to look up where to connect to) * - assigning a smartwrapper needs a lock * - constructing an object from reference needs a lock (because it * might need to connect a server) */ Arts::Dispatcher::lock(); Arts::SoundServer server = Arts::Reference("global:Arts_SoundServer"); Arts::Dispatcher::unlock(); for(;;) { /* * you need a lock here, because * - dereferencing a smartwrapper needs a lock (because it might * do lazy creation) * - doing an MCOP invocation needs a lock */ Arts::Dispatcher::lock(); long seconds = server.secondsUntilSuspend(); Arts::Dispatcher::unlock(); printf("seconds until suspend = %d",seconds); sleep(1); } } }
The following threading related classes are currently available:
Arts::Thread
- which encapsulates a thread.
Arts::Mutex
- which encapsulates a mutex.
Arts::ThreadCondition
- which provides
support to wake up threads which are waiting for a certain condition to
become true.
Arts::SystemThreads
- which encapsulates the operating system threading layer (which offers
a few helpful functions to application programmers).
See the links for documentation.
Would you like to comment or contribute an update to this page?
Send feedback to the TDE Development Team