|
Boost : |
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk