Boost logo

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