Loading...
Searching...
No Matches
juce_MessageManager.h
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
To use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
class MessageManagerLock;
class ThreadPoolJob;
class ActionListener;
class ActionBroadcaster;
//==============================================================================
using MessageCallbackFunction = void* (void* userData);
//==============================================================================
class JUCE_API MessageManager final
{
public:
//==============================================================================
static MessageManager* getInstance();
static MessageManager* getInstanceWithoutCreating() noexcept;
static void deleteInstance();
//==============================================================================
void runDispatchLoop();
void stopDispatchLoop();
bool hasStopMessageBeenSent() const noexcept { return quitMessagePosted.get() != 0; }
#if JUCE_MODAL_LOOPS_PERMITTED
bool runDispatchLoopUntil (int millisecondsToRunFor);
#endif
//==============================================================================
static bool callAsync (std::function<void()> functionToCall);
void* callFunctionOnMessageThread (MessageCallbackFunction* callback, void* userData);
bool isThisTheMessageThread() const noexcept;
void setCurrentThreadAsMessageThread();
Thread::ThreadID getCurrentMessageThread() const noexcept { return messageThreadId; }
bool currentThreadHasLockedMessageManager() const noexcept;
static bool existsAndIsLockedByCurrentThread() noexcept;
static bool existsAndIsCurrentThread() noexcept;
//==============================================================================
static void broadcastMessage (const String& messageText);
void registerBroadcastListener (ActionListener* listener);
void deregisterBroadcastListener (ActionListener* listener);
//==============================================================================
class JUCE_API MessageBase : public ReferenceCountedObject
{
public:
MessageBase() = default;
~MessageBase() override = default;
virtual void messageCallback() = 0;
bool post();
using Ptr = ReferenceCountedObjectPtr<MessageBase>;
JUCE_DECLARE_NON_COPYABLE (MessageBase)
};
//==============================================================================
class JUCE_API Lock
{
public:
Lock();
~Lock();
void enter() const noexcept;
bool tryEnter() const noexcept;
void exit() const noexcept;
void abort() const noexcept;
//==============================================================================
using ScopedLockType = GenericScopedLock<Lock>;
using ScopedUnlockType = GenericScopedUnlock<Lock>;
using ScopedTryLockType = GenericScopedTryLock<Lock>;
private:
struct BlockingMessage;
friend class ReferenceCountedObjectPtr<BlockingMessage>;
bool exclusiveTryAcquire (bool) const noexcept;
bool tryAcquire (bool) const noexcept;
void setAcquired (bool success) const noexcept;
//==============================================================================
// This mutex is used to make this lock type behave like a normal mutex.
// If multiple threads call enter() simultaneously, only one will succeed in gaining
// this mutex. The mutex is released again in exit().
mutable CriticalSection entryMutex;
// This mutex protects the other data members of the lock from concurrent access, which
// happens when the BlockingMessage calls setAcquired to indicate that the lock was gained.
mutable std::mutex mutex;
mutable ReferenceCountedObjectPtr<BlockingMessage> blockingMessage;
mutable std::condition_variable condvar;
mutable bool abortWait = false, acquired = false;
};
//==============================================================================
#ifndef DOXYGEN
// Internal methods - do not use!
void deliverBroadcastMessage (const String&);
~MessageManager() noexcept;
#endif
private:
//==============================================================================
MessageManager() noexcept;
static MessageManager* instance;
friend class MessageBase;
class QuitMessage;
friend class QuitMessage;
friend class MessageManagerLock;
std::unique_ptr<ActionBroadcaster> broadcaster;
Atomic<int> quitMessagePosted { 0 }, quitMessageReceived { 0 };
Thread::ThreadID messageThreadId;
Atomic<Thread::ThreadID> threadWithLock;
mutable std::mutex messageThreadIdMutex;
static bool postMessageToSystemQueue (MessageBase*);
static void* exitModalLoopCallback (void*);
static void doPlatformSpecificInitialisation();
static void doPlatformSpecificShutdown();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MessageManager)
};
//==============================================================================
class JUCE_API MessageManagerLock : private Thread::Listener
{
public:
//==============================================================================
MessageManagerLock (Thread* threadToCheckForExitSignal = nullptr);
//==============================================================================
MessageManagerLock (ThreadPoolJob* jobToCheckForExitSignal);
//==============================================================================
~MessageManagerLock() override;
//==============================================================================
bool lockWasGained() const noexcept { return locked; }
private:
//==============================================================================
MessageManager::Lock mmLock;
bool locked;
//==============================================================================
bool attemptLock (Thread*, ThreadPoolJob*);
void exitSignalSent() override;
JUCE_DECLARE_NON_COPYABLE (MessageManagerLock)
};
//==============================================================================
#define JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED \
jassert (juce::MessageManager::existsAndIsLockedByCurrentThread());
#define JUCE_ASSERT_MESSAGE_THREAD \
jassert (juce::MessageManager::existsAndIsCurrentThread());
#define JUCE_ASSERT_MESSAGE_MANAGER_EXISTS \
jassert (juce::MessageManager::getInstanceWithoutCreating() != nullptr);
} // namespace juce
juce::ActionBroadcaster
Definition juce_ActionBroadcaster.h:37
juce::ActionListener
Definition juce_ActionListener.h:35
juce::CriticalSection
Definition juce_CriticalSection.h:43
juce::GenericScopedLock
Definition juce_ScopedLock.h:55
juce::GenericScopedTryLock
Definition juce_ScopedLock.h:198
juce::GenericScopedUnlock
Definition juce_ScopedLock.h:126
juce::MessageManagerLock
Definition juce_MessageManager.h:390
juce::MessageManagerLock::MessageManagerLock
MessageManagerLock(Thread *threadToCheckForExitSignal=nullptr)
Definition juce_MessageManager.cpp:442
juce::MessageManagerLock::lockWasGained
bool lockWasGained() const noexcept
Definition juce_MessageManager.h:456
juce::MessageManager::Lock
Definition juce_MessageManager.h:200
juce::MessageManager::Lock::Lock
Lock()
Definition juce_MessageManager.cpp:317
juce::MessageManager::Lock::ScopedTryLockType
GenericScopedTryLock< Lock > ScopedTryLockType
Definition juce_MessageManager.h:294
juce::MessageManager::Lock::enter
void enter() const noexcept
Definition juce_MessageManager.cpp:319
juce::MessageManager::Lock::abort
void abort() const noexcept
Definition juce_MessageManager.cpp:428
juce::MessageManager::Lock::tryEnter
bool tryEnter() const noexcept
Definition juce_MessageManager.cpp:320
juce::MessageManager::Lock::ScopedUnlockType
GenericScopedUnlock< Lock > ScopedUnlockType
Definition juce_MessageManager.h:291
juce::MessageManager::Lock::ScopedLockType
GenericScopedLock< Lock > ScopedLockType
Definition juce_MessageManager.h:288
juce::MessageManager::Lock::exit
void exit() const noexcept
Definition juce_MessageManager.cpp:401
juce::MessageManager::MessageBase
Definition juce_MessageManager.h:182
juce::MessageManager::broadcastMessage
static void broadcastMessage(const String &messageText)
juce::MessageManager::runDispatchLoop
void runDispatchLoop()
Definition juce_MessageManager.cpp:104
juce::MessageManager::hasStopMessageBeenSent
bool hasStopMessageBeenSent() const noexcept
Definition juce_MessageManager.h:80
juce::MessageManager::stopDispatchLoop
void stopDispatchLoop()
Definition juce_MessageManager.cpp:119
juce::MessageManager::deregisterBroadcastListener
void deregisterBroadcastListener(ActionListener *listener)
Definition juce_MessageManager.cpp:222
juce::MessageManager::registerBroadcastListener
void registerBroadcastListener(ActionListener *listener)
Definition juce_MessageManager.cpp:214
juce::MessageManager::getCurrentMessageThread
Thread::ThreadID getCurrentMessageThread() const noexcept
Definition juce_MessageManager.h:134
juce::MessageManager::deleteInstance
static void deleteInstance()
Definition juce_MessageManager.cpp:63
juce::MessageManager::getInstanceWithoutCreating
static MessageManager * getInstanceWithoutCreating() noexcept
Definition juce_MessageManager.cpp:58
juce::MessageManager::getInstance
static MessageManager * getInstance()
Definition juce_MessageManager.cpp:47
juce::ReferenceCountedObjectPtr
Definition juce_ReferenceCountedObject.h:247
juce::ReferenceCountedObject::ReferenceCountedObject
ReferenceCountedObject()=default
juce::String
Definition juce_String.h:53
juce::ThreadPoolJob
Definition juce_ThreadPool.h:45
juce::Thread::Listener
Definition juce_Thread.h:396
juce::Thread
Definition juce_Thread.h:43
juce::Atomic
Definition juce_Atomic.h:42