26 MessageManager::MessageManager() noexcept
27 : messageThreadId (Thread::getCurrentThreadId())
33 MessageManager::~MessageManager() noexcept
37 doPlatformSpecificShutdown();
39 jassert (instance ==
this);
43 MessageManager* MessageManager::instance =
nullptr;
47 if (instance ==
nullptr)
50 doPlatformSpecificInitialisation();
63 deleteAndZero (instance);
67 bool MessageManager::MessageBase::post()
69 auto* mm = MessageManager::instance;
71 if (mm ==
nullptr || mm->quitMessagePosted.get() != 0 || ! postMessageToSystemQueue (
this))
81 #if JUCE_MODAL_LOOPS_PERMITTED && ! (JUCE_MAC || JUCE_IOS) 88 while (quitMessageReceived.
get() == 0)
92 if (! dispatchNextMessageOnSystemQueue (millisecondsToRunFor >= 0))
101 return quitMessageReceived.
get() == 0;
105 #if ! (JUCE_MAC || JUCE_IOS || JUCE_ANDROID) 111 void messageCallback()
override 113 if (
auto* mm = MessageManager::instance)
114 mm->quitMessageReceived =
true;
117 JUCE_DECLARE_NON_COPYABLE (QuitMessage)
124 while (quitMessageReceived.get() == 0)
128 if (! dispatchNextMessageOnSystemQueue (
false))
137 (
new QuitMessage())->post();
138 quitMessagePosted =
true;
148 : func (f), parameter (param)
151 void messageCallback()
override 153 result = (*func) (parameter);
158 std::atomic<void*> result {
nullptr };
161 MessageCallbackFunction*
const func;
162 void*
const parameter;
170 return func (parameter);
179 message->finished.wait();
180 return message->result.load();
191 AsyncCallInvoker (std::function<
void()> f) : callback (std::move (f)) {}
192 void messageCallback()
override { callback(); }
193 std::function<void()> callback;
196 return (
new AsyncCallInvoker (std::move (fn)))->post();
200 void MessageManager::deliverBroadcastMessage (
const String& value)
202 if (broadcaster !=
nullptr)
203 broadcaster->sendActionMessage (value);
208 if (broadcaster ==
nullptr)
211 broadcaster->addActionListener (listener);
216 if (broadcaster !=
nullptr)
217 broadcaster->removeActionListener (listener);
230 if (messageThreadId != thisThread)
232 messageThreadId = thisThread;
235 doPlatformSpecificShutdown();
236 doPlatformSpecificInitialisation();
243 return thisThread == messageThreadId || thisThread == threadWithLock.get();
249 return i->currentThreadHasLockedMessageManager();
257 return i->isThisTheMessageThread();
279 void messageCallback()
override 284 if (
auto* o = owner.get())
285 o->messageCallback();
304 bool MessageManager::Lock::tryAcquire (
bool lockIsMandatory)
const noexcept
306 auto* mm = MessageManager::instance;
314 if (! lockIsMandatory && (abortWait.get() != 0))
320 if (mm->currentThreadHasLockedMessageManager())
329 jassert (! lockIsMandatory);
333 if (! blockingMessage->post())
336 jassert (! lockIsMandatory);
337 blockingMessage =
nullptr;
343 while (abortWait.get() == 0)
344 lockedEvent.wait (-1);
348 if (lockGained.get() != 0)
354 }
while (lockIsMandatory);
357 blockingMessage->releaseEvent.signal();
360 ScopedLock lock (blockingMessage->ownerCriticalSection);
363 blockingMessage->owner.set (
nullptr);
366 blockingMessage =
nullptr;
372 if (lockGained.compareAndSetBool (
false,
true))
374 auto* mm = MessageManager::instance;
376 jassert (mm ==
nullptr || mm->currentThreadHasLockedMessageManager());
380 mm->threadWithLock = {};
382 if (blockingMessage !=
nullptr)
384 blockingMessage->releaseEvent.signal();
385 blockingMessage =
nullptr;
390 void MessageManager::Lock::messageCallback()
const 399 lockedEvent.signal();
404 : locked (attemptLock (threadToCheck, nullptr))
408 : locked (attemptLock (nullptr, jobToCheck))
413 jassert (threadToCheck ==
nullptr || jobToCheck ==
nullptr);
415 if (threadToCheck !=
nullptr)
418 if (jobToCheck !=
nullptr)
423 && (jobToCheck ==
nullptr || ! jobToCheck->
shouldExit()))
429 if (threadToCheck !=
nullptr)
437 if (jobToCheck !=
nullptr)
450 void MessageManagerLock::exitSignalSent()
456 JUCE_API void JUCE_CALLTYPE initialiseJuce_GUI();
457 JUCE_API void JUCE_CALLTYPE initialiseJuce_GUI()
465 JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI();
466 JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI()
475 static int numScopedInitInstances = 0;
void * callFunctionOnMessageThread(MessageCallbackFunction *callback, void *userData)
Calls a function using the message-thread.
A simple wrapper around std::atomic.
#define JUCE_API
This macro is added to all JUCE public class declarations.
Interface class for delivery of events that are sent by an ActionBroadcaster.
bool currentThreadHasLockedMessageManager() const noexcept
Returns true if the caller thread has currently got the message manager locked.
static bool existsAndIsCurrentThread() noexcept
Returns true if there's an instance of the MessageManager, and if the current thread is running it...
void setCurrentThreadAsMessageThread()
Called to tell the manager that the current thread is the one that's running the dispatch loop...
void exit() const noexcept
Releases the message manager lock.
void addListener(Listener *)
Add a listener to this thread which will receive a callback when signalThreadShouldExit was called on...
void removeListener(Thread::Listener *)
Removes a listener added with addListener.
static void deleteAll()
Deletes all extant objects.
ScopedJuceInitialiser_GUI()
The constructor simply calls initialiseJuce_GUI().
Allows threads to wait for events triggered by other threads.
static MessageManager * getInstance()
Returns the global instance of the MessageManager.
This class is in charge of the application's event-dispatch loop.
Lock()
Creates a new critical section to exclusively access methods which can only be called when the messag...
bool runDispatchLoopUntil(int millisecondsToRunFor)
Synchronously dispatches messages until a given time has elapsed.
void stopDispatchLoop()
Sends a signal that the dispatch loop should terminate.
static int64 currentTimeMillis() noexcept
Returns the current system time.
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
Returns an id that identifies the caller thread.
void runDispatchLoop()
Runs the event dispatch loop until a stop message is posted.
bool isThisTheMessageThread() const noexcept
Returns true if the caller-thread is the message thread.
~MessageManagerLock() override
Releases the current thread's lock on the message manager.
bool threadShouldExit() const
Checks whether the thread has been told to stop running.
MessageManagerLock(Thread *threadToCheckForExitSignal=nullptr)
Tries to acquire a lock on the message manager.
void enter() const noexcept
Acquires the message manager lock.
void addListener(Thread::Listener *)
Add a listener to this thread job which will receive a callback when signalJobShouldExit was called o...
void registerBroadcastListener(ActionListener *listener)
Registers a listener to get told about broadcast messages.
static void deleteInstance()
Deletes the global MessageManager instance.
~ScopedJuceInitialiser_GUI()
The destructor simply calls shutdownJuce_GUI().
Type get() const noexcept
Atomically reads and returns the current value.
static bool existsAndIsLockedByCurrentThread() noexcept
Returns true if there's an instance of the MessageManager, and if the current thread has the lock on ...
bool tryEnter() const noexcept
Attempts to lock the message manager and exits if abort is called.
A smart-pointer class which points to a reference-counted object.
static void JUCE_CALLTYPE sleep(int milliseconds)
Suspends the execution of the current thread until the specified timeout period has elapsed (note tha...
A task that is executed by a ThreadPool object.
static bool callAsync(std::function< void()> functionToCall)
Asynchronously invokes a function or C++11 lambda on the message thread.
static MessageManager * getInstanceWithoutCreating() noexcept
Returns the global instance of the MessageManager, or nullptr if it doesn't exist.
Automatically locks and unlocks a mutex object.
void deregisterBroadcastListener(ActionListener *listener)
Deregisters a broadcast listener.
void abort() const noexcept
Unblocks a thread which is waiting in tryEnter Call this method if you want to unblock a thread which...
void removeListener(Listener *)
Removes a listener added with addListener.
static bool isStandaloneApp() noexcept
Returns true if this executable is running as an app (as opposed to being a plugin or other kind of s...
Manages a list of ActionListeners, and can send them messages.
Internal class used as the base class for all message objects.
static void JUCE_CALLTYPE setCurrentThreadName(const String &newThreadName)
Changes the name of the caller thread.
bool shouldExit() const noexcept
Returns true if something is trying to interrupt this job and make it stop.
A lock you can use to lock the message manager.