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.

391 lines
9.9KB

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