Browse Source

Simplified some message-handling code.

tags/2021-05-28
jules 13 years ago
parent
commit
31209dadfc
9 changed files with 78 additions and 284 deletions
  1. +2
    -0
      modules/juce_events/broadcasters/juce_AsyncUpdater.cpp
  2. +4
    -7
      modules/juce_events/interprocess/juce_InterprocessConnection.h
  3. +68
    -25
      modules/juce_events/messages/juce_MessageManager.cpp
  4. +3
    -2
      modules/juce_events/messages/juce_MessageManager.h
  5. +0
    -39
      modules/juce_events/native/juce_android_Messaging.cpp
  6. +0
    -79
      modules/juce_events/native/juce_ios_MessageManager.mm
  7. +0
    -43
      modules/juce_events/native/juce_linux_Messaging.cpp
  8. +0
    -62
      modules/juce_events/native/juce_mac_MessageManager.mm
  9. +1
    -27
      modules/juce_events/native/juce_win32_Messaging.cpp

+ 2
- 0
modules/juce_events/broadcasters/juce_AsyncUpdater.cpp View File

@@ -41,6 +41,8 @@ public:
private: private:
AsyncUpdater& owner; AsyncUpdater& owner;
JUCE_DECLARE_NON_COPYABLE (AsyncUpdaterMessage);
}; };
//============================================================================== //==============================================================================


+ 4
- 7
modules/juce_events/interprocess/juce_InterprocessConnection.h View File

@@ -192,15 +192,12 @@ private:
//============================================================================== //==============================================================================
friend class InterprocessConnectionServer; 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 connectionMadeInt();
void connectionLostInt(); void connectionLostInt();
void deliverDataInt (const MemoryBlock& data);
void deliverDataInt (const MemoryBlock&);
bool readNextMessageInt(); bool readNextMessageInt();
void run(); void run();


+ 68
- 25
modules/juce_events/messages/juce_MessageManager.cpp View File

@@ -32,16 +32,27 @@ CallbackMessage::~CallbackMessage() {}
void CallbackMessage::post() 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; MessageManager* MessageManager::instance = nullptr;
@@ -103,13 +114,7 @@ void MessageManager::deliverMessage (Message* const message)
CallbackMessage* const callbackMessage = dynamic_cast <CallbackMessage*> (message); CallbackMessage* const callbackMessage = dynamic_cast <CallbackMessage*> (message);
if (callbackMessage != nullptr) if (callbackMessage != nullptr)
{
callbackMessage->messageCallback(); callbackMessage->messageCallback();
}
else if (dynamic_cast <QuitMessage*> (message) != nullptr)
{
quitMessageReceived = true;
}
} }
else if (messageListeners.contains (recipient)) else if (messageListeners.contains (recipient))
{ {
@@ -130,8 +135,7 @@ void MessageManager::runDispatchLoop()
void MessageManager::stopDispatchLoop() void MessageManager::stopDispatchLoop()
{ {
postMessageToQueue (new QuitMessage());
quitMessagePosted = true;
(new QuitMessage())->post();
} }
bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
@@ -161,6 +165,41 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
#endif #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<AsyncFunctionCallback> message (new AsyncFunctionCallback (func, parameter));
message->post();
message->finished.wait();
return message->result;
}
//============================================================================== //==============================================================================
void MessageManager::deliverBroadcastMessage (const String& value) void MessageManager::deliverBroadcastMessage (const String& value)
{ {
@@ -249,25 +288,27 @@ MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSi
bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob* const job) bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob* const job)
{ {
if (MessageManager::instance == nullptr)
MessageManager* const mm = MessageManager::instance;
if (mm == nullptr)
return false; return false;
if (MessageManager::instance->currentThreadHasLockedMessageManager())
if (mm->currentThreadHasLockedMessageManager())
return true; return true;
if (threadToCheck == nullptr && job == nullptr) if (threadToCheck == nullptr && job == nullptr)
{ {
MessageManager::instance->lockingLock.enter();
mm->lockingLock.enter();
} }
else else
{ {
while (! MessageManager::instance->lockingLock.tryEnter())
while (! mm->lockingLock.tryEnter())
{ {
if ((threadToCheck != nullptr && threadToCheck->threadShouldExit()) if ((threadToCheck != nullptr && threadToCheck->threadShouldExit())
|| (job != nullptr && job->shouldExit())) || (job != nullptr && job->shouldExit()))
return false; return false;
Thread::sleep (1);
Thread::yield();
} }
} }
@@ -281,14 +322,14 @@ bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob
{ {
blockingMessage->releaseEvent.signal(); blockingMessage->releaseEvent.signal();
blockingMessage = nullptr; blockingMessage = nullptr;
MessageManager::instance->lockingLock.exit();
mm->lockingLock.exit();
return false; return false;
} }
} }
jassert (MessageManager::instance->threadWithLock == 0);
jassert (mm->threadWithLock == 0);
MessageManager::instance->threadWithLock = Thread::getCurrentThreadId();
mm->threadWithLock = Thread::getCurrentThreadId();
return true; return true;
} }
@@ -296,15 +337,17 @@ MessageManagerLock::~MessageManagerLock() noexcept
{ {
if (blockingMessage != nullptr) if (blockingMessage != nullptr)
{ {
jassert (MessageManager::instance == nullptr || MessageManager::instance->currentThreadHasLockedMessageManager());
MessageManager* const mm = MessageManager::instance;
jassert (mm == nullptr || mm->currentThreadHasLockedMessageManager());
blockingMessage->releaseEvent.signal(); blockingMessage->releaseEvent.signal();
blockingMessage = nullptr; blockingMessage = nullptr;
if (MessageManager::instance != nullptr)
if (mm != nullptr)
{ {
MessageManager::instance->threadWithLock = 0;
MessageManager::instance->lockingLock.exit();
mm->threadWithLock = 0;
mm->lockingLock.exit();
} }
} }
} }


+ 3
- 2
modules/juce_events/messages/juce_MessageManager.h View File

@@ -177,7 +177,8 @@ private:
SortedSet <const MessageListener*> messageListeners; SortedSet <const MessageListener*> messageListeners;
ScopedPointer <ActionBroadcaster> broadcaster; ScopedPointer <ActionBroadcaster> broadcaster;
friend class JUCEApplication;
class QuitMessage;
friend class QuitMessage;
bool quitMessagePosted, quitMessageReceived; bool quitMessagePosted, quitMessageReceived;
Thread::ThreadID messageThreadId; Thread::ThreadID messageThreadId;
@@ -185,7 +186,7 @@ private:
Thread::ThreadID volatile threadWithLock; Thread::ThreadID volatile threadWithLock;
CriticalSection lockingLock; CriticalSection lockingLock;
void postMessageToQueue (Message* message);
void postMessageToQueue (Message*);
static bool postMessageToSystemQueue (Message*); static bool postMessageToSystemQueue (Message*);
static void* exitModalLoopCallback (void*); static void* exitModalLoopCallback (void*);
static void doPlatformSpecificInitialisation(); static void doPlatformSpecificInitialisation();


+ 0
- 39
modules/juce_events/native/juce_android_Messaging.cpp View File

@@ -50,45 +50,6 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, deliverMessage, void, (jobje
message->decReferenceCount(); 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&) void MessageManager::broadcastMessage (const String&)
{ {


+ 0
- 79
modules/juce_events/native/juce_ios_MessageManager.mm View File

@@ -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() void MessageManager::runDispatchLoop()
{ {
jassert (isThisTheMessageThread()); // must only be called by the message thread 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::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;
}
}

+ 0
- 43
modules/juce_events/native/juce_linux_Messaging.cpp View File

@@ -360,49 +360,6 @@ void MessageManager::broadcastMessage (const String& value)
/* TODO */ /* 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 // this function expects that it will NEVER be called simultaneously for two concurrent threads
bool MessageManager::dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages) bool MessageManager::dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages)
{ {


+ 0
- 62
modules/juce_events/native/juce_mac_MessageManager.mm View File

@@ -91,20 +91,6 @@ public:
(*appFocusChangeCallback)(); (*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() virtual void deleteSelf()
{ {
delete this; delete this;
@@ -159,7 +145,6 @@ using namespace juce;
- (void) applicationDidBecomeActive: (NSNotification*) aNotification; - (void) applicationDidBecomeActive: (NSNotification*) aNotification;
- (void) applicationDidResignActive: (NSNotification*) aNotification; - (void) applicationDidResignActive: (NSNotification*) aNotification;
- (void) applicationWillUnhide: (NSNotification*) aNotification; - (void) applicationWillUnhide: (NSNotification*) aNotification;
- (void) performCallback: (id) info;
- (void) broadcastMessageCallback: (NSNotification*) info; - (void) broadcastMessageCallback: (NSNotification*) info;
- (void) dummyMethod; - (void) dummyMethod;
@end @end
@@ -261,22 +246,6 @@ using namespace juce;
redirector->focusChanged(); 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 - (void) broadcastMessageCallback: (NSNotification*) n
{ {
NSDictionary* dict = (NSDictionary*) [n userInfo]; NSDictionary* dict = (NSDictionary*) [n userInfo];
@@ -406,34 +375,3 @@ void MessageManager::broadcastMessage (const String& message)
object: nil object: nil
userInfo: info]; 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;
}
}

+ 1
- 27
modules/juce_events/native/juce_win32_Messaging.cpp View File

@@ -33,7 +33,6 @@ namespace WindowsMessageHelpers
{ {
const unsigned int specialId = WM_APP + 0x4400; const unsigned int specialId = WM_APP + 0x4400;
const unsigned int broadcastId = WM_APP + 0x4403; const unsigned int broadcastId = WM_APP + 0x4403;
const unsigned int specialCallbackId = WM_APP + 0x4402;
const TCHAR messageWindowName[] = _T("JUCEWindow"); const TCHAR messageWindowName[] = _T("JUCEWindow");
ScopedPointer<HiddenMessageWindow> messageWindow; ScopedPointer<HiddenMessageWindow> messageWindow;
@@ -45,12 +44,7 @@ namespace WindowsMessageHelpers
{ {
if (h == juce_messageWindowHandle) 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 // 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 // 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; 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) void MessageManager::broadcastMessage (const String& value)
{ {
Array<HWND> windows; Array<HWND> windows;


Loading…
Cancel
Save