
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