![]() |
Boost : |
From: klaus triendl (klaus_at_[hidden])
Date: 2008-03-17 17:36:54
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
Boost list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk