Is there a way to test if my code is already holding a lock


#1

The same way I can test whether the current thread has locked the MessageManager with MessageManager::currentThreadHasLockedMessageManager (), is there a way to test whether the current thread is currently holding the lock to a generic CriticalSection?

The purpose is to trigger a jassert if one of my methods is being called while its caller is NOT holding the lock.


Calling setValueNotifyingHost() from processBlock()
#2

if (section.tryEnter())
{
section.exit();
jassertfalse;
}


#3

uhm, no, the case is more like that:

CriticalSection lock;

void function1 ()
{
lock.enter ();
function2 ();
lock.exit ();
}

void function2 ()
{
jassert (lock.isLockedByCurrentThread ());

... do other stuff

}

I want to be sure that function2 is being called only when the lock is hold by the current thread


#4

You can’t enter a critical section if it’s already entered.
So if tryEnter returns false, it’s because either the current thread has locked it, or another thread has locked it.
I don’t see the point in checking if it’s your thread that locked it or not, it looks like a bad design to me, IMHO.

You better write a private method with a name in “unlockedDoSomething” and a public “doSomething” that calls the former, so you’re sure it’s done automatically.

Anyway, if you want to know which thread locked the CS, you’ll have to write a class like this:

class MetaCS: public CriticalSection
{
public: 
    void enter() { CriticalSection::enter(); currentThreadId = getThreadId(); }
    bool tryEnter() { if (CriticalSection::tryEnter()) { currentThreadId = getThreadId(); return true; } return false; }
    void exit() { currentThreadId = 0; CriticalSection::exit(); }
    bool isLockedByCurrentThread() { return currentThreadId == getThreadId(); }     
};

#5

Something like that would be nice, but I think it’d require some research into whether such a function is possible using win32 and posix locks.


#6

I usually forbid people to use these kinds of “trick” because you’ll soon see code like this:

if (!lock.isLockedByCurrentThread()) 
     lock.enter();

[...]
// Now what ? exit or not ?

or even worse, like this: (try to spot the error on this one)

bool exitLock = false;
if (!lock.isLockedByCurrentThread())
{
     // This section should be locked
     jassertfalse;
     exitLock = true;
     lock.enter();
}

[...]

// Where's RAII ?
if (exitLock) lock.exit();

That kind of code become a mess when you have more than a lock. A lot nicer code would be:

class A
{
private:
   void doSomethingUnlocked() { [...] }
public:
    void doSomething() { ScopedLock scope(lock); doSomethingUnlocked(); }
}

#7

Hmm, good point. Sadly people probably would use it to write crap like that, and that’s a very good reason not to provide it!