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.

405 lines
10KB

  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. #include "win32_headers.h"
  24. #ifdef _MSC_VER
  25. #pragma warning (disable: 4514)
  26. #pragma warning (push)
  27. #include <crtdbg.h>
  28. #endif
  29. #include <process.h>
  30. #include "../../../src/juce_core/basics/juce_StandardHeader.h"
  31. BEGIN_JUCE_NAMESPACE
  32. #include "../../../src/juce_core/text/juce_String.h"
  33. #include "../../../src/juce_core/threads/juce_CriticalSection.h"
  34. #include "../../../src/juce_core/threads/juce_WaitableEvent.h"
  35. #include "../../../src/juce_core/threads/juce_Thread.h"
  36. #include "../../../src/juce_core/threads/juce_Process.h"
  37. #include "../../../src/juce_core/threads/juce_InterProcessLock.h"
  38. extern HWND juce_messageWindowHandle;
  39. #ifdef _MSC_VER
  40. #pragma warning (pop)
  41. #endif
  42. //==============================================================================
  43. CriticalSection::CriticalSection() throw()
  44. {
  45. // (just to check the MS haven't changed this structure and broken things...)
  46. #if _MSC_VER >= 1400
  47. static_jassert (sizeof (CRITICAL_SECTION) <= sizeof (internal));
  48. #else
  49. static_jassert (sizeof (CRITICAL_SECTION) <= 24);
  50. #endif
  51. InitializeCriticalSection ((CRITICAL_SECTION*) internal);
  52. }
  53. CriticalSection::~CriticalSection() throw()
  54. {
  55. DeleteCriticalSection ((CRITICAL_SECTION*) internal);
  56. }
  57. void CriticalSection::enter() const throw()
  58. {
  59. EnterCriticalSection ((CRITICAL_SECTION*) internal);
  60. }
  61. bool CriticalSection::tryEnter() const throw()
  62. {
  63. return TryEnterCriticalSection ((CRITICAL_SECTION*) internal) != FALSE;
  64. }
  65. void CriticalSection::exit() const throw()
  66. {
  67. LeaveCriticalSection ((CRITICAL_SECTION*) internal);
  68. }
  69. //==============================================================================
  70. WaitableEvent::WaitableEvent() throw()
  71. #ifdef JUCE_DEBUG
  72. : internal (CreateEvent (0, FALSE, FALSE, _T("Juce WaitableEvent")))
  73. #else
  74. : internal (CreateEvent (0, FALSE, FALSE, 0))
  75. #endif
  76. {
  77. }
  78. WaitableEvent::~WaitableEvent() throw()
  79. {
  80. CloseHandle (internal);
  81. }
  82. bool WaitableEvent::wait (const int timeOutMillisecs) const throw()
  83. {
  84. return WaitForSingleObject (internal, timeOutMillisecs) == WAIT_OBJECT_0;
  85. }
  86. void WaitableEvent::signal() const throw()
  87. {
  88. SetEvent (internal);
  89. }
  90. void WaitableEvent::reset() const throw()
  91. {
  92. ResetEvent (internal);
  93. }
  94. //==============================================================================
  95. void JUCE_API juce_threadEntryPoint (void*);
  96. static unsigned int __stdcall threadEntryProc (void* userData) throw()
  97. {
  98. AttachThreadInput (GetWindowThreadProcessId (juce_messageWindowHandle, 0),
  99. GetCurrentThreadId(), TRUE);
  100. juce_threadEntryPoint (userData);
  101. _endthreadex(0);
  102. return 0;
  103. }
  104. void juce_CloseThreadHandle (void* handle) throw()
  105. {
  106. CloseHandle ((HANDLE) handle);
  107. }
  108. void* juce_createThread (void* userData) throw()
  109. {
  110. unsigned int threadId;
  111. return (void*) _beginthreadex (0, 0,
  112. &threadEntryProc,
  113. userData,
  114. 0, &threadId);
  115. }
  116. void juce_killThread (void* handle) throw()
  117. {
  118. if (handle != 0)
  119. {
  120. #ifdef JUCE_DEBUG
  121. OutputDebugString (_T("** Warning - Forced thread termination **\n"));
  122. #endif
  123. TerminateThread (handle, 0);
  124. }
  125. }
  126. void juce_setCurrentThreadName (const String& name) throw()
  127. {
  128. #if defined (JUCE_DEBUG) && JUCE_MSVC
  129. struct
  130. {
  131. DWORD dwType;
  132. LPCSTR szName;
  133. DWORD dwThreadID;
  134. DWORD dwFlags;
  135. } info;
  136. info.dwType = 0x1000;
  137. info.szName = name;
  138. info.dwThreadID = GetCurrentThreadId();
  139. info.dwFlags = 0;
  140. #define MS_VC_EXCEPTION 0x406d1388
  141. __try
  142. {
  143. RaiseException (MS_VC_EXCEPTION, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
  144. }
  145. __except (EXCEPTION_CONTINUE_EXECUTION)
  146. {}
  147. #else
  148. (void) name;
  149. #endif
  150. }
  151. int Thread::getCurrentThreadId() throw()
  152. {
  153. return (int) GetCurrentThreadId();
  154. }
  155. // priority 1 to 10 where 5=normal, 1=low
  156. void juce_setThreadPriority (void* threadHandle, int priority) throw()
  157. {
  158. int pri = THREAD_PRIORITY_TIME_CRITICAL;
  159. if (priority < 1)
  160. pri = THREAD_PRIORITY_IDLE;
  161. else if (priority < 2)
  162. pri = THREAD_PRIORITY_LOWEST;
  163. else if (priority < 5)
  164. pri = THREAD_PRIORITY_BELOW_NORMAL;
  165. else if (priority < 7)
  166. pri = THREAD_PRIORITY_NORMAL;
  167. else if (priority < 9)
  168. pri = THREAD_PRIORITY_ABOVE_NORMAL;
  169. else if (priority < 10)
  170. pri = THREAD_PRIORITY_HIGHEST;
  171. if (threadHandle == 0)
  172. threadHandle = GetCurrentThread();
  173. SetThreadPriority (threadHandle, pri);
  174. }
  175. void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) throw()
  176. {
  177. SetThreadAffinityMask (GetCurrentThread(), affinityMask);
  178. }
  179. static HANDLE sleepEvent = 0;
  180. void juce_initialiseThreadEvents() throw()
  181. {
  182. if (sleepEvent == 0)
  183. #ifdef JUCE_DEBUG
  184. sleepEvent = CreateEvent (0, 0, 0, _T("Juce Sleep Event"));
  185. #else
  186. sleepEvent = CreateEvent (0, 0, 0, 0);
  187. #endif
  188. }
  189. void Thread::yield() throw()
  190. {
  191. Sleep (0);
  192. }
  193. void JUCE_CALLTYPE Thread::sleep (const int millisecs) throw()
  194. {
  195. if (millisecs >= 10)
  196. {
  197. Sleep (millisecs);
  198. }
  199. else
  200. {
  201. jassert (sleepEvent != 0);
  202. // unlike Sleep() this is guaranteed to return to the current thread after
  203. // the time expires, so we'll use this for short waits, which are more likely
  204. // to need to be accurate
  205. WaitForSingleObject (sleepEvent, millisecs);
  206. }
  207. }
  208. //==============================================================================
  209. static int lastProcessPriority = -1;
  210. // called by WindowDriver because Windows does wierd things to process priority
  211. // when you swap apps, and this forces an update when the app is brought to the front.
  212. void juce_repeatLastProcessPriority() throw()
  213. {
  214. if (lastProcessPriority >= 0) // (avoid changing this if it's not been explicitly set by the app..)
  215. {
  216. DWORD p;
  217. switch (lastProcessPriority)
  218. {
  219. case Process::LowPriority:
  220. p = IDLE_PRIORITY_CLASS;
  221. break;
  222. case Process::NormalPriority:
  223. p = NORMAL_PRIORITY_CLASS;
  224. break;
  225. case Process::HighPriority:
  226. p = HIGH_PRIORITY_CLASS;
  227. break;
  228. case Process::RealtimePriority:
  229. p = REALTIME_PRIORITY_CLASS;
  230. break;
  231. default:
  232. jassertfalse // bad priority value
  233. return;
  234. }
  235. SetPriorityClass (GetCurrentProcess(), p);
  236. }
  237. }
  238. void Process::setPriority (ProcessPriority prior)
  239. {
  240. if (lastProcessPriority != (int) prior)
  241. {
  242. lastProcessPriority = (int) prior;
  243. juce_repeatLastProcessPriority();
  244. }
  245. }
  246. //==============================================================================
  247. void Process::raisePrivilege()
  248. {
  249. jassertfalse // xxx not implemented
  250. }
  251. void Process::lowerPrivilege()
  252. {
  253. jassertfalse // xxx not implemented
  254. }
  255. void Process::terminate()
  256. {
  257. #if defined (JUCE_DEBUG) && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS
  258. _CrtDumpMemoryLeaks();
  259. #endif
  260. // bullet in the head in case there's a problem shutting down..
  261. ExitProcess (0);
  262. }
  263. void* Process::loadDynamicLibrary (const String& name)
  264. {
  265. void* result = 0;
  266. JUCE_TRY
  267. {
  268. result = (void*) LoadLibrary (name);
  269. }
  270. JUCE_CATCH_ALL
  271. return result;
  272. }
  273. void Process::freeDynamicLibrary (void* h)
  274. {
  275. JUCE_TRY
  276. {
  277. if (h != 0)
  278. FreeLibrary ((HMODULE) h);
  279. }
  280. JUCE_CATCH_ALL
  281. }
  282. void* Process::getProcedureEntryPoint (void* h, const String& name)
  283. {
  284. return (h != 0) ? (void*) GetProcAddress ((HMODULE) h, name)
  285. : 0;
  286. }
  287. //==============================================================================
  288. InterProcessLock::InterProcessLock (const String& name_) throw()
  289. : internal (0),
  290. name (name_),
  291. reentrancyLevel (0)
  292. {
  293. }
  294. InterProcessLock::~InterProcessLock() throw()
  295. {
  296. exit();
  297. }
  298. bool InterProcessLock::enter (const int timeOutMillisecs) throw()
  299. {
  300. if (reentrancyLevel++ == 0)
  301. {
  302. internal = CreateMutex (0, TRUE, name);
  303. if (internal != 0 && GetLastError() == ERROR_ALREADY_EXISTS)
  304. {
  305. if (timeOutMillisecs == 0
  306. || WaitForSingleObject (internal, (timeOutMillisecs < 0) ? INFINITE : timeOutMillisecs)
  307. == WAIT_TIMEOUT)
  308. {
  309. ReleaseMutex (internal);
  310. CloseHandle (internal);
  311. internal = 0;
  312. }
  313. }
  314. }
  315. return (internal != 0);
  316. }
  317. void InterProcessLock::exit() throw()
  318. {
  319. if (--reentrancyLevel == 0 && internal != 0)
  320. {
  321. ReleaseMutex (internal);
  322. CloseHandle (internal);
  323. internal = 0;
  324. }
  325. }
  326. END_JUCE_NAMESPACE