JUCE  v5.1.1-3-g1a0b28c73
JUCE API
MessageManagerLock Class Reference

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

#include <juce_MessageManager.h>

Collaboration diagram for MessageManagerLock:

Classes

struct  BailOutChecker
 
struct  ThreadChecker
 

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 (BailOutChecker &)
 This is an abstraction of the other constructors. More...
 
 ~MessageManagerLock () noexcept
 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 (BailOutChecker *)
 

Private Attributes

ReferenceCountedObjectPtr< BlockingMessage > blockingMessage
 
ThreadChecker checker
 
bool locked
 

Friends

class ReferenceCountedObjectPtr< BlockingMessage >
 

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/3]

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/3]

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() [3/3]

MessageManagerLock::MessageManagerLock ( BailOutChecker )

This is an abstraction of the other constructors.

You can pass this constructor a functor which is periodically checked if attempting the lock should be aborted.

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

◆ ~MessageManagerLock()

MessageManagerLock::~MessageManagerLock ( )
noexcept

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 MessageManagerLock::attemptLock ( BailOutChecker )
private

◆ lockWasGained()

bool MessageManagerLock::lockWasGained ( ) const
inlinenoexcept

Returns true if the lock was successfully acquired.

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

Friends And Related Function Documentation

◆ ReferenceCountedObjectPtr< BlockingMessage >

friend class ReferenceCountedObjectPtr< BlockingMessage >
friend

Member Data Documentation

◆ blockingMessage

ReferenceCountedObjectPtr<BlockingMessage> MessageManagerLock::blockingMessage
private

◆ checker

ThreadChecker MessageManagerLock::checker
private

◆ locked

bool MessageManagerLock::locked
private

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