home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / system / source / thread.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-07-01  |  5.6 KB  |  224 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. void VDSetThreadDebugName(VDThreadID tid, const char *name) {
  57.     THREADNAME_INFO info;
  58.     info.dwType        = 0x1000;
  59.     info.szName        = name;
  60.     info.dwThreadID    = tid;
  61.     info.dwFlags    = 0;
  62.  
  63.     __try {
  64.         RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *)&info);
  65.     } __except (EXCEPTION_CONTINUE_EXECUTION) {
  66.     }
  67. }
  68.  
  69. VDThread::VDThread(const char *pszDebugName)
  70.     : mpszDebugName(pszDebugName)
  71.     , mhThread(0)
  72.     , mThreadID(0)
  73. {
  74. }
  75.  
  76. VDThread::~VDThread() throw() {
  77.     if (isThreadAttached())
  78.         ThreadWait();
  79. }
  80.  
  81. bool VDThread::ThreadStart() {
  82.     VDASSERT(!isThreadAttached());
  83.  
  84.     if (!isThreadAttached())
  85.         mhThread = (void *)_beginthreadex(NULL, 0, StaticThreadStart, this, 0, &mThreadID);
  86.  
  87.     return mhThread != 0;
  88. }
  89.  
  90. void VDThread::ThreadDetach() {
  91.     if (isThreadAttached()) {
  92.         CloseHandle((HANDLE)mhThread);
  93.         mhThread = NULL;
  94.         mThreadID = 0;
  95.     }
  96. }
  97.  
  98. void VDThread::ThreadWait() {
  99.     if (isThreadAttached()) {
  100.         WaitForSingleObject((HANDLE)mhThread, INFINITE);
  101.         ThreadDetach();
  102.         mThreadID = 0;
  103.     }
  104. }
  105.  
  106. bool VDThread::isThreadActive() {
  107.     if (isThreadAttached()) {
  108.         if (WAIT_TIMEOUT == WaitForSingleObject((HANDLE)mhThread, 0))
  109.             return true;
  110.  
  111.         ThreadDetach();
  112.         mThreadID = 0;
  113.     }
  114.     return false;
  115. }
  116.  
  117. void VDThread::ThreadFinish() {
  118.     _endthreadex(0);
  119. }
  120.  
  121. void *VDThread::ThreadLocation() const {
  122.     if (!isThreadAttached())
  123.         return NULL;
  124.  
  125.     CONTEXT ctx;
  126.  
  127.     ctx.ContextFlags = CONTEXT_CONTROL;
  128.  
  129.     SuspendThread(mhThread);
  130.     GetThreadContext(mhThread, &ctx);
  131.     ResumeThread(mhThread);
  132.  
  133. #ifdef _M_AMD64
  134.     return (void *)ctx.Rip;
  135. #else
  136.     return (void *)ctx.Eip;
  137. #endif
  138. }
  139.  
  140. ///////////////////////////////////////////////////////////////////////////
  141.  
  142. unsigned __stdcall VDThread::StaticThreadStart(void *pThisAsVoid) {
  143.     VDThread *pThis = static_cast<VDThread *>(pThisAsVoid);
  144.  
  145.     // We cannot use mThreadID here because it might already have been
  146.     // invalidated by a detach in the main thread.
  147.     if (pThis->mpszDebugName)
  148.         VDSetThreadDebugName(GetCurrentThreadId(), pThis->mpszDebugName);
  149.  
  150.     VDInitThreadData(pThis->mpszDebugName);
  151.  
  152.     vdprotected1("running thread \"%.64s\"", const char *, pThis->mpszDebugName) {
  153.         pThis->ThreadRun();
  154.     }
  155.  
  156.     // NOTE: Do not put anything referencing this here, since our object
  157.     //       may have been destroyed by the threaded code.
  158.  
  159.     VDDeinitThreadData();
  160.  
  161.     return 0;
  162. }
  163.  
  164. ///////////////////////////////////////////////////////////////////////////
  165.  
  166. void VDCriticalSection::StructCheck() {
  167.     VDASSERTCT(sizeof(CritSec) == sizeof(CRITICAL_SECTION));
  168. }
  169.  
  170. ///////////////////////////////////////////////////////////////////////////
  171.  
  172. VDSignal::VDSignal() {
  173.     hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  174. }
  175.  
  176. VDSignalPersistent::VDSignalPersistent() {
  177.     hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  178. }
  179.  
  180. VDSignalBase::~VDSignalBase() {
  181.     CloseHandle(hEvent);
  182. }
  183.  
  184. void VDSignalBase::signal() {
  185.     SetEvent(hEvent);
  186. }
  187.  
  188. void VDSignalBase::wait() {
  189.     WaitForSingleObject(hEvent, INFINITE);
  190. }
  191.  
  192. bool VDSignalBase::check() {
  193.     return WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0);
  194. }
  195.  
  196. int VDSignalBase::wait(VDSignalBase *second) {
  197.     HANDLE        hArray[16];
  198.     DWORD        dwRet;
  199.  
  200.     hArray[0] = hEvent;
  201.     hArray[1] = second->hEvent;
  202.  
  203.     dwRet = WaitForMultipleObjects(2, hArray, FALSE, INFINITE);
  204.  
  205.     return dwRet == WAIT_FAILED ? -1 : dwRet - WAIT_OBJECT_0;
  206. }
  207.  
  208. int VDSignalBase::wait(VDSignalBase *second, VDSignalBase *third) {
  209.     HANDLE        hArray[3];
  210.     DWORD        dwRet;
  211.  
  212.     hArray[0] = hEvent;
  213.     hArray[1] = second->hEvent;
  214.     hArray[2] = third->hEvent;
  215.  
  216.     dwRet = WaitForMultipleObjects(3, hArray, FALSE, INFINITE);
  217.  
  218.     return dwRet == WAIT_FAILED ? -1 : dwRet - WAIT_OBJECT_0;
  219. }
  220.  
  221. void VDSignalPersistent::unsignal() {
  222.     ResetEvent(hEvent);
  223. }
  224.