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.

416 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. #if ! JUCE_ONLY_BUILD_CORE_LIBRARY
  39. extern HWND juce_messageWindowHandle;
  40. #endif
  41. #ifdef _MSC_VER
  42. #pragma warning (pop)
  43. #endif
  44. //==============================================================================
  45. CriticalSection::CriticalSection() throw()
  46. {
  47. // (just to check the MS haven't changed this structure and broken things...)
  48. #if _MSC_VER >= 1400
  49. static_jassert (sizeof (CRITICAL_SECTION) <= sizeof (internal));
  50. #else
  51. static_jassert (sizeof (CRITICAL_SECTION) <= 24);
  52. #endif
  53. InitializeCriticalSection ((CRITICAL_SECTION*) internal);
  54. }
  55. CriticalSection::~CriticalSection() throw()
  56. {
  57. DeleteCriticalSection ((CRITICAL_SECTION*) internal);
  58. }
  59. void CriticalSection::enter() const throw()
  60. {
  61. EnterCriticalSection ((CRITICAL_SECTION*) internal);
  62. }
  63. bool CriticalSection::tryEnter() const throw()
  64. {
  65. return TryEnterCriticalSection ((CRITICAL_SECTION*) internal) != FALSE;
  66. }
  67. void CriticalSection::exit() const throw()
  68. {
  69. LeaveCriticalSection ((CRITICAL_SECTION*) internal);
  70. }
  71. //==============================================================================
  72. WaitableEvent::WaitableEvent() throw()
  73. : internal (CreateEvent (0, FALSE, FALSE, 0))
  74. {
  75. }
  76. WaitableEvent::~WaitableEvent() throw()
  77. {
  78. CloseHandle (internal);
  79. }
  80. bool WaitableEvent::wait (const int timeOutMillisecs) const throw()
  81. {
  82. return WaitForSingleObject (internal, timeOutMillisecs) == WAIT_OBJECT_0;
  83. }
  84. void WaitableEvent::signal() const throw()
  85. {
  86. SetEvent (internal);
  87. }
  88. void WaitableEvent::reset() const throw()
  89. {
  90. ResetEvent (internal);
  91. }
  92. //==============================================================================
  93. void JUCE_API juce_threadEntryPoint (void*);
  94. static unsigned int __stdcall threadEntryProc (void* userData) throw()
  95. {
  96. #if ! JUCE_ONLY_BUILD_CORE_LIBRARY
  97. AttachThreadInput (GetWindowThreadProcessId (juce_messageWindowHandle, 0),
  98. GetCurrentThreadId(), TRUE);
  99. #endif
  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. bool JUCE_API JUCE_CALLTYPE juce_isRunningUnderDebugger() throw()
  247. {
  248. return IsDebuggerPresent() != FALSE;
  249. }
  250. bool JUCE_CALLTYPE Process::isRunningUnderDebugger() throw()
  251. {
  252. return juce_isRunningUnderDebugger();
  253. }
  254. //==============================================================================
  255. void Process::raisePrivilege()
  256. {
  257. jassertfalse // xxx not implemented
  258. }
  259. void Process::lowerPrivilege()
  260. {
  261. jassertfalse // xxx not implemented
  262. }
  263. void Process::terminate()
  264. {
  265. #if defined (JUCE_DEBUG) && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS
  266. _CrtDumpMemoryLeaks();
  267. #endif
  268. // bullet in the head in case there's a problem shutting down..
  269. ExitProcess (0);
  270. }
  271. void* Process::loadDynamicLibrary (const String& name)
  272. {
  273. void* result = 0;
  274. JUCE_TRY
  275. {
  276. result = (void*) LoadLibrary (name);
  277. }
  278. JUCE_CATCH_ALL
  279. return result;
  280. }
  281. void Process::freeDynamicLibrary (void* h)
  282. {
  283. JUCE_TRY
  284. {
  285. if (h != 0)
  286. FreeLibrary ((HMODULE) h);
  287. }
  288. JUCE_CATCH_ALL
  289. }
  290. void* Process::getProcedureEntryPoint (void* h, const String& name)
  291. {
  292. return (h != 0) ? (void*) GetProcAddress ((HMODULE) h, name)
  293. : 0;
  294. }
  295. //==============================================================================
  296. InterProcessLock::InterProcessLock (const String& name_) throw()
  297. : internal (0),
  298. name (name_),
  299. reentrancyLevel (0)
  300. {
  301. }
  302. InterProcessLock::~InterProcessLock() throw()
  303. {
  304. exit();
  305. }
  306. bool InterProcessLock::enter (const int timeOutMillisecs) throw()
  307. {
  308. if (reentrancyLevel++ == 0)
  309. {
  310. internal = CreateMutex (0, TRUE, name);
  311. if (internal != 0 && GetLastError() == ERROR_ALREADY_EXISTS)
  312. {
  313. if (timeOutMillisecs == 0
  314. || WaitForSingleObject (internal, (timeOutMillisecs < 0) ? INFINITE : timeOutMillisecs)
  315. == WAIT_TIMEOUT)
  316. {
  317. ReleaseMutex (internal);
  318. CloseHandle (internal);
  319. internal = 0;
  320. }
  321. }
  322. }
  323. return (internal != 0);
  324. }
  325. void InterProcessLock::exit() throw()
  326. {
  327. if (--reentrancyLevel == 0 && internal != 0)
  328. {
  329. ReleaseMutex (internal);
  330. CloseHandle (internal);
  331. internal = 0;
  332. }
  333. }
  334. END_JUCE_NAMESPACE