The object can be locked two different ways, where if the lock is entered the same way a second time, the lock is recursive, but if it's entered the other way, it blocks. Like a reader-writer lock, but symmetric.
In case the text isn't clear, this code should be clear. Beware of bugs. I've only proved it correct, I haven't actually used it yet.
struct mylock {
pthread_mutex_t entry;
pthread_mutex_t manager;
pthread_mutex_t core;
int counter;
int state;
}
void mylock_acquire(struct mylock *lock, int state)
{
assert(state != 0);
pthread_mutex_lock(&lock->entry);
if (lock->state != state) {
pthread_mutex_lock(&lock->core);
lock->state = state;
}
pthread_mutex_lock(&lock->manager);
++lock->counter;
pthread_mutex_unlock(&lock->manager);
pthread_mutex_unlock(&lock->entry);
}
void mylock_release(struct mylock *lock)
{
pthread_mutex_lock(&lock->manager);
if (--lock->counter == 0) {
lock->state = 0;
pthread_mutex_unlock(&lock->core);
}
pthread_mutex_unlock(&lock->manager);
}
This is exactly the same as reader-writer, right down to there being exactly two classes of lock holder, except that the "writer" side is also multi-entry. So I took the core reader-writer code I learned two decades ago and converted it from P-V notation to mutexes and made both sides use the reader-type logic. ratchet freak did catch that it's no longer allowed to unlock a mutex from another thread anymore.
The actual code is different due to using atomic operations, but that complicates the question too much. The sample code is designed to illustrate the lock structure as simply as possible.
If I call up the Debian man page for pthread_mutex_unlock it actually says you can unlock from another thread ("If the mutex is of the "fast" kind, pthread_mutex_unlock
always returns it to the unlocked state."), but ratchet freak has pointed out this isn't portable.
What is the name of this kind of lock? If it has a name, it would be helpful for documenting the thing.