$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: William E. Kempf (williamkempf_at_[hidden])
Date: 2002-05-17 13:05:35
----- Original Message -----
From: "Eric D Crahen" <crahen_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Friday, May 17, 2002 12:23 PM
Subject: [boost] Re: Boost.Threads Locking Delima (William E. Kempf)
>
> Couldn't a simple policy based template be used instead of move
> semantics? The syntax is almost identical, and the flow of the
> code is easier to follow without the ownership issues. All I did
> was to make the behavioral-scope of the lock be controlled by a
> boolean rather than by the lifetime of the template that encapusaltes
> it; so it can end prematurety to deal with overlapped locks.
>
> I modified the template I've been using in my thread library to
> demonstrate this. I've been calling it Guard, which seems even
> more appropriate now in the sense that scopes by nature are nested
> things and don't overlap.
>
>
> // Example code
>
> // Policy for acquire then release
> class ForwardLocking {
> public:
>
> template <class LockType>
> static void acquire(LockType& lock) { lock.acquire(); }
>
> template <class LockType>
> static void release(LockType& lock) { lock.release(); }
>
> };
>
> // Policy for release then acquire
> class BackwardsLocking {
> public:
>
> template <class LockType>
> static void acquire(LockType& lock) { lock.release(); }
>
> template <class LockType>
> static void release(LockType& lock) { lock.acquire(); }
>
> };
>
> // Guard/ScopedLock template
> template <class LockType, class Strategy = ForwardLocking>
> class Guard : protected Strategy {
>
> LockType& _lock;
> volatile bool _active; // control the behavioral scope
>
> public:
>
> // Overlapped scopes
> template <class Y, class Z>
> Guard(Guard<Y, Z>& guard, LockType& lock) : _lock(lock), _active(true) {
> acquire();
> guard.release();
> }
This doesn't transfer ownership of a lock across scopes. It overlaps locks
on two different mutexes (where you use LockType Boost.Threads uses Mutex...
locks are not mutexes but are locks on a mutex).
> // Nested or non-nested scopes
> Guard(LockType& lock) : _lock(lock), _active(true) {
> acquire();
> }
>
> ~Guard() {
> release();
> }
>
> private:
>
> // Acquire the lock, activate the scope
> void acquire() {
> _active = true;
> Strategy::acquire(_lock);
> }
>
> // Release the lock, deactivate the scope
> void release() {
>
> if(_active) {
>
> Strategy::release(_lock);
> _active = false;
>
> }
>
> }
>
> };
>
> //
> // Example usage
> //
>
> void aFunction() {
>
> Mutex mtx1, mtx2;
>
> Guard<Mutex> g1(mtx1);
>
> // mtx1 locked
>
> { // Nested scope
>
> Guard<Mutex, BackwardsLocking> g2(mtx1);
>
> // mtx1 unlocked
>
> }
>
> // mtx1 locked
>
> // overlapped scopes, move from g1's scope to a new one
> Guard<Mutex> g3(g1, mtx2);
>
> // mtx1 unlocked, mtx2 locked
>
> }
>
>
> This is just a quick implementation, but is there anything that move
> semantics would allow that you can't accomplish with a template like
> this (or along these lines anyways)? I think something like this may
> be a little easier to understand and use.
As I said above, this doesn't allow us to transfer a lock out of one scope
and into another, it only allows overlapped locks, and I think Boost.Threads
has a better solution for this today. Read Bjarne's article I posted in the
first message in this thread and try to implement a locking_ptr<> using
either the current Boost.Threads ScopedLocks or the above Guard to see
precisely where the problem lies.
Bill Kempf