@@ -41,6 +41,8 @@ public: | |||
private: | |||
AsyncUpdater& owner; | |||
JUCE_DECLARE_NON_COPYABLE (AsyncUpdaterMessage); | |||
}; | |||
//============================================================================== | |||
@@ -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(); | |||
@@ -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 <CallbackMessage*> (message); | |||
if (callbackMessage != nullptr) | |||
{ | |||
callbackMessage->messageCallback(); | |||
} | |||
else if (dynamic_cast <QuitMessage*> (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<AsyncFunctionCallback> 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(); | |||
} | |||
} | |||
} | |||
@@ -177,7 +177,8 @@ private: | |||
SortedSet <const MessageListener*> messageListeners; | |||
ScopedPointer <ActionBroadcaster> 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(); | |||
@@ -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&) | |||
{ | |||
@@ -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; | |||
} | |||
} |
@@ -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) | |||
{ | |||
@@ -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; | |||
} | |||
} |
@@ -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<HiddenMessageWindow> 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<HWND> windows; | |||