JUCE
Public Member Functions | List of all members
MessageManagerLock Class Reference

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

Inheritance diagram for 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...
 

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;
const MessageManagerLock mmLock;
// 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

Constructor & Destructor Documentation

◆ MessageManagerLock() [1/2]

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]

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()

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

◆ lockWasGained()

bool MessageManagerLock::lockWasGained ( ) const
noexcept

Returns true if the lock was successfully acquired.

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

References Thread::Listener::exitSignalSent(), and JUCE_DECLARE_NON_COPYABLE.


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