Boost logo

Boost :

From: Jesse Jones (jejones_at_[hidden])
Date: 2000-08-08 19:32:47

>Here's a rough starting point for a mutex class.

I think there are two likely paths Boost can take when providing threading
classes. It can either provide a bare bones set of classes to allow
portable thread safe classes or it can provide portable classes for writing
multi-threaded code.

For the bare bones class it's questionable as to whether we need to share
the mutex between processes, have timeouts, or possibly even recursive
timeouts. And even if we decide to create a more comprehensive set of
classes it would arguably be better to have two mutex classes since it may
be possible to implement the primitive one more efficiently on some OS's.

Windows for example has three primary synchronization mechanisms:

1) Critical Sections are recursive, but don't have timeouts, and can't be
accessed from a different process. However, in the absence of contention,
they're very fast to lock.

2) Mutexes are like criticals sections but may have a timeout and can be
accessed from a different thread (eg by name).

3) Semaphores are like mutexes but also include a count.

The classs below looks like a good start, but in most cases it provides
more functionality and overhead than I need.

>class mutex
> // Should copying be allowed?
> mutex(const mutex&);
> operator=(const mutex&);

Maybe. I can imagine a thread safe wrapper around an STL container with the
STL container and a mutex as member data. It might be nice if the wrapper
could use the compiler provided copy ctor. But the new mutex shouldn't copy
the old mutex's locked state.

> // Creates a new mutex. If a name is specified the mutex
> // will be created in such a way that it's sharable between
> // processes. Should the sharable functionality be included?
> // Today this would require support from the platform, and
> // if the language were to adopt it it could be complicated
> // to include this on all platforms. However, the platforms
> // I'm familiar with would allow for this and it's almost an
> // essential quality for some constructs.
> mutex(char* name=0);

This should be a const pointer of course. Probably explicit as well. I also
would prefer a NULL instead of 0. :-) I'm a bit dubious about the notion of
the ctor being smart enough to create the correct OS object. To do this
right you also need to know if a timeout will be used with lock (and you
can't wait until lock to create the OS object because of race conditions).

Unless there's a relatively popular platform with threads, but in-process
only I'm inclined to think we should include the sharable functionality.

It might be worthwhile to allow for a mutex to start out locked. The idea
behind this is that other threads will be blocked allowing you to do some
additional initialization without worrying about race conditions.

> // Destoys the mutex.
> ~mutex();
> // Used to lock and unlock the mutex.
> class lock
> {
> public:
> lock(mutex& mx);
> // Throws an exception if timed out

What exception?

> lock(mutex& mx, int timeout);

Seconds? Milliseconds?

> ~lock();
> };
> // Locks the mutex. If already locked the thread enters a
> // suspended state until it can lock the mutex. Should this
> // be recursive?
> void do_lock();

Recursive sounds nice to me. :-)

> // Attempts to lock the mutex. If the mutex can not be
> // locked within the given time frame the result is false;
> // otherwise it's true.
> bool do_lock(int timeout);

This should just throw. That way implementors have at least a shot at using
any error codes returned by the OS.

> // Unlocks the mutex.
> void do_unlock();
> // Should we have an is_locked()? If so, does it report a
> // lock by any thread or only by the current thread?

Only if someone comes up with a good reason for having it.

  -- Jesse

Boost list run by bdawes at, gregod at, cpdaniel at, john at