JUCE  v5.4.1-191-g0ab5e696f
JUCE API
Looking for a senior C++ dev?
I'm looking for work. Hire me!
juce::MessageManagerLock Class Reference

Used to make sure that the calling thread has exclusive access to the message loop. More...

#include <juce_MessageManager.h>

Inheritance diagram for juce::MessageManagerLock:
Collaboration diagram for juce::MessageManagerLock:

Public Member Functions

 MessageManagerLock (Thread *threadToCheckForExitSignal=nullptr)
 Tries to acquire a lock on the message manager. More...
 
 MessageManagerLock (ThreadPoolJob *jobToCheckForExitSignal)
 This has the same behaviour as the other constructor, but takes a ThreadPoolJob instead of a thread. More...
 
 ~MessageManagerLock () override
 Releases the current thread's lock on the message manager. More...
 
bool lockWasGained () const noexcept
 Returns true if the lock was successfully acquired. More...
 

Private Member Functions

bool attemptLock (Thread *, ThreadPoolJob *)
 
void exitSignalSent () override
 Called if Thread::signalThreadShouldExit was called. More...
 

Private Attributes

bool locked
 
MessageManager::Lock mmLock
 

Detailed Description

Used to make sure that the calling thread has exclusive access to the message loop.

Because it's not thread-safe to call any of the Component or other UI classes from threads other than the message thread, one of these objects can be used to lock the message loop and allow this to be done. The message thread will be suspended for the lifetime of the MessageManagerLock object, so create one on the stack like this:

void MyThread::run()
{
someData = 1234;
// the event loop will now be locked so it's safe to make a few calls..
myComponent->setBounds (newBounds);
myComponent->repaint();
// ..the event loop will now be unlocked as the MessageManagerLock goes out of scope
}

Obviously be careful not to create one of these and leave it lying around, or your app will grind to a halt!

MessageManagerLocks are re-entrant, so can be safely nested if the current thread already has the lock.

Another caveat is that using this in conjunction with other CriticalSections can create lots of interesting ways of producing a deadlock! In particular, if your message thread calls stopThread() for a thread that uses these locks, you'll get an (occasional) deadlock..

See also
MessageManager, MessageManager::currentThreadHasLockedMessageManager

{Events}

Constructor & Destructor Documentation

◆ MessageManagerLock() [1/2]

juce::MessageManagerLock::MessageManagerLock ( Thread threadToCheckForExitSignal = nullptr)

Tries to acquire a lock on the message manager.

The constructor attempts to gain a lock on the message loop, and the lock will be kept for the lifetime of this object.

Optionally, you can pass a thread object here, and while waiting to obtain the lock, this method will keep checking whether the thread has been given the Thread::signalThreadShouldExit() signal. If this happens, then it will return without gaining the lock. If you pass a thread, you must check whether the lock was successful by calling lockWasGained(). If this is false, your thread is being told to die, so you should take evasive action.

If you pass nullptr for the thread object, it will wait indefinitely for the lock - be careful when doing this, because it's very easy to deadlock if your message thread attempts to call stopThread() on a thread just as that thread attempts to get the message lock.

If the calling thread already has the lock, nothing will be done, so it's safe and quick to use these locks recursively.

E.g.

void run()
{
...
while (! threadShouldExit())
{
if (! mml.lockWasGained())
return; // another thread is trying to kill us!
..do some locked stuff here..
}
..and now the MM is now unlocked..
}

◆ MessageManagerLock() [2/2]

juce::MessageManagerLock::MessageManagerLock ( ThreadPoolJob jobToCheckForExitSignal)

This has the same behaviour as the other constructor, but takes a ThreadPoolJob instead of a thread.

See the MessageManagerLock (Thread*) constructor for details on how this works.

◆ ~MessageManagerLock()

juce::MessageManagerLock::~MessageManagerLock ( )
override

Releases the current thread's lock on the message manager.

Make sure this object is created and deleted by the same thread, otherwise there are no guarantees what will happen!

Member Function Documentation

◆ attemptLock()

bool juce::MessageManagerLock::attemptLock ( Thread ,
ThreadPoolJob  
)
private

◆ exitSignalSent()

void juce::MessageManagerLock::exitSignalSent ( )
overrideprivatevirtual

◆ lockWasGained()

bool juce::MessageManagerLock::lockWasGained ( ) const
inlinenoexcept

Returns true if the lock was successfully acquired.

(See the constructor that takes a Thread for more info).

Member Data Documentation

◆ locked

bool juce::MessageManagerLock::locked
private

◆ mmLock

MessageManager::Lock juce::MessageManagerLock::mmLock
private

The documentation for this class was generated from the following file: