The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

342 lines
14KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #ifndef __JUCE_MESSAGEMANAGER_JUCEHEADER__
  24. #define __JUCE_MESSAGEMANAGER_JUCEHEADER__
  25. #include "../application/juce_DeletedAtShutdown.h"
  26. #include "../../juce_core/containers/juce_SortedSet.h"
  27. #include "juce_ActionListenerList.h"
  28. #include "juce_Timer.h"
  29. class Thread;
  30. class InternalTimerThread;
  31. //==============================================================================
  32. /** See MessageManager::callFunctionOnMessageThread() for use of this function type
  33. */
  34. typedef void* (MessageCallbackFunction) (void* userData);
  35. //==============================================================================
  36. /** Delivers Message objects to MessageListeners, and handles the event-dispatch loop.
  37. @see Message, MessageListener, MessageManagerLock, JUCEApplication
  38. */
  39. class JUCE_API MessageManager : private DeletedAtShutdown,
  40. private Timer
  41. {
  42. public:
  43. //==============================================================================
  44. /** Returns the global instance of the MessageManager. */
  45. static MessageManager* getInstance() throw();
  46. //==============================================================================
  47. /** Synchronously dispatches up to a certain number of messages from the queue.
  48. This will return when the queue becomes empty, or when the given number of
  49. messages has been sent.
  50. */
  51. void dispatchPendingMessages (int maxNumberOfMessagesToDispatch = 1000);
  52. /** Synchronously sends the next pending message.
  53. This must only be called by the message-thread.
  54. @param returnImmediatelyIfNoMessages if false, it will block indefinitely until a message
  55. needs dispatching. If true, then if no messages are
  56. pending, it will return immediately.
  57. @param wasAMessageDispatched if this is non-zero, it will be set to true or false
  58. depending on whether a message was actually sent or
  59. not.
  60. @returns false if the thing that's calling it should stop calling - i.e. if the
  61. app is trying to quit.
  62. */
  63. bool dispatchNextMessage (const bool returnImmediatelyIfNoMessages = false,
  64. bool* const wasAMessageDispatched = 0);
  65. //==============================================================================
  66. /** Calls a function using the message-thread.
  67. This can be used by any thread to cause this function to be called-back
  68. by the message thread. If it's the message-thread that's calling this method,
  69. then the function will just be called; if another thread is calling, a message
  70. will be posted to the queue, and this method will block until that message
  71. is delivered, the function is called, and the result is returned.
  72. Be careful not to cause any deadlocks with this! It's easy to do - e.g. if the caller
  73. thread has a critical section locked, which an unrelated message callback then tries to lock
  74. before the message thread gets round to processing this callback.
  75. @param callback the function to call - its signature must be @code
  76. void* myCallbackFunction (void*) @endcode
  77. @param userData a user-defined pointer that will be passed to the function that gets called
  78. @returns the value that the callback function returns.
  79. @see MessageManagerLock
  80. */
  81. void* callFunctionOnMessageThread (MessageCallbackFunction* callback,
  82. void* userData);
  83. /** Returns true if the caller-thread is the message thread. */
  84. bool isThisTheMessageThread() const;
  85. /** Called to tell the manager which thread is the one that's running the dispatch loop.
  86. (Best to ignore this method unless you really know what you're doing..)
  87. @see getCurrentMessageThread
  88. */
  89. void setCurrentMessageThread (const int threadId);
  90. /** Returns the ID of the current message thread, as set by setCurrentMessageThread().
  91. (Best to ignore this method unless you really know what you're doing..)
  92. @see setCurrentMessageThread
  93. */
  94. int getCurrentMessageThread() const throw() { return messageThreadId; }
  95. /** Returns true if the caller thread has currenltly got the message manager locked.
  96. see the MessageManagerLock class for more info about this.
  97. This will be true if the caller is the message thread, because that automatically
  98. gains a lock while a message is being dispatched.
  99. */
  100. bool currentThreadHasLockedMessageManager() const;
  101. //==============================================================================
  102. /** Sends a message to all other JUCE applications that are running.
  103. @param messageText the string that will be passed to the actionListenerCallback()
  104. method of the broadcast listeners in the other app.
  105. @see registerBroadcastListener, ActionListener
  106. */
  107. static void broadcastMessage (const String& messageText);
  108. /** Registers a listener to get told about broadcast messages.
  109. The actionListenerCallback() callback's string parameter
  110. is the message passed into broadcastMessage().
  111. @see broadcastMessage
  112. */
  113. void registerBroadcastListener (ActionListener* listener);
  114. /** Deregisters a broadcast listener. */
  115. void deregisterBroadcastListener (ActionListener* listener);
  116. //==============================================================================
  117. /** Sets a time-limit for the app to be 'busy' before an hourglass cursor will be shown.
  118. @param millisecs how long before the cursor is shown (the default time is 500ms). If the
  119. value is 0 or less, the wait cursor will never be shown (although on the
  120. Mac the system might still decide to show it after a while).
  121. @see MouseCursor::showWaitCursor
  122. */
  123. void setTimeBeforeShowingWaitCursor (const int millisecs);
  124. /** Returns the time-out before the 'busy' cursor is shown when the app is busy.
  125. @see setTimeBeforeShowingWaitCursor, MouseCursor::showWaitCursor
  126. */
  127. int getTimeBeforeShowingWaitCursor() const;
  128. /** Tells the message manager that the system isn't locked-up, even if the message
  129. loop isn't active.
  130. Used internally, this is handy when an OS enters its own modal loop.
  131. */
  132. static void delayWaitCursor();
  133. //==============================================================================
  134. /** Returns true if JUCEApplication::quit() has been called. */
  135. bool hasQuitMessageBeenPosted() const;
  136. //==============================================================================
  137. /** @internal */
  138. void deliverMessage (void*);
  139. /** @internal */
  140. void deliverBroadcastMessage (const String&);
  141. /** @internal */
  142. void timerCallback();
  143. //==============================================================================
  144. juce_UseDebuggingNewOperator
  145. private:
  146. MessageManager() throw();
  147. ~MessageManager() throw();
  148. friend class MessageListener;
  149. friend class ChangeBroadcaster;
  150. friend class ActionBroadcaster;
  151. static MessageManager* instance;
  152. SortedSet<const MessageListener*> messageListeners;
  153. ActionListenerList* broadcastListeners;
  154. friend class JUCEApplication;
  155. bool quitMessagePosted, quitMessageReceived, useMaximumForceWhenQuitting;
  156. int messageThreadId;
  157. int volatile messageCounter, lastMessageCounter, isInMessageDispatcher;
  158. bool volatile needToGetRidOfWaitCursor;
  159. int volatile timeBeforeWaitCursor;
  160. unsigned int lastActivityCheckOkTime;
  161. bool runDispatchLoop();
  162. void postMessageToQueue (Message* const message);
  163. void postQuitMessage (const bool useMaximumForce);
  164. static void doPlatformSpecificInitialisation();
  165. static void doPlatformSpecificShutdown();
  166. friend class InternalTimerThread;
  167. static void inactivityCheckCallback();
  168. void inactivityCheckCallbackInt();
  169. friend class MessageManagerLock;
  170. CriticalSection messageDispatchLock;
  171. int currentLockingThreadId;
  172. MessageManager (const MessageManager&);
  173. const MessageManager& operator= (const MessageManager&);
  174. };
  175. //==============================================================================
  176. /** Used to make sure that the calling thread has exclusive access to the message loop.
  177. Because it's not thread-safe to call any of the Component or other UI classes
  178. from threads other than the message thread, one of these objects can be used to
  179. lock the message loop and allow this to be done. The message thread will be
  180. suspended for the lifetime of the MessageManagerLock object, so create one on
  181. the stack like this: @code
  182. void MyThread::run()
  183. {
  184. someData = 1234;
  185. const MessageManagerLock mmLock;
  186. // the event loop will now be locked so it's safe to make a few calls..
  187. myComponent->setBounds (newBounds);
  188. myComponent->repaint();
  189. // ..the event loop will now be unlocked as the MessageManagerLock goes out of scope
  190. }
  191. @endcode
  192. Obviously be careful not to create one of these and leave it lying around, or
  193. your app will grind to a halt!
  194. Another caveat is that using this in conjunction with other CriticalSections
  195. can create lots of interesting ways of producing a deadlock! In particular, if
  196. your message thread calls stopThread() for a thread that uses these locks,
  197. you'll get an (occasional) deadlock..
  198. @see MessageManager, MessageManager::currentThreadHasLockedMessageManager
  199. */
  200. class JUCE_API MessageManagerLock
  201. {
  202. public:
  203. //==============================================================================
  204. /** Tries to acquire a lock on the message manager.
  205. If this constructor
  206. When this constructor returns, the message manager will have finished processing the
  207. last message and will not send another message until this MessageManagerLock is
  208. deleted.
  209. If the current thread already has the lock, nothing will be done, so it's perfectly
  210. safe to create these locks recursively.
  211. */
  212. MessageManagerLock() throw();
  213. /** Releases the current thread's lock on the message manager.
  214. Make sure this object is created and deleted by the same thread,
  215. otherwise there are no guarantees what will happen!
  216. */
  217. ~MessageManagerLock() throw();
  218. //==============================================================================
  219. /** Tries to acquire a lock on the message manager.
  220. This does the same thing as the normal constructor, but while it's waiting to get
  221. the lock, it checks the specified thread to see if it has been given the
  222. Thread::signalThreadShouldExit() signal. If this happens, then it will return
  223. without gaining the lock.
  224. To find out whether the lock was successful, call lockWasGained(). If this is
  225. false, your thread is being told to die, so you'd better get out of there.
  226. If the current thread already has the lock, nothing will be done, so it's perfectly
  227. safe to create these locks recursively.
  228. E.g.
  229. @code
  230. void run()
  231. {
  232. ...
  233. while (! threadShouldExit())
  234. {
  235. MessageManagerLock mml (Thread::getCurrentThread());
  236. if (! mml.lockWasGained)
  237. return; // another thread is trying to kill us!
  238. ..do some locked stuff here..
  239. }
  240. ..and now the MM is now unlocked..
  241. }
  242. @endcode
  243. */
  244. MessageManagerLock (Thread* const threadToCheckForExitSignal) throw();
  245. /** Returns true if the lock was successfully acquired.
  246. (See the constructor that takes a Thread for more info).
  247. */
  248. bool lockWasGained() const throw() { return locked; }
  249. private:
  250. int lastLockingThreadId;
  251. bool locked;
  252. };
  253. #endif // __JUCE_MESSAGEMANAGER_JUCEHEADER__