Boost logo

Boost :

From: Bronek Kozicki (brok_at_[hidden])
Date: 2004-07-19 05:55:08


Howard Hinnant wrote:
> http://home.twcny.rr.com/hinnant/cpp_extensions/threads.html

I have number of comments:

* do we need distinction between "write_lock" and "scoped_lock"? After
all, both lock are:
  1. exclusive (in regard to ownership of "mutex" object)
  2. moveable (ie. have move semantics instead of copy semantics)

write_lock delivers some superset of functionality that scoped_lock does
not have, but do we need separate class for this functionality? After
all "if the client of scoped_lock<Mutex> does not use funtionality which
the Mutex does not supply, no harm is done". I understand that under
current proposal mutex class may deliver three separate families of lock
functions : lock, read_lock and write_lock, but I want you to consider
just two: lock (== exclusive == write) and shared_lock (== read). I
suggest that scoped_lock (another possible name "exclusive_lock") would
be move-constructible also from upgradable_shared_lock. If Mutex class
does not deliver member function
unlock_upgradable_shared_lock_exclusive , we would have compilation
error. Otherwise, no harm is done. The same applies to move-assignment
from upgradable_shared_lock (hm, some shorter name please?)

* I do not quite like
"write_lock(try_rvalue_ref<upgradable_read_lock<mutex_type> > r);"
(neither
"exclusive_lock(try_rvalue_ref<upgradable_shared_lock<mutex_type> >
r)" ). It seems inconsistent with rest of interface. What about
"write_lock (rvalue_ref<upgradable_read_lock<mutex_type> > r,
blocking_enum block_it);" ?

* mutex() memeber function may return void* instead of "const
mutex_type*". This will make it suitable just to check for equality of
owned mutex, while preventing any kind of mutex manipulation. Just an
idea, because "const" (which is already there) in most cases should
suffice.

* I'd still like to have number of free functions:

template <typename Mutex>
scoped_lock<Mutex> lock_mutex(Mutex); // or "acquire"

template <typename Mutex>
scoped_lock<Mutex> try_lock_mutex(Mutex); // nonblocking; or
"try_acquire"

template <typename Mutex>
scoped_lock<Mutex> try_lock_mutex(Mutex, const elapsed_time&); // or
"try_acquire"

These functions might look little different (eg. use enumerations
locking_enum and blocking_enum). The idea is that function will create
lock appropriate for given Mutex type - assuming that there migh be
Mutex-es delivered with their own lock class, or that.

* I'd like to have common base class over all lock classes. I do not
want polymorphic behaviour (all member functions might be protected,
including destructor, ctor and cctor), but to allow following very
simple and I believe typical usage scenarios:

(following typedef defined in library)
typedef common_lock_base& lock;

// scenario 1.
{
  lock l1 = lock_mutex(SomeMutex1);
}

// scenario 2.
if (lock l2 = try_lock_mutex(SomeMutex2, non_blocking))
{
  // great, we acquired SomeMutex2
}

In both scenarios we do not know what's actual type of SomeMutexX, and
functions will create appropriate lock type for type of SomeMutexX (this
is how I used my own very simple threading library).

Both points (free functions and common base class) are just ideas -
possibly we could live without it. My idea of threads interface was that
lock classes have much simpler interface, while we would have number of
free functions used to create them. Given amount of lock constructors in
proposed interface these free functions are just an addition.

About first point (IMHO unnecessary distinction between scoped_lock and
write_lock) - obviously I could be wrong, but at least I'd like to hear
that :)

B.

PS. I allowed myself to ask Kevlin Henney to evaluate this design; on
recent ACCU conference he presented number of ideas about threading
interfaces, see
http://www.accu.org/conference/presentations/Henney_-_More_C++_Threading.pdf


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk