LMMS
Loading...
Searching...
No Matches
juce_MessageManager.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
34
36{
37 broadcaster.reset();
38
40
41 jassert (instance == this);
42 instance = nullptr; // do this last in case this instance is still needed by doPlatformSpecificShutdown()
43}
44
46
48{
49 if (instance == nullptr)
50 {
53 }
54
55 return instance;
56}
57
62
67
68//==============================================================================
70{
72
73 if (mm == nullptr || mm->quitMessagePosted.get() != 0 || ! postMessageToSystemQueue (this))
74 {
75 Ptr deleter (this); // (this will delete messages that were just created with a 0 ref count)
76 return false;
77 }
78
79 return true;
80}
81
82//==============================================================================
83#if ! (JUCE_MAC || JUCE_IOS || JUCE_ANDROID)
84// implemented in platform-specific code (juce_linux_Messaging.cpp and juce_win32_Messaging.cpp)
85bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages);
86
88{
89public:
91
92 void messageCallback() override
93 {
94 if (auto* mm = MessageManager::instance)
95 mm->quitMessageReceived = true;
96 }
97
99};
100
102{
103 jassert (isThisTheMessageThread()); // must only be called by the message thread
104
105 while (quitMessageReceived.get() == 0)
106 {
108 {
110 Thread::sleep (1);
111 }
113 }
114}
115
117{
118 (new QuitMessage())->post();
119 quitMessagePosted = true;
120}
121
122#if JUCE_MODAL_LOOPS_PERMITTED
123bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
124{
125 jassert (isThisTheMessageThread()); // must only be called by the message thread
126
127 auto endTime = Time::currentTimeMillis() + millisecondsToRunFor;
128
129 while (quitMessageReceived.get() == 0)
130 {
132 {
133 if (! dispatchNextMessageOnSystemQueue (millisecondsToRunFor >= 0))
134 Thread::sleep (1);
135 }
137
138 if (millisecondsToRunFor >= 0 && Time::currentTimeMillis() >= endTime)
139 break;
140 }
141
142 return quitMessageReceived.get() == 0;
143}
144#endif
145
146#endif
147
148//==============================================================================
150{
151public:
153 : func (f), parameter (param)
154 {}
155
156 void messageCallback() override
157 {
158 result = (*func) (parameter);
159 finished.signal();
160 }
161
163 std::atomic<void*> result { nullptr };
164
165private:
167 void* const parameter;
168
170};
171
173{
175 return func (parameter);
176
177 // If this thread has the message manager locked, then this will deadlock!
179
181
182 if (message->post())
183 {
184 message->finished.wait();
185 return message->result.load();
186 }
187
188 jassertfalse; // the OS message queue failed to send the message!
189 return nullptr;
190}
191
192bool MessageManager::callAsync (std::function<void()> fn)
193{
194 struct AsyncCallInvoker : public MessageBase
195 {
196 AsyncCallInvoker (std::function<void()> f) : callback (std::move (f)) {}
197 void messageCallback() override { callback(); }
198 std::function<void()> callback;
199 };
200
201 return (new AsyncCallInvoker (std::move (fn)))->post();
202}
203
204//==============================================================================
206{
207 if (broadcaster != nullptr)
208 broadcaster->sendActionMessage (value);
209}
210
212{
213 if (broadcaster == nullptr)
214 broadcaster.reset (new ActionBroadcaster());
215
216 broadcaster->addActionListener (listener);
217}
218
220{
221 if (broadcaster != nullptr)
222 broadcaster->removeActionListener (listener);
223}
224
225//==============================================================================
230
232{
233 auto thisThread = Thread::getCurrentThreadId();
234
235 if (messageThreadId != thisThread)
236 {
237 messageThreadId = thisThread;
238
239 #if JUCE_WINDOWS
240 // This is needed on windows to make sure the message window is created by this thread
243 #endif
244 }
245}
246
248{
249 auto thisThread = Thread::getCurrentThreadId();
250 return thisThread == messageThreadId || thisThread == threadWithLock.get();
251}
252
254{
255 if (auto i = getInstanceWithoutCreating())
256 return i->currentThreadHasLockedMessageManager();
257
258 return false;
259}
260
262{
263 if (auto i = getInstanceWithoutCreating())
264 return i->isThisTheMessageThread();
265
266 return false;
267}
268
269//==============================================================================
270//==============================================================================
271/* The only safe way to lock the message thread while another thread does
272 some work is by posting a special message, whose purpose is to tie up the event
273 loop until the other thread has finished its business.
274
275 Any other approach can get horribly deadlocked if the OS uses its own hidden locks which
276 get locked before making an event callback, because if the same OS lock gets indirectly
277 accessed from another thread inside a MM lock, you're screwed. (this is exactly what happens
278 in Cocoa).
279*/
304
305//==============================================================================
310
311bool MessageManager::Lock::tryAcquire (bool lockIsMandatory) const noexcept
312{
314
315 if (mm == nullptr)
316 {
318 return false;
319 }
320
321 if (! lockIsMandatory && (abortWait.get() != 0))
322 {
323 abortWait.set (0);
324 return false;
325 }
326
327 if (mm->currentThreadHasLockedMessageManager())
328 return true;
329
330 try
331 {
332 blockingMessage = *new BlockingMessage (this);
333 }
334 catch (...)
335 {
336 jassert (! lockIsMandatory);
337 return false;
338 }
339
340 if (! blockingMessage->post())
341 {
342 // post of message failed while trying to get the lock
343 jassert (! lockIsMandatory);
344 blockingMessage = nullptr;
345 return false;
346 }
347
348 do
349 {
350 while (abortWait.get() == 0)
351 lockedEvent.wait (-1);
352
353 abortWait.set (0);
354
355 if (lockGained.get() != 0)
356 {
357 mm->threadWithLock = Thread::getCurrentThreadId();
358 return true;
359 }
360
361 } while (lockIsMandatory);
362
363 // we didn't get the lock
364 blockingMessage->releaseEvent.signal();
365
366 {
367 ScopedLock lock (blockingMessage->ownerCriticalSection);
368
369 lockGained.set (0);
370 blockingMessage->owner.set (nullptr);
371 }
372
373 blockingMessage = nullptr;
374 return false;
375}
376
378{
379 if (lockGained.compareAndSetBool (false, true))
380 {
382
383 jassert (mm == nullptr || mm->currentThreadHasLockedMessageManager());
384 lockGained.set (0);
385
386 if (mm != nullptr)
387 mm->threadWithLock = {};
388
389 if (blockingMessage != nullptr)
390 {
391 blockingMessage->releaseEvent.signal();
392 blockingMessage = nullptr;
393 }
394 }
395}
396
398{
399 lockGained.set (1);
400 abort();
401}
402
404{
405 abortWait.set (1);
406 lockedEvent.signal();
407}
408
409//==============================================================================
411 : locked (attemptLock (threadToCheck, nullptr))
412{}
413
417
418bool MessageManagerLock::attemptLock (Thread* threadToCheck, ThreadPoolJob* jobToCheck)
419{
420 jassert (threadToCheck == nullptr || jobToCheck == nullptr);
421
422 if (threadToCheck != nullptr)
423 threadToCheck->addListener (this);
424
425 if (jobToCheck != nullptr)
426 jobToCheck->addListener (this);
427
428 // tryEnter may have a spurious abort (return false) so keep checking the condition
429 while ((threadToCheck == nullptr || ! threadToCheck->threadShouldExit())
430 && (jobToCheck == nullptr || ! jobToCheck->shouldExit()))
431 {
432 if (mmLock.tryEnter())
433 break;
434 }
435
436 if (threadToCheck != nullptr)
437 {
438 threadToCheck->removeListener (this);
439
440 if (threadToCheck->threadShouldExit())
441 return false;
442 }
443
444 if (jobToCheck != nullptr)
445 {
446 jobToCheck->removeListener (this);
447
448 if (jobToCheck->shouldExit())
449 return false;
450 }
451
452 return true;
453}
454
456
458{
459 mmLock.abort();
460}
461
462//==============================================================================
470
479
481
484
485} // namespace juce
#define noexcept
Definition DistrhoDefines.h:72
#define nullptr
Definition DistrhoDefines.h:75
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
Definition juce_ActionBroadcaster.h:37
Definition juce_ActionListener.h:35
Definition juce_MessageManager.cpp:150
MessageCallbackFunction *const func
Definition juce_MessageManager.cpp:166
WaitableEvent finished
Definition juce_MessageManager.cpp:162
AsyncFunctionCallback(MessageCallbackFunction *const f, void *const param)
Definition juce_MessageManager.cpp:152
std::atomic< void * > result
Definition juce_MessageManager.cpp:163
void *const parameter
Definition juce_MessageManager.cpp:167
void messageCallback() override
Definition juce_MessageManager.cpp:156
Definition juce_CriticalSection.h:43
static void deleteAll()
Definition juce_DeletedAtShutdown.cpp:50
static bool isStandaloneApp() noexcept
Definition juce_ApplicationBase.h:267
Definition juce_MessageManager.h:200
WaitableEvent lockedEvent
Definition juce_MessageManager.h:305
Atomic< int > lockGained
Definition juce_MessageManager.h:306
Lock()
Definition juce_MessageManager.cpp:306
bool tryAcquire(bool) const noexcept
Definition juce_MessageManager.cpp:311
ReferenceCountedObjectPtr< BlockingMessage > blockingMessage
Definition juce_MessageManager.h:304
~Lock()
Definition juce_MessageManager.cpp:307
void enter() const noexcept
Definition juce_MessageManager.cpp:308
void messageCallback() const
Definition juce_MessageManager.cpp:397
void abort() const noexcept
Definition juce_MessageManager.cpp:403
bool tryEnter() const noexcept
Definition juce_MessageManager.cpp:309
void exit() const noexcept
Definition juce_MessageManager.cpp:377
Atomic< int > abortWait
Definition juce_MessageManager.h:306
Definition juce_MessageManager.h:182
ReferenceCountedObjectPtr< MessageBase > Ptr
Definition juce_MessageManager.h:190
bool post()
Definition juce_MessageManager.cpp:69
Definition juce_MessageManager.cpp:88
void messageCallback() override
Definition juce_MessageManager.cpp:92
QuitMessage()
Definition juce_MessageManager.cpp:90
Definition juce_MessageManager.h:45
static MessageManager * instance
Definition juce_MessageManager.h:320
static bool callAsync(std::function< void()> functionToCall)
Definition juce_MessageManager.cpp:192
static void doPlatformSpecificShutdown()
Definition juce_linux_Messaging.cpp:310
Atomic< int > quitMessageReceived
Definition juce_MessageManager.h:328
bool isThisTheMessageThread() const noexcept
Definition juce_MessageManager.cpp:226
static void doPlatformSpecificInitialisation()
Definition juce_linux_Messaging.cpp:301
static bool existsAndIsCurrentThread() noexcept
Definition juce_MessageManager.cpp:261
void runDispatchLoop()
Definition juce_MessageManager.cpp:101
void stopDispatchLoop()
Definition juce_MessageManager.cpp:116
bool currentThreadHasLockedMessageManager() const noexcept
Definition juce_MessageManager.cpp:247
Atomic< Thread::ThreadID > threadWithLock
Definition juce_MessageManager.h:330
void * callFunctionOnMessageThread(MessageCallbackFunction *callback, void *userData)
Definition juce_MessageManager.cpp:172
Atomic< int > quitMessagePosted
Definition juce_MessageManager.h:328
void deregisterBroadcastListener(ActionListener *listener)
Definition juce_MessageManager.cpp:219
Thread::ThreadID messageThreadId
Definition juce_MessageManager.h:329
std::unique_ptr< ActionBroadcaster > broadcaster
Definition juce_MessageManager.h:327
void setCurrentThreadAsMessageThread()
Definition juce_MessageManager.cpp:231
void deliverBroadcastMessage(const String &)
Definition juce_MessageManager.cpp:205
static bool existsAndIsLockedByCurrentThread() noexcept
Definition juce_MessageManager.cpp:253
void registerBroadcastListener(ActionListener *listener)
Definition juce_MessageManager.cpp:211
static bool postMessageToSystemQueue(MessageBase *)
Definition juce_linux_Messaging.cpp:316
static void deleteInstance()
Definition juce_MessageManager.cpp:63
static MessageManager * getInstanceWithoutCreating() noexcept
Definition juce_MessageManager.cpp:58
MessageManager() noexcept
Definition juce_MessageManager.cpp:26
~MessageManager() noexcept
Definition juce_MessageManager.cpp:35
static MessageManager * getInstance()
Definition juce_MessageManager.cpp:47
bool locked
Definition juce_MessageManager.h:450
bool attemptLock(Thread *, ThreadPoolJob *)
Definition juce_MessageManager.cpp:418
MessageManager::Lock mmLock
Definition juce_MessageManager.h:449
~MessageManagerLock() override
Definition juce_MessageManager.cpp:455
MessageManagerLock(Thread *threadToCheckForExitSignal=nullptr)
Definition juce_MessageManager.cpp:410
void exitSignalSent() override
Definition juce_MessageManager.cpp:457
Definition juce_ReferenceCountedObject.h:247
~ScopedJuceInitialiser_GUI()
Definition juce_MessageManager.cpp:483
ScopedJuceInitialiser_GUI()
Definition juce_MessageManager.cpp:482
Definition juce_String.h:53
Definition juce_Thread.h:43
bool threadShouldExit() const
Definition juce_Thread.cpp:177
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
Definition juce_posix_SharedCode.h:1028
static void JUCE_CALLTYPE setCurrentThreadName(const String &newThreadName)
Definition juce_posix_SharedCode.h:975
void addListener(Listener *)
Definition juce_Thread.cpp:242
void removeListener(Listener *)
Definition juce_Thread.cpp:247
static void JUCE_CALLTYPE sleep(int milliseconds)
Definition juce_posix_SharedCode.h:44
Definition juce_ThreadPool.h:45
void addListener(Thread::Listener *)
Definition juce_ThreadPool.cpp:74
bool shouldExit() const noexcept
Definition juce_ThreadPool.h:107
void removeListener(Thread::Listener *)
Definition juce_ThreadPool.cpp:79
static int64 currentTimeMillis() noexcept
Definition juce_Time.cpp:220
Definition juce_WaitableEvent.h:36
register unsigned i
Definition inflate.c:1575
unsigned f
Definition inflate.c:1572
static PuglViewHint int value
Definition pugl.h:1708
static uintptr_t parent
Definition pugl.h:1644
CARLA_PLUGIN_EXPORT void exit(int status)
Definition interposer-safe.cpp:70
#define JUCE_TRY
Definition juce_ApplicationBase.h:329
#define JUCE_CATCH_EXCEPTION
Definition juce_ApplicationBase.h:330
#define JUCE_AUTORELEASEPOOL
Definition juce_Memory.h:158
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE(className)
#define jassertfalse
#define JUCE_CALLTYPE
#define JUCE_API
Definition juce_StandardHeader.h:152
#define JUCE_VERSION_ID
Definition juce_StandardHeader.h:45
Definition carla_juce.cpp:31
CriticalSection::ScopedLockType ScopedLock
Definition juce_CriticalSection.h:186
static int numScopedInitInstances
Definition juce_MessageManager.cpp:480
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t port void(* func)(const char *))
Definition juce_linux_JackAudio.cpp:67
void *(void *userData) MessageCallbackFunction
Definition juce_MessageManager.h:33
void deleteAndZero(Type &pointer)
Definition juce_Memory.h:40
bool dispatchNextMessageOnSystemQueue(bool returnIfNoPendingMessages)
Definition juce_linux_Messaging.cpp:333
JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI()
Definition juce_MessageManager.cpp:471
JUCE_API void JUCE_CALLTYPE initialiseJuce_GUI()
Definition juce_MessageManager.cpp:463
Definition juce_Atomic.h:42
Type get() const noexcept
Definition juce_Atomic.h:64
Definition juce_MessageManager.cpp:281
CriticalSection ownerCriticalSection
Definition juce_MessageManager.cpp:298
Atomic< const MessageManager::Lock * > owner
Definition juce_MessageManager.cpp:299
WaitableEvent releaseEvent
Definition juce_MessageManager.cpp:300
BlockingMessage(const MessageManager::Lock *parent) noexcept
Definition juce_MessageManager.cpp:282
void messageCallback() override
Definition juce_MessageManager.cpp:286
const char const char const char const char char * fn
Definition swell-functions.h:168
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
ZCONST char * post
Definition fileio.c:2493
#define void
Definition unzip.h:396
mm
Definition zipinfo.c:2291
#define const
Definition zconf.h:137