|
Boost : |
From: Jeff Paquette (paquette_at_[hidden])
Date: 2000-08-08 15:52:30
See below...
-- Jeff Paquette paquette at mediaone.net http://www.atnetsend.net > -----Original Message----- > From: William Kempf [mailto:sirwillard_at_[hidden]] > Sent: Tuesday, August 08, 2000 4:36 PM > To: boost_at_[hidden] > Subject: [boost] Re: Threads: what I wrote... > > > --- In boost_at_[hidden], Dietmar Kuehl <dietmar_kuehl_at_y...> wrote: > > Hi, > > > > --- William Kempf <sirwillard_at_m...> wrote: > > > --- In boost_at_[hidden], scleary_at_j... wrote: > > > > > > IMO, pthreads is a good example of object-oriented C. Object = > > > data + > > > > related functions -> pthread_mutex_t + pthread_mutex_init, > > > > pthread_mutex_destroy, pthread_mutex_lock, ... > > > > > > Agreed, but this all implies too many restrictions on the OO > model. > > > The simplest example to give in this regard is the requirement > that > > > the thread creation routines take a function pointer and a void > > > pointer as arguments. > > > > I disagree with this being a restriction: This can be used to > implement > > whatever design we choose, including a base class with an overriden > > function being started. The function pointer used is internal to the > > implementation. Here is a potential implementation: > > > > extern "C" void* run_thread(void*); > > > > struct thread { > > void run() { > > if (pthread_create(&m_thread, &m_attr, run_tread ,this)) > > throw "thread could not be created!"; > > } > > // ... > > > > private: > > friend void* thread_run(void*); > > virtual int do_run() = 0; > > > > pthread_t m_thread; > > pthread_attr_t m_attr; > > }; > > > > void* run_thread(void* obj) { > > pthread_exit(static_cast<thread*>(obj)->do_run()); > > return 0; > > } > > > > With something like this, we have objects to be run and can easily > > create derived functions calling whatever kind of function object we > > want to call. ... and the pthreads interface is not at all > visible. > > This is the "thin wrapper" that I dislike. Now we must derive from > thread (or in other implementation, derive from runnable or some > other suitably named secondary class) in order to be an "active > object" and the active object is the only form of thread routine > available. A thread creation routine that truly took C++ into > consideration would allow you to create a thread from any function or > any member function or even from some arbitrary functor. As the > caller I should be able to supply what ever arguments I want to to > the "routine" that runs in the thread. The C callback approach isn't > really appropriate in C++. Instead, think "slots for threads". I agree. Thread creation should not be limited to derived classes. > > > > In fact, the related functions map so well to member functions > that > > > > a wrapper class can be written almost without thought (error > > > > checking ommitted, but can be easily added): > > > > class mutex { > > > > private: > > > > pthread_mutex_t me; > > > > mutex(const mutex &); > > > > void operator=(const mutex &); > > > > public: > > > > mutex() { pthread_mutex_init(&me, 0); } > > > > ~mutex() { pthread_mutex_destroy(&me); } > > > > void lock() { pthread_mutex_lock(&me); } > > > > void unlock() { pthread_mutex_unlock(&me); } > > > > bool trylock() { return !pthread_mutex_trylock(&me); } > > > > }; > > > > This is the kind of interfaces I want to avoid! You can lock the > mutex > > without automatic release. This wrapper is clearly too thin. > > It's not a bad interface, and is in fact the proper starting point. > However, the lock and unlock routines probably should be private and > a nested class would be used to lock/unlock the mutex with "auto_ptr > like" semantics. This would likely mean that the "trylock" > functionality would need to throw an exception since we'd be using c- > tor/d-tor pairs to lock and unlock the mutex. > > > > Is it possible to copy a mutex class? > > > > This was taken care of: The copy ctor and assignment are declared to > > be private and thus these objects can neither be copied nor > assigned. > > I've got egg on my face. I looked specifically to see if he'd > addressed this issue and missed it! Time to clean my glasses off. > > > This is, IMO, the right semantics. Possible, there could be > function to > > copy attributes like there is for IOStreams ('copyfmt()') to create > a > > mutex with identical attributes or to safe the attributes to be > > restored later but I don't think mutex can be copied. > > I'm not sure I agree here. If the mutex isn't copyable this means > that any class that contains a mutex (to handle internal > synchronization) then the class is either not copyable or code must > be supplied within every such class to deal with the issue. Copy > semantics here have a lot of pros and cons and I think they'll need a > bit of discussion. > This would depend on the type of mutex. A recursive-mutex should allow copying, while a single-lock mutex should only be copied if it is not currently locked. And as for the other thread discussion...is boost's goal to write a library that would be implemented for each platform that supports threading, thus supplying a sorely-needed portable interface or to write a threading library that would implement a scheduler as well as the locking primitives?
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk