26MessageManager::MessageManager() noexcept
27 : messageThreadId (
Thread::getCurrentThreadId())
35MessageManager::~MessageManager() noexcept
39 doPlatformSpecificShutdown();
41 jassert (instance ==
this);
49 if (instance ==
nullptr)
51 instance =
new MessageManager();
52 doPlatformSpecificInitialisation();
65 deleteAndZero (instance);
69bool MessageManager::MessageBase::post()
71 auto* mm = MessageManager::instance;
73 if (mm ==
nullptr || mm->quitMessagePosted.get() != 0 || ! postMessageToSystemQueue (
this))
83#if ! (JUCE_MAC || JUCE_IOS || JUCE_ANDROID)
87bool dispatchNextMessageOnSystemQueue (
bool returnIfNoPendingMessages);
90class MessageManager::QuitMessage final :
public MessageManager::MessageBase
95 void messageCallback()
override
97 if (
auto* mm = MessageManager::instance)
98 mm->quitMessageReceived =
true;
101 JUCE_DECLARE_NON_COPYABLE (QuitMessage)
108 while (quitMessageReceived.get() == 0)
112 if (! detail::dispatchNextMessageOnSystemQueue (
false))
121 (
new QuitMessage())->post();
122 quitMessagePosted =
true;
125#if JUCE_MODAL_LOOPS_PERMITTED
126bool MessageManager::runDispatchLoopUntil (
int millisecondsToRunFor)
132 while (quitMessageReceived.
get() == 0)
136 if (! detail::dispatchNextMessageOnSystemQueue (millisecondsToRunFor >= 0))
145 return quitMessageReceived.get() == 0;
152class AsyncFunctionCallback final :
public MessageManager::MessageBase
155 AsyncFunctionCallback (MessageCallbackFunction*
const f,
void*
const param)
156 : func (f), parameter (param)
159 void messageCallback()
override
161 result = (*func) (parameter);
165 WaitableEvent finished;
166 std::atomic<void*> result {
nullptr };
169 MessageCallbackFunction*
const func;
170 void*
const parameter;
172 JUCE_DECLARE_NON_COPYABLE (AsyncFunctionCallback)
178 return func (parameter);
187 message->finished.wait();
188 return message->result.load();
199 AsyncCallInvoker (std::function<
void()> f) : callback (std::move (f)) {}
200 void messageCallback()
override { callback(); }
201 std::function<void()> callback;
204 return (
new AsyncCallInvoker (std::move (fn)))->post();
208void MessageManager::deliverBroadcastMessage (
const String& value)
210 if (broadcaster !=
nullptr)
211 broadcaster->sendActionMessage (value);
216 if (broadcaster ==
nullptr)
219 broadcaster->addActionListener (listener);
224 if (broadcaster !=
nullptr)
225 broadcaster->removeActionListener (listener);
231 const std::lock_guard<std::mutex> lock { messageThreadIdMutex };
240 const std::lock_guard<std::mutex> lock { messageThreadIdMutex };
242 if (std::exchange (messageThreadId, thisThread) != thisThread)
246 doPlatformSpecificShutdown();
247 doPlatformSpecificInitialisation();
255 return thisThread == messageThreadId || thisThread == threadWithLock.get();
261 return i->currentThreadHasLockedMessageManager();
269 return i->isThisTheMessageThread();
290 void messageCallback()
override
292 std::unique_lock lock { mutex };
294 if (owner !=
nullptr)
295 owner->setAcquired (
true);
297 condvar.wait (lock, [&] {
return owner ==
nullptr; });
302 const ScopeGuard scope { [&] { condvar.notify_one(); } };
303 const std::scoped_lock lock { mutex };
309 std::condition_variable condvar;
311 const MessageManager::Lock* owner =
nullptr;
313 JUCE_DECLARE_NON_COPYABLE (BlockingMessage)
322bool MessageManager::Lock::exclusiveTryAcquire (
bool lockIsMandatory)
const noexcept
326 else if (! entryMutex.tryEnter())
329 const auto result = tryAcquire (lockIsMandatory);
337bool MessageManager::Lock::tryAcquire (
bool lockIsMandatory)
const noexcept
339 auto* mm = MessageManager::instance;
347 if (! lockIsMandatory && [&]
349 const std::scoped_lock lock { mutex };
350 return std::exchange (abortWait,
false);
356 if (mm->currentThreadHasLockedMessageManager())
361 blockingMessage = *
new BlockingMessage (
this);
365 jassert (! lockIsMandatory);
369 if (! blockingMessage->post())
372 jassert (! lockIsMandatory);
373 blockingMessage =
nullptr;
380 std::unique_lock lock { mutex };
381 condvar.wait (lock, [&] {
return std::exchange (abortWait,
false); });
390 if (! lockIsMandatory)
396 blockingMessage->stopWaiting();
397 blockingMessage =
nullptr;
403 const auto wasAcquired = [&]
405 const std::scoped_lock lock { mutex };
412 const ScopeGuard unlocker { [&] { entryMutex.exit(); } };
414 if (blockingMessage ==
nullptr)
417 if (
auto* mm = MessageManager::instance)
419 jassert (mm->currentThreadHasLockedMessageManager());
420 mm->threadWithLock = {};
423 blockingMessage->stopWaiting();
424 blockingMessage =
nullptr;
433void MessageManager::Lock::setAcquired (
bool x)
const noexcept
435 const ScopeGuard scope { [&] { condvar.notify_one(); } };
436 const std::scoped_lock lock { mutex };
443 : locked (attemptLock (threadToCheck, nullptr))
447 : locked (attemptLock (nullptr, jobToCheck))
452 jassert (threadToCheck ==
nullptr || jobToCheck ==
nullptr);
454 if (threadToCheck !=
nullptr)
457 if (jobToCheck !=
nullptr)
462 && (jobToCheck ==
nullptr || ! jobToCheck->
shouldExit()))
468 if (threadToCheck !=
nullptr)
476 if (jobToCheck !=
nullptr)
495JUCE_API
void JUCE_CALLTYPE initialiseJuce_GUI()
503JUCE_API
void JUCE_CALLTYPE shutdownJuce_GUI()
512static int numScopedInitInstances = 0;
static bool isStandaloneApp() noexcept
~MessageManagerLock() override
MessageManagerLock(Thread *threadToCheckForExitSignal=nullptr)
void enter() const noexcept
void abort() const noexcept
bool tryEnter() const noexcept
void exit() const noexcept
static bool callAsync(std::function< void()> functionToCall)
bool isThisTheMessageThread() const noexcept
static bool existsAndIsCurrentThread() noexcept
bool currentThreadHasLockedMessageManager() const noexcept
void * callFunctionOnMessageThread(MessageCallbackFunction *callback, void *userData)
void deregisterBroadcastListener(ActionListener *listener)
void setCurrentThreadAsMessageThread()
static bool existsAndIsLockedByCurrentThread() noexcept
void registerBroadcastListener(ActionListener *listener)
static void deleteInstance()
static MessageManager * getInstanceWithoutCreating() noexcept
static MessageManager * getInstance()
~ScopedJuceInitialiser_GUI()
ScopedJuceInitialiser_GUI()
void addListener(Thread::Listener *)
bool shouldExit() const noexcept
void removeListener(Thread::Listener *)
virtual void exitSignalSent()=0
static void JUCE_CALLTYPE sleep(int milliseconds)
static void JUCE_CALLTYPE setCurrentThreadName(const String &newThreadName)
bool threadShouldExit() const
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
void addListener(Listener *)
void removeListener(Listener *)
static int64 currentTimeMillis() noexcept
Type get() const noexcept