
Christopher Currie wrote:
Michael Glassford wrote:
Christopher Currie wrote:
TryLock: What would be the semantics of l(m, NO_LOCK, b)? In other words, if you're not going to lock on construction, why specify a blocking policy?
The only reason is so that if you write l(m, LOCK, ...) you could also specify the blocking parameter. An expansion of Vladimir Batov's of using structs rather than enums could help here:
struct nolock_t {}; nolock_t nolock;
struct lock_t {}; lock_t lock;
class TryLock { TryLock(TryMutex m, no_lock_t s) {...}
TryLock(TryMutex m, lock_t s, blocking_t b) {...} }
An interesting syntax, I can see how it does make explicit whether you are locking or not. Personally, I dislike having to type an extra argument when it's the only choice; IMO if you're specifying a blocking parameter, the locking is implied, and therefore superfluous.
That was an oversight on my part. Though in the case of read/write locks, you do need to specify both the lock type (read/write) and whether it is blocking or not.
I was thinking something like (going back to enums for a moment):
enum { unlocked = 0, locked } lock_init; enum { nonblocking = 0, blocking } blocking_action;
class TryLock { public: TryLock( TryMutex m, lock_init s = locked ) { ... }
TryLock( TryMutex m, blocking_action b ) { ... } };
Also, going back to the struct technique, do the struct instances need to be in an anonymous namespace to prevent ODR violations? Just trying to get my head around the concept.
Probably they should be in a separate namespace, though possibly not anonymous. Mike