home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / system / source / thread.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  6.7 KB  |  275 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #include "stdafx.h"
  27. #include <process.h>
  28.  
  29. #include <windows.h>
  30.  
  31. #include <vd2/system/vdtypes.h>
  32. #include <vd2/system/thread.h>
  33. #include <vd2/system/tls.h>
  34. #include <vd2/system/protscope.h>
  35.  
  36. namespace {
  37.     //
  38.     // This apparently came from one a talk by one of the Visual Studio
  39.     // developers, i.e. I didn't write it.
  40.     //
  41.     #define MS_VC_EXCEPTION 0x406d1388
  42.  
  43.     typedef struct tagTHREADNAME_INFO
  44.     {
  45.         DWORD dwType;        // must be 0x1000
  46.         LPCSTR szName;       // pointer to name (in same addr space)
  47.         DWORD dwThreadID;    // thread ID (-1 caller thread)
  48.         DWORD dwFlags;       // reserved for future use, most be zero
  49.     } THREADNAME_INFO;
  50. }
  51.  
  52. VDThreadID VDGetCurrentThreadID() {
  53.     return (VDThreadID)GetCurrentThreadId();
  54. }
  55.  
  56. VDProcessId VDGetCurrentProcessId() {
  57.     return (VDProcessId)GetCurrentProcessId();
  58. }
  59.  
  60. void VDSetThreadDebugName(VDThreadID tid, const char *name) {
  61.     THREADNAME_INFO info;
  62.     info.dwType        = 0x1000;
  63.     info.szName        = name;
  64.     info.dwThreadID    = tid;
  65.     info.dwFlags    = 0;
  66.  
  67.     __try {
  68.         RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *)&info);
  69.     } __except (EXCEPTION_CONTINUE_EXECUTION) {
  70.     }
  71. }
  72.  
  73. void VDThreadSleep(int milliseconds) {
  74.     if (milliseconds > 0)
  75.         ::Sleep(milliseconds);
  76. }
  77.  
  78. ///////////////////////////////////////////////////////////////////////////
  79.  
  80. VDThread::VDThread(const char *pszDebugName)
  81.     : mpszDebugName(pszDebugName)
  82.     , mhThread(0)
  83.     , mThreadID(0)
  84. {
  85. }
  86.  
  87. VDThread::~VDThread() throw() {
  88.     if (isThreadAttached())
  89.         ThreadWait();
  90. }
  91.  
  92. bool VDThread::ThreadStart() {
  93.     VDASSERT(!isThreadAttached());
  94.  
  95.     if (!isThreadAttached())
  96.         mhThread = (void *)_beginthreadex(NULL, 0, StaticThreadStart, this, 0, &mThreadID);
  97.  
  98.     return mhThread != 0;
  99. }
  100.  
  101. void VDThread::ThreadDetach() {
  102.     if (isThreadAttached()) {
  103.         CloseHandle((HANDLE)mhThread);
  104.         mhThread = NULL;
  105.         mThreadID = 0;
  106.     }
  107. }
  108.  
  109. void VDThread::ThreadWait() {
  110.     if (isThreadAttached()) {
  111.         WaitForSingleObject((HANDLE)mhThread, INFINITE);
  112.         ThreadDetach();
  113.         mThreadID = 0;
  114.     }
  115. }
  116.  
  117. bool VDThread::isThreadActive() {
  118.     if (isThreadAttached()) {
  119.         if (WAIT_TIMEOUT == WaitForSingleObject((HANDLE)mhThread, 0))
  120.             return true;
  121.  
  122.         ThreadDetach();
  123.         mThreadID = 0;
  124.     }
  125.     return false;
  126. }
  127.  
  128. void VDThread::ThreadFinish() {
  129.     _endthreadex(0);
  130. }
  131.  
  132. void *VDThread::ThreadLocation() const {
  133.     if (!isThreadAttached())
  134.         return NULL;
  135.  
  136.     CONTEXT ctx;
  137.  
  138.     ctx.ContextFlags = CONTEXT_CONTROL;
  139.  
  140.     SuspendThread(mhThread);
  141.     GetThreadContext(mhThread, &ctx);
  142.     ResumeThread(mhThread);
  143.  
  144. #ifdef _M_AMD64
  145.     return (void *)ctx.Rip;
  146. #else
  147.     return (void *)ctx.Eip;
  148. #endif
  149. }
  150.  
  151. ///////////////////////////////////////////////////////////////////////////
  152.  
  153. unsigned __stdcall VDThread::StaticThreadStart(void *pThisAsVoid) {
  154.     VDThread *pThis = static_cast<VDThread *>(pThisAsVoid);
  155.  
  156.     // We cannot use mThreadID here because it might already have been
  157.     // invalidated by a detach in the main thread.
  158.     if (pThis->mpszDebugName)
  159.         VDSetThreadDebugName(GetCurrentThreadId(), pThis->mpszDebugName);
  160.  
  161.     VDInitThreadData(pThis->mpszDebugName);
  162.  
  163.     vdprotected1("running thread \"%.64s\"", const char *, pThis->mpszDebugName) {
  164.         pThis->ThreadRun();
  165.     }
  166.  
  167.     // NOTE: Do not put anything referencing this here, since our object
  168.     //       may have been destroyed by the threaded code.
  169.  
  170.     VDDeinitThreadData();
  171.  
  172.     return 0;
  173. }
  174.  
  175. ///////////////////////////////////////////////////////////////////////////
  176.  
  177. void VDCriticalSection::StructCheck() {
  178.     VDASSERTCT(sizeof(CritSec) == sizeof(CRITICAL_SECTION));
  179. }
  180.  
  181. ///////////////////////////////////////////////////////////////////////////
  182.  
  183. VDSignal::VDSignal() {
  184.     hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  185. }
  186.  
  187. VDSignalPersistent::VDSignalPersistent() {
  188.     hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  189. }
  190.  
  191. VDSignalBase::~VDSignalBase() {
  192.     CloseHandle(hEvent);
  193. }
  194.  
  195. void VDSignalBase::signal() {
  196.     SetEvent(hEvent);
  197. }
  198.  
  199. void VDSignalBase::wait() {
  200.     WaitForSingleObject(hEvent, INFINITE);
  201. }
  202.  
  203. bool VDSignalBase::check() {
  204.     return WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0);
  205. }
  206.  
  207. int VDSignalBase::wait(VDSignalBase *second) {
  208.     HANDLE        hArray[16];
  209.     DWORD        dwRet;
  210.  
  211.     hArray[0] = hEvent;
  212.     hArray[1] = second->hEvent;
  213.  
  214.     dwRet = WaitForMultipleObjects(2, hArray, FALSE, INFINITE);
  215.  
  216.     return dwRet == WAIT_FAILED ? -1 : dwRet - WAIT_OBJECT_0;
  217. }
  218.  
  219. int VDSignalBase::wait(VDSignalBase *second, VDSignalBase *third) {
  220.     HANDLE        hArray[3];
  221.     DWORD        dwRet;
  222.  
  223.     hArray[0] = hEvent;
  224.     hArray[1] = second->hEvent;
  225.     hArray[2] = third->hEvent;
  226.  
  227.     dwRet = WaitForMultipleObjects(3, hArray, FALSE, INFINITE);
  228.  
  229.     return dwRet == WAIT_FAILED ? -1 : dwRet - WAIT_OBJECT_0;
  230. }
  231.  
  232. int VDSignalBase::waitMultiple(const VDSignalBase **signals, int count) {
  233.     VDASSERT(count <= 16);
  234.  
  235.     HANDLE handles[16];
  236.     int active = 0;
  237.  
  238.     for(int i=0; i<count; ++i) {
  239.         HANDLE h = signals[i]->hEvent;
  240.  
  241.         if (h)
  242.             handles[active++] = h;
  243.     }
  244.  
  245.     if (!active)
  246.         return -1;
  247.  
  248.     DWORD dwRet = WaitForMultipleObjects(active, handles, FALSE, INFINITE);
  249.  
  250.     return dwRet == WAIT_FAILED ? -1 : dwRet - WAIT_OBJECT_0;
  251. }
  252.  
  253. void VDSignalPersistent::unsignal() {
  254.     ResetEvent(hEvent);
  255. }
  256.  
  257. VDSemaphore::VDSemaphore(int initial)
  258.     : mKernelSema(CreateSemaphore(NULL, initial, 0x0fffffff, NULL))
  259. {
  260. }
  261.  
  262. VDSemaphore::~VDSemaphore() {
  263.     if (mKernelSema)
  264.         CloseHandle(mKernelSema);
  265. }
  266.  
  267. void VDSemaphore::Reset(int count) {
  268.     // reset semaphore to zero
  269.     while(WAIT_OBJECT_0 == WaitForSingleObject(mKernelSema, 0))
  270.         ;
  271.  
  272.     if (count)
  273.         ReleaseSemaphore(mKernelSema, count, NULL);
  274. }
  275.