Used to make sure that the calling thread has exclusive access to the message loop. More...
#include <juce_MessageManager.h>
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 |
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:
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..
@tags{Events}
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.
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.
|
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!
|
private |
|
overrideprivatevirtual |
Called if Thread::signalThreadShouldExit was called.
Implements juce::Thread::Listener.
|
inlinenoexcept |
Returns true if the lock was successfully acquired.
(See the constructor that takes a Thread for more info).
|
private |
|
private |