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.

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