
Hi, Phil Endecott schrieb:
I've mentioned something like this here a couple of times; did you see my Proto review? http://thread.gmane.org/gmane.comp.lib.boost.devel/171620
I've just taken a look at your proto review and to me it just asserts the usefulness of a lockable. The same goes for Frank's monitoring_ptr. My feeling is that some sort of type/mutex pairing and an expressive threadsafe access is desirable.
My feeling is that the basic Lockable<T> that pairs a mutex with the data that it locks is by itself too trivial for Boostification. Where it gets interesting is when you provide an interface to do automatic locking and unlocking, i.e. your locking pointer; I'd be interested to see some example usage for your version. In my case I found that the locking pointer (or locking reference) was actually more verbose than explicitly locking the mutex and accessing the data, so the only benefit is that the locking can be mandatory. But normally the only "enforcement" that I need is a comment: /* lock this before writing that */. Perhaps you have something more concise than I managed.
Well, you are right, a lockable<T> is a very trivial wrapper; however under the premise that I like encapsulation :) it does more than that: - it encapsulates a certain feature and gives it a (hopefully) sound name, still being generic - you can clearly express in a relatively easy technical way your intention that a variable should be accessed in a threadsafe manner. If I see a lockable eventually together with a lock_acquirer I immediately know that some threadsafe access is happening - a lockable<T> is easier to share with a shared_ptr<lockable<T>> between multiple threads and places of code than something else - transitive constness: no matter whether the lockable<T> is shared const (even if T is non-const) or T itself is const or the programmer requires read-only access, she only gets const-access to T (which doesn't mean that she gets non-const access to const T if she requires write access) - if lockable<T>'s T is only accessible through interface methods you can clearly see in which way you access T - encapsulation of volatile-ness: I don't know how important the volatile qualifier is for a lockable but since my lockable<T> stores T volatile and the proper interface methods and the lock_aqcuirer gives me non-volatile access I don't have to think so much about some type being volatile or not. Having read Andrei's article on ddj (btw: http://www.ddj.com/dept/cpp/184403766) I had the impression that the volatile qualifier is quite important. The lock_acquirer functions with lockables as well as with free-floating variables and mutexes. It's more a locking reference than a pointer; first I considered pointer semantics but it is even safer to have a protected friend template function (access_acquiree) that requires a named lock_acquirer object and that is only accessible by its unqualified name through ADL. Sure, the creation of a named lock_acquirer is quite verbose - I thought already of the c++09 auto typing feature together with RVO (return value optimization) like: auto some_lock = make_lock_acquirer(some_lockable); Still, to me the syntactic overhead seems worth the effort and might be solved by other ways yet to be found. Please have a look at my code, it can be found in the boost vault, name "thread_lockable.zip". The project contains a solution for msvc 2008 but should be easy to compile with any compiler. Klaus