Subj : Re: Thoughts about threads in C++ To : comp.programming.threads From : Maciej Sobczak Date : Fri May 27 2005 06:59 pm Hi, Arash Partow wrote: >>>1. You use explicit lock and unlock calls in your example code. This is >>>not really C++. > > Threading is not really C++ either - or at least until someone defines > it within the standard. So in theory what one does could be > interpreted either way. that said I have not seen a C++ guru of high > calibre get up on the podium and say so and so way is the right way to > do this and the other way is wrong. The point is about the exception safety and resource management. This is a much broader issue than threading. Explicit use of lock() and unlock() methods is contrary to what C++ is promoting, that's why I say that this is not really C++. The following pages will have more to say about this: http://www.research.att.com/~bs/bs_faq2.html#finally http://www.gotw.ca/gotw/082.htm http://www.parashift.com/c++-faq-lite/exceptions.html Of course, what makes a guru of high calibre (and a podium) is kind of subjective, but since you mentioned Boost on your page, then let's use it as a basis for discussion. In Boost.Threads lock() and unlock() methods of the mutex class are private and cannot be used by the client code directly. You have done something contrary. Why? What is the advantage of your approach in relation to the approach taken by Boost.Threads? For me, replacing this: pthread_mutex_lock(mtx); // ... pthread_mutex_unlock(mtx); with this: mtx.lock(); // ... mtx.unlock(); has very little added value. >>>3. The class POSIXScopeMutex makes no sense at all - how do you want to >>>use it from multiple threads? > > not everything can be used everywhere, the scope mutex is one of these > cases. Its purpose is two fold. > > 1.) to make mutex oriented code look cleaner > > 2.) to ensure any additions to the code which is meant to be mutexed > wont effect the synchronos of the code. > > > Basically you pass an reference of a mutex to the scope mutex. Sorry, in the version that I downloaded the constructor of POSIXScopeMutex has no parameters at all and instead it *creates* and locks its own private mutex. In that form it is not useable, at least for synchronization. If you change the private mutex to the reference (or pointer), so that the whole class will only lock and unlock the given mutex (which has to be created outside), then OK. >>>4. The POSIXCondition class contains *both* the condvar and the mutex as >>>members. Is there any gain from doing this? Moreover, the wait() method >>>takes no parameters. How can I wait for some *condition* (instead of >>>just "signal") to take place? > > the pthreads standard only defined one type of conditional break-out > from a condition wait and that is a time-out. [...] > > The next level of condition aka boolean variants would be actually a > composite of threads and condition variables. The threads would be > doing the evaluation of the condition themselves i.e.: via a functor or > delegate methodology being fired, on a true result they fire signal or > broadcast. OK, so how can I do this with your class? Classic example: there is a queue and I want to wait until there is something in the queue, so that I can consume it. In Boost.Threads it would be something like this: queue myqueue; mutex mtx; condition cond; // ... { mutex::scoped_lock lck(mtx); while (myqueue.empty()) cond.wait(lck); // consume the element from the queue T t = myqueue.front(); myqueue.pop(); } (the code that add elements to the queue calls cond.notify_one()) What would be the equivalent code using your classes? >>>5. Coming back to the POSIXThread base class, it contains the static >>>member which is used as a thread start routine. This may not compile on >>>some platforms, since class members (even if static) cannot be made >>>extern "C". > > True to some extent. In any case my answer would be get a half decent > compiler. :) The fix would be much easier than changing compilers. ;) >>>I don't claim that this list is complete. ;) > > If you do think of any more, please feel free to tell me about them. In one of the examples you use unsynchronized volatile bool flag. This is not guaranteed to work. You also throw exceptions from destructors. In general, I think that the idea of using inheritance (with some Thread class as a base) is not what I would do in C++. This might be very subjective, of course. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ .