
Michael Glassford wrote:
Eric Niebler wrote:
How about:
if( ScopedLock l = try_lock( m ) ) { }
where try_lock is function that returns a simple wrapper class:
template< Mutex > struct try_locker { Mutex & m; ... };
template< Mutex > try_locker< Mutex > try_lock( Mutex & m ) { return try_locker< Mutex >( m ); };
and ScopedLock is some lockable type which has a constructor that accepts a try_locker. (It would also need a bool-ish conversion to allow the lock to be declared in the "if" statement, but that's not relevant to this discussion.)
Interesting idea. I suppose you could even do this:
if (ScopedLock l(m, locker())) { }
where locker() is a function object that defines
operator()(LockType& l)
which the lock calls in the constructor, passing *this. You could have locker(), try_locker(), timed_locker(t), etc.
Not quite. In order to declare and initialize a variable in an "if" statement, you need to use the "if( type var = fun() )" form, where the "=" is necessary. I realize that the code I posted before is incompatible with the requirement that ScopedLock be non-copyable. Below is an interesting variation which works around the problem. It defines a single type "lock" which is non-copyable, yet it can be returned by value from a function. (This may or may not be desirable for a lock class, but it's interesting.) struct lock; lock try_lock(); struct lock_ref { lock_ref(lock & ref) : ref_(ref) { } lock & ref_; }; struct lock { lock(lock_ref ref){} operator lock_ref() { // ... move the lock ... return lock_ref(*this); } operator bool() const { // TODO return true iff we're holding the lock return true; } private: friend lock try_lock(); lock(/*params*/){} // a try-lock c'tor // make this type non-copyable, non-assignable lock(lock &); lock & operator=(lock &); }; inline lock try_lock(/*params*/) { // call a special try-lock c'tor on lock return lock(/*params*/); } int main() { if( lock l = try_lock(/*params*/) ) {} } The idea is to have just one lock class (leaving aside read/write locks) and a collection of factory functions like try_lock(), timed_lock(), defered_lock() etc. Those functions create a lock object by calling the appropriate (private) constructor and returning the new lock object. (Some fancy auto_ptr-like move shenanigans are needed to make the lock return-able but not copy-able.) I'm not really advocating this design. I'm not close enough to this problem to have a strong preference. Just offering it as an alternative. -- Eric Niebler Boost Consulting www.boost-consulting.com