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 / VDScheduler.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-11-05  |  6.0 KB  |  262 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 <vd2/system/vdtypes.h>
  28. #include <vd2/system/VDScheduler.h>
  29. #include <vd2/system/thread.h>
  30. #include <vd2/system/error.h>
  31. #include <windows.h>
  32.  
  33. VDScheduler::VDScheduler()
  34.     : mpErrorCB(NULL)
  35.     , pWakeupSignal(NULL)
  36.     , pParentSchedulerNode(NULL)
  37.     , mbExitThreads(false)
  38. {
  39. }
  40.  
  41. VDScheduler::~VDScheduler() {
  42. }
  43.  
  44. void VDScheduler::setSignal(VDSignal *pSignal) {
  45.     pWakeupSignal = pSignal;
  46. }
  47.  
  48. void VDScheduler::setSchedulerNode(VDSchedulerNode *pSchedulerNode) {
  49.     pParentSchedulerNode = pSchedulerNode;
  50. }
  51.  
  52. void VDScheduler::BeginShutdown() {
  53.     mbExitThreads = true;
  54.     Ping();
  55. }
  56.  
  57. void VDScheduler::Repost(VDSchedulerNode *pNode, bool bReschedule) {
  58.     vdsynchronized(csScheduler) {
  59.         if (pNode->bCondemned) {
  60.             tSuspendList::iterator it(listSuspends.begin()), itEnd(listSuspends.end());
  61.  
  62.             while(it!=itEnd) {
  63.                 VDSchedulerSuspendNode *pSuspendNode = *it;
  64.  
  65.                 if (pSuspendNode->mpNode == pNode) {
  66.                     it = listSuspends.erase(it);
  67.                     pSuspendNode->mSignal.signal();
  68.                 } else
  69.                     ++it;
  70.             }
  71.         } else {
  72.             pNode->bRunning = false;
  73.             if (bReschedule || pNode->bReschedule) {
  74.                 pNode->bReschedule = false;
  75.                 pNode->bReady = true;
  76.                 listReady.push_back(pNode);
  77.             } else
  78.                 listWaiting.push_back(pNode);
  79.         }
  80.     }
  81. }
  82.  
  83. bool VDScheduler::Run() {
  84.     VDSchedulerNode *pNode = NULL;
  85.     vdsynchronized(csScheduler) {
  86.         if (!listReady.empty()) {
  87.             pNode = listReady.front();
  88.             listReady.pop_front();
  89.             pNode->bRunning = true;
  90.             pNode->bReady = false;
  91.         }
  92.     }
  93.  
  94.     if (!pNode)
  95.         return false;
  96.  
  97.     bool bReschedule;
  98.     try {
  99.         bReschedule = pNode->Service();
  100.     } catch(MyError& e) {
  101.         Repost(pNode, false);
  102.  
  103.         vdsynchronized(csScheduler) {
  104.             if (mpErrorCB) {
  105.                 if (!mpErrorCB->OnAsyncError(e))
  106.                     throw;
  107.             }
  108.         }
  109.  
  110.         return true;
  111.     } catch(...) {
  112.         Repost(pNode, false);
  113.         throw;
  114.     }
  115.  
  116.     Repost(pNode, bReschedule);
  117.  
  118.     return true;
  119. }
  120.  
  121. bool VDScheduler::IdleWait() {
  122.     if (mbExitThreads)
  123.         return false;
  124.  
  125.     if (pWakeupSignal) {
  126. #if 0
  127.         while(WAIT_TIMEOUT == WaitForSingleObject(pWakeupSignal->getHandle(), 1000))
  128.             DumpStatus();
  129. #else
  130.         pWakeupSignal->wait();
  131. #endif
  132.     }
  133.  
  134.     return true;
  135. }
  136.  
  137. void VDScheduler::Ping() {
  138.     if (pWakeupSignal)
  139.         pWakeupSignal->signal();
  140. }
  141.  
  142. void VDScheduler::Lock() {
  143.     ++csScheduler;
  144. }
  145.  
  146. void VDScheduler::Unlock() {
  147.     --csScheduler;
  148. }
  149.  
  150. void VDScheduler::Reschedule(VDSchedulerNode *pNode) {
  151.     VDCriticalSection::AutoLock lock(csScheduler);
  152.  
  153.     RescheduleFast(pNode);
  154. }
  155.  
  156. void VDScheduler::RescheduleFast(VDSchedulerNode *pNode) {
  157.     if (pNode->bReady)
  158.         return;
  159.  
  160.     pNode->bReady = true;
  161.  
  162.     if (pNode->bRunning)
  163.         pNode->bReschedule = true;
  164.     else {
  165.         if (pWakeupSignal)
  166.             pWakeupSignal->signal();
  167.  
  168.         if (pParentSchedulerNode)
  169.             pParentSchedulerNode->Reschedule();
  170.  
  171.         listWaiting.erase(pNode);
  172.         listReady.push_back(pNode);
  173.     }
  174. }
  175.  
  176. void VDScheduler::Add(VDSchedulerNode *pNode) {
  177.     VDASSERT(pNode);
  178.  
  179.     pNode->pScheduler = this;
  180.     pNode->bRunning = false;
  181.     pNode->bReschedule = false;
  182.     pNode->bReady = true;
  183.     pNode->bCondemned = false;
  184.  
  185.     vdsynchronized(csScheduler) {
  186.         tNodeList::iterator it(listReady.begin()), itEnd(listReady.end());
  187.  
  188.         while(it != itEnd && (*it)->nPriority <= pNode->nPriority)
  189.             ++it;
  190.  
  191.         listReady.insert(it, pNode);
  192.     }
  193.  
  194.     if (pWakeupSignal)
  195.         pWakeupSignal->signal();
  196.  
  197.     if (pParentSchedulerNode)
  198.         pParentSchedulerNode->Reschedule();
  199. }
  200.  
  201. void VDScheduler::Remove(VDSchedulerNode *pNode) {
  202.     VDASSERT(pNode);
  203.  
  204.     VDSchedulerSuspendNode suspendNode(pNode);
  205.     bool running = false;
  206.  
  207.     vdsynchronized(csScheduler) {
  208.         pNode->bCondemned = true;
  209.         if (pNode->bRunning) {
  210.             running = true;
  211.             listSuspends.push_back(&suspendNode);
  212.         } else if (pNode->bReady)
  213.             listReady.erase(pNode);
  214.         else
  215.             listWaiting.erase(pNode);
  216.     }
  217.  
  218.     if (running)
  219.         suspendNode.mSignal.wait();
  220. }
  221.  
  222. void VDScheduler::DumpStatus() {
  223.     vdsynchronized(csScheduler) {
  224.         VDDEBUG2("\n    Waiting nodes:\n");
  225.         for(tNodeList::iterator it(listWaiting.begin()), itEnd(listWaiting.end()); it!=itEnd; ++it)
  226.             (*it)->DumpStatus();
  227.         VDDEBUG2("\n    Ready nodes:\n");
  228.         for(tNodeList::iterator it2(listReady.begin()), it2End(listReady.end()); it2!=it2End; ++it2)
  229.             (*it2)->DumpStatus();
  230.     }
  231. }
  232.  
  233. void VDSchedulerNode::DumpStatus() {
  234.     VDDEBUG2("        anonymous %p\n", this);
  235. }
  236.  
  237. ///////////////////////////////////////////////////////////////////////////
  238.  
  239. VDSchedulerThread::VDSchedulerThread()
  240.     : mpScheduler(NULL)
  241. {
  242. }
  243.  
  244. VDSchedulerThread::~VDSchedulerThread() {
  245. }
  246.  
  247. bool VDSchedulerThread::Start(VDScheduler *pScheduler) {
  248.     mpScheduler = pScheduler;
  249.     return VDThread::ThreadStart();
  250. }
  251.  
  252. void VDSchedulerThread::ThreadRun() {
  253.     VDScheduler& scheduler = *mpScheduler;
  254.  
  255.     do {
  256.         while(scheduler.Run())
  257.             ;
  258.     } while(scheduler.IdleWait());
  259.  
  260.     scheduler.Ping();
  261. }
  262.