From 31209dadfceed8283c09a83d38eaa2fa13a7e3af Mon Sep 17 00:00:00 2001 From: jules Date: Sat, 24 Mar 2012 11:38:05 +0000 Subject: [PATCH] Simplified some message-handling code. --- .../broadcasters/juce_AsyncUpdater.cpp | 2 + .../juce_InterprocessConnection.h | 11 +-- .../messages/juce_MessageManager.cpp | 93 ++++++++++++++----- .../messages/juce_MessageManager.h | 5 +- .../native/juce_android_Messaging.cpp | 39 -------- .../native/juce_ios_MessageManager.mm | 79 ---------------- .../native/juce_linux_Messaging.cpp | 43 --------- .../native/juce_mac_MessageManager.mm | 62 ------------- .../native/juce_win32_Messaging.cpp | 28 +----- 9 files changed, 78 insertions(+), 284 deletions(-) diff --git a/modules/juce_events/broadcasters/juce_AsyncUpdater.cpp b/modules/juce_events/broadcasters/juce_AsyncUpdater.cpp index 9b05082c83..b7b8012abe 100644 --- a/modules/juce_events/broadcasters/juce_AsyncUpdater.cpp +++ b/modules/juce_events/broadcasters/juce_AsyncUpdater.cpp @@ -41,6 +41,8 @@ public: private: AsyncUpdater& owner; + + JUCE_DECLARE_NON_COPYABLE (AsyncUpdaterMessage); }; //============================================================================== diff --git a/modules/juce_events/interprocess/juce_InterprocessConnection.h b/modules/juce_events/interprocess/juce_InterprocessConnection.h index e802a05cf5..60d87b6fe9 100644 --- a/modules/juce_events/interprocess/juce_InterprocessConnection.h +++ b/modules/juce_events/interprocess/juce_InterprocessConnection.h @@ -192,15 +192,12 @@ private: //============================================================================== friend class InterprocessConnectionServer; - void initialiseWithSocket (StreamingSocket* socket_); - void initialiseWithPipe (NamedPipe* pipe_); - - void handleMessage (const Message& message); - + void initialiseWithSocket (StreamingSocket*); + void initialiseWithPipe (NamedPipe*); + void handleMessage (const Message&); void connectionMadeInt(); void connectionLostInt(); - void deliverDataInt (const MemoryBlock& data); - + void deliverDataInt (const MemoryBlock&); bool readNextMessageInt(); void run(); diff --git a/modules/juce_events/messages/juce_MessageManager.cpp b/modules/juce_events/messages/juce_MessageManager.cpp index 3930075751..51dd3b2fa9 100644 --- a/modules/juce_events/messages/juce_MessageManager.cpp +++ b/modules/juce_events/messages/juce_MessageManager.cpp @@ -32,16 +32,27 @@ CallbackMessage::~CallbackMessage() {} void CallbackMessage::post() { - if (MessageManager::instance != nullptr) - MessageManager::instance->postMessageToQueue (this); + MessageManager* const mm = MessageManager::instance; + if (mm != nullptr) + mm->postMessageToQueue (this); } //============================================================================== -struct QuitMessage : public Message +class MessageManager::QuitMessage : public CallbackMessage { - QuitMessage() noexcept {} -}; +public: + QuitMessage() {} + + void messageCallback() + { + MessageManager* const mm = MessageManager::instance; + if (mm != nullptr) + mm->quitMessageReceived = true; + } +private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (QuitMessage); +}; //============================================================================== MessageManager* MessageManager::instance = nullptr; @@ -103,13 +114,7 @@ void MessageManager::deliverMessage (Message* const message) CallbackMessage* const callbackMessage = dynamic_cast (message); if (callbackMessage != nullptr) - { callbackMessage->messageCallback(); - } - else if (dynamic_cast (message) != nullptr) - { - quitMessageReceived = true; - } } else if (messageListeners.contains (recipient)) { @@ -130,8 +135,7 @@ void MessageManager::runDispatchLoop() void MessageManager::stopDispatchLoop() { - postMessageToQueue (new QuitMessage()); - quitMessagePosted = true; + (new QuitMessage())->post(); } bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) @@ -161,6 +165,41 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) #endif +//============================================================================== +class AsyncFunctionCallback : public CallbackMessage +{ +public: + AsyncFunctionCallback (MessageCallbackFunction* const f, void* const param) + : result (nullptr), func (f), parameter (param) + {} + + void messageCallback() + { + result = (*func) (parameter); + finished.signal(); + } + + WaitableEvent finished; + void* volatile result; + +private: + MessageCallbackFunction* const func; + void* const parameter; + + JUCE_DECLARE_NON_COPYABLE (AsyncFunctionCallback); +}; + +void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* const func, void* const parameter) +{ + if (MessageManager::getInstance()->isThisTheMessageThread()) + return func (parameter); + + const ReferenceCountedObjectPtr message (new AsyncFunctionCallback (func, parameter)); + message->post(); + message->finished.wait(); + return message->result; +} + //============================================================================== void MessageManager::deliverBroadcastMessage (const String& value) { @@ -249,25 +288,27 @@ MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSi bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob* const job) { - if (MessageManager::instance == nullptr) + MessageManager* const mm = MessageManager::instance; + + if (mm == nullptr) return false; - if (MessageManager::instance->currentThreadHasLockedMessageManager()) + if (mm->currentThreadHasLockedMessageManager()) return true; if (threadToCheck == nullptr && job == nullptr) { - MessageManager::instance->lockingLock.enter(); + mm->lockingLock.enter(); } else { - while (! MessageManager::instance->lockingLock.tryEnter()) + while (! mm->lockingLock.tryEnter()) { if ((threadToCheck != nullptr && threadToCheck->threadShouldExit()) || (job != nullptr && job->shouldExit())) return false; - Thread::sleep (1); + Thread::yield(); } } @@ -281,14 +322,14 @@ bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob { blockingMessage->releaseEvent.signal(); blockingMessage = nullptr; - MessageManager::instance->lockingLock.exit(); + mm->lockingLock.exit(); return false; } } - jassert (MessageManager::instance->threadWithLock == 0); + jassert (mm->threadWithLock == 0); - MessageManager::instance->threadWithLock = Thread::getCurrentThreadId(); + mm->threadWithLock = Thread::getCurrentThreadId(); return true; } @@ -296,15 +337,17 @@ MessageManagerLock::~MessageManagerLock() noexcept { if (blockingMessage != nullptr) { - jassert (MessageManager::instance == nullptr || MessageManager::instance->currentThreadHasLockedMessageManager()); + MessageManager* const mm = MessageManager::instance; + + jassert (mm == nullptr || mm->currentThreadHasLockedMessageManager()); blockingMessage->releaseEvent.signal(); blockingMessage = nullptr; - if (MessageManager::instance != nullptr) + if (mm != nullptr) { - MessageManager::instance->threadWithLock = 0; - MessageManager::instance->lockingLock.exit(); + mm->threadWithLock = 0; + mm->lockingLock.exit(); } } } diff --git a/modules/juce_events/messages/juce_MessageManager.h b/modules/juce_events/messages/juce_MessageManager.h index 1cf65bf40e..3797905fce 100644 --- a/modules/juce_events/messages/juce_MessageManager.h +++ b/modules/juce_events/messages/juce_MessageManager.h @@ -177,7 +177,8 @@ private: SortedSet messageListeners; ScopedPointer broadcaster; - friend class JUCEApplication; + class QuitMessage; + friend class QuitMessage; bool quitMessagePosted, quitMessageReceived; Thread::ThreadID messageThreadId; @@ -185,7 +186,7 @@ private: Thread::ThreadID volatile threadWithLock; CriticalSection lockingLock; - void postMessageToQueue (Message* message); + void postMessageToQueue (Message*); static bool postMessageToSystemQueue (Message*); static void* exitModalLoopCallback (void*); static void doPlatformSpecificInitialisation(); diff --git a/modules/juce_events/native/juce_android_Messaging.cpp b/modules/juce_events/native/juce_android_Messaging.cpp index d0047b3e45..523ab11546 100644 --- a/modules/juce_events/native/juce_android_Messaging.cpp +++ b/modules/juce_events/native/juce_android_Messaging.cpp @@ -50,45 +50,6 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, deliverMessage, void, (jobje message->decReferenceCount(); } -//============================================================================== -class AsyncFunctionCaller : public AsyncUpdater -{ -public: - static void* call (MessageCallbackFunction* func_, void* parameter_) - { - if (MessageManager::getInstance()->isThisTheMessageThread()) - return func_ (parameter_); - - AsyncFunctionCaller caller (func_, parameter_); - caller.triggerAsyncUpdate(); - caller.finished.wait(); - return caller.result; - } - - void handleAsyncUpdate() - { - result = (*func) (parameter); - finished.signal(); - } - -private: - WaitableEvent finished; - MessageCallbackFunction* func; - void* parameter; - void* volatile result; - - AsyncFunctionCaller (MessageCallbackFunction* func_, void* parameter_) - : result (nullptr), func (func_), parameter (parameter_) - {} - - JUCE_DECLARE_NON_COPYABLE (AsyncFunctionCaller); -}; - -void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* func, void* parameter) -{ - return AsyncFunctionCaller::call (func, parameter); -} - //============================================================================== void MessageManager::broadcastMessage (const String&) { diff --git a/modules/juce_events/native/juce_ios_MessageManager.mm b/modules/juce_events/native/juce_ios_MessageManager.mm index 422bc6339e..2aa6f7bec5 100644 --- a/modules/juce_events/native/juce_ios_MessageManager.mm +++ b/modules/juce_events/native/juce_ios_MessageManager.mm @@ -23,52 +23,6 @@ ============================================================================== */ -struct CallbackMessagePayload -{ - MessageCallbackFunction* function; - void* parameter; - void* volatile result; - bool volatile hasBeenExecuted; -}; - -} // (juce namespace) - -//============================================================================== -@interface JuceCustomMessageHandler : NSObject -{ -} - -- (void) performCallback: (id) info; - -@end - -//============================================================================== -@implementation JuceCustomMessageHandler - -- (void) performCallback: (id) info -{ - if ([info isKindOfClass: [NSData class]]) - { - juce::CallbackMessagePayload* pl = (juce::CallbackMessagePayload*) [((NSData*) info) bytes]; - - if (pl != nullptr) - { - pl->result = (*pl->function) (pl->parameter); - pl->hasBeenExecuted = true; - } - } - else - { - jassertfalse; // should never get here! - } -} - -@end - -//============================================================================== -namespace juce -{ - void MessageManager::runDispatchLoop() { jassert (isThisTheMessageThread()); // must only be called by the message thread @@ -146,36 +100,3 @@ bool MessageManager::postMessageToSystemQueue (Message* message) void MessageManager::broadcastMessage (const String& value) { } - -void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, void* data) -{ - if (isThisTheMessageThread()) - { - return (*callback) (data); - } - else - { - jassert (dispatcher != nullptr); // trying to call this when the juce system isn't initialised.. - - // If a thread has a MessageManagerLock and then tries to call this method, it'll - // deadlock because the message manager is blocked from running, so can never - // call your function.. - jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - - JUCE_AUTORELEASEPOOL - - CallbackMessagePayload cmp; - cmp.function = callback; - cmp.parameter = data; - cmp.result = 0; - cmp.hasBeenExecuted = false; - - [dispatcher->juceCustomMessageHandler performSelectorOnMainThread: @selector (performCallback:) - withObject: [NSData dataWithBytesNoCopy: &cmp - length: sizeof (cmp) - freeWhenDone: NO] - waitUntilDone: YES]; - - return cmp.result; - } -} diff --git a/modules/juce_events/native/juce_linux_Messaging.cpp b/modules/juce_events/native/juce_linux_Messaging.cpp index c0c28e837c..f369dba00f 100644 --- a/modules/juce_events/native/juce_linux_Messaging.cpp +++ b/modules/juce_events/native/juce_linux_Messaging.cpp @@ -360,49 +360,6 @@ void MessageManager::broadcastMessage (const String& value) /* TODO */ } - -//============================================================================== -class AsyncFunctionCaller : public AsyncUpdater -{ -public: - static void* call (MessageCallbackFunction* func_, void* parameter_) - { - if (MessageManager::getInstance()->isThisTheMessageThread()) - return func_ (parameter_); - - AsyncFunctionCaller caller (func_, parameter_); - caller.triggerAsyncUpdate(); - caller.finished.wait(); - return caller.result; - } - - void handleAsyncUpdate() - { - result = (*func) (parameter); - finished.signal(); - } - -private: - WaitableEvent finished; - MessageCallbackFunction* func; - void* parameter; - void* volatile result; - - AsyncFunctionCaller (MessageCallbackFunction* func_, void* parameter_) - : result (nullptr), func (func_), parameter (parameter_) - {} - - JUCE_DECLARE_NON_COPYABLE (AsyncFunctionCaller); -}; - -void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* func, void* parameter) -{ - if (LinuxErrorHandling::errorOccurred) - return nullptr; - - return AsyncFunctionCaller::call (func, parameter); -} - // this function expects that it will NEVER be called simultaneously for two concurrent threads bool MessageManager::dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages) { diff --git a/modules/juce_events/native/juce_mac_MessageManager.mm b/modules/juce_events/native/juce_mac_MessageManager.mm index 71dc23d769..1803315350 100644 --- a/modules/juce_events/native/juce_mac_MessageManager.mm +++ b/modules/juce_events/native/juce_mac_MessageManager.mm @@ -91,20 +91,6 @@ public: (*appFocusChangeCallback)(); } - struct CallbackMessagePayload - { - MessageCallbackFunction* function; - void* parameter; - void* volatile result; - bool volatile hasBeenExecuted; - }; - - virtual void performCallback (CallbackMessagePayload* pl) - { - pl->result = (*pl->function) (pl->parameter); - pl->hasBeenExecuted = true; - } - virtual void deleteSelf() { delete this; @@ -159,7 +145,6 @@ using namespace juce; - (void) applicationDidBecomeActive: (NSNotification*) aNotification; - (void) applicationDidResignActive: (NSNotification*) aNotification; - (void) applicationWillUnhide: (NSNotification*) aNotification; -- (void) performCallback: (id) info; - (void) broadcastMessageCallback: (NSNotification*) info; - (void) dummyMethod; @end @@ -261,22 +246,6 @@ using namespace juce; redirector->focusChanged(); } -- (void) performCallback: (id) info -{ - if ([info isKindOfClass: [NSData class]]) - { - AppDelegateRedirector::CallbackMessagePayload* pl - = (AppDelegateRedirector::CallbackMessagePayload*) [((NSData*) info) bytes]; - - if (pl != nullptr) - redirector->performCallback (pl); - } - else - { - jassertfalse; // should never get here! - } -} - - (void) broadcastMessageCallback: (NSNotification*) n { NSDictionary* dict = (NSDictionary*) [n userInfo]; @@ -406,34 +375,3 @@ void MessageManager::broadcastMessage (const String& message) object: nil userInfo: info]; } - -void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, void* data) -{ - if (isThisTheMessageThread()) - { - return (*callback) (data); - } - else - { - // If a thread has a MessageManagerLock and then tries to call this method, it'll - // deadlock because the message manager is blocked from running, so can never - // call your function.. - jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - - JUCE_AUTORELEASEPOOL - - AppDelegateRedirector::CallbackMessagePayload cmp; - cmp.function = callback; - cmp.parameter = data; - cmp.result = 0; - cmp.hasBeenExecuted = false; - - [juceAppDelegate performSelectorOnMainThread: @selector (performCallback:) - withObject: [NSData dataWithBytesNoCopy: &cmp - length: sizeof (cmp) - freeWhenDone: NO] - waitUntilDone: YES]; - - return cmp.result; - } -} diff --git a/modules/juce_events/native/juce_win32_Messaging.cpp b/modules/juce_events/native/juce_win32_Messaging.cpp index 5fefdea9b5..d55f8afaaf 100644 --- a/modules/juce_events/native/juce_win32_Messaging.cpp +++ b/modules/juce_events/native/juce_win32_Messaging.cpp @@ -33,7 +33,6 @@ namespace WindowsMessageHelpers { const unsigned int specialId = WM_APP + 0x4400; const unsigned int broadcastId = WM_APP + 0x4403; - const unsigned int specialCallbackId = WM_APP + 0x4402; const TCHAR messageWindowName[] = _T("JUCEWindow"); ScopedPointer messageWindow; @@ -45,12 +44,7 @@ namespace WindowsMessageHelpers { if (h == juce_messageWindowHandle) { - if (message == specialCallbackId) - { - MessageCallbackFunction* const func = (MessageCallbackFunction*) wParam; - return (LRESULT) (*func) ((void*) lParam); - } - else if (message == specialId) + if (message == specialId) { // these are trapped early in the dispatch call, but must also be checked // here in case there are windows modal dialog boxes doing their own @@ -142,26 +136,6 @@ bool MessageManager::postMessageToSystemQueue (Message* message) return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::specialId, 0, (LPARAM) message) != 0; } -void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, void* userData) -{ - if (MessageManager::getInstance()->isThisTheMessageThread()) - { - return (*callback) (userData); - } - else - { - // If a thread has a MessageManagerLock and then tries to call this method, it'll - // deadlock because the message manager is blocked from running, and can't - // call your function.. - jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - - return (void*) SendMessage (juce_messageWindowHandle, - WindowsMessageHelpers::specialCallbackId, - (WPARAM) callback, - (LPARAM) userData); - } -} - void MessageManager::broadcastMessage (const String& value) { Array windows;