home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2004 March / PCWELT_3_2004.ISO / pcwsoft / flaskmpeg_078_39_src.z.exe / flaskmpeg / thread.h < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-28  |  8.3 KB  |  356 lines

  1. /* 
  2.  *  thread.h 
  3.  *
  4.  *    Copyright (C) Alberto Vigata - July 2000 - ultraflask@yahoo.com
  5.  *
  6.  *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
  7.  *    
  8.  *  FlasKMPEG is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published by
  10.  *  the Free Software Foundation; either version 2, or (at your option)
  11.  *  any later version.
  12.  *   
  13.  *  FlasKMPEG is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *   
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with GNU Make; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  21.  *
  22.  */
  23. #if !defined(THREAD_H)
  24. #define THREAD_H
  25.  
  26. #include <windows.h>
  27. #include <list>
  28.  
  29. using namespace std;
  30.  
  31. #include "flasktypes.h"
  32.  
  33. // Critial Section object
  34. class CCritSec {
  35.     
  36.     
  37.     CCritSec(const CCritSec &refCritSec);
  38.     CCritSec &operator=(const CCritSec &refCritSec);
  39.     
  40.     CRITICAL_SECTION m_CritSec;
  41.     
  42. public:
  43.     CCritSec() {
  44.         InitializeCriticalSection(&m_CritSec);
  45.     };
  46.     
  47.     ~CCritSec() {
  48.         DeleteCriticalSection(&m_CritSec);
  49.     };
  50.     
  51.     void Lock() {
  52.         EnterCriticalSection(&m_CritSec);
  53.     };
  54.     
  55.     void Unlock() {
  56.         LeaveCriticalSection(&m_CritSec);
  57.     };
  58. };
  59.  
  60. typedef CCritSec CFlCritSec;
  61.  
  62. // Lock a critical section when object is created
  63. // Unlock when its destructed
  64. class CAutoLock {
  65.     
  66.     CAutoLock(const CAutoLock &refAutoLock);
  67.     CAutoLock &operator=(const CAutoLock &refAutoLock);
  68.     
  69. protected:
  70.     CCritSec * m_pLock;
  71.     
  72. public:
  73.     CAutoLock(CCritSec * plock)
  74.     {
  75.         m_pLock = plock;
  76.         m_pLock->Lock();
  77.     };
  78.     
  79.     ~CAutoLock() {
  80.         m_pLock->Unlock();
  81.     };
  82. };
  83.  
  84. typedef CAutoLock CFlAutoLock;
  85.  
  86. // Thin wrapper for event objects
  87. class CFlEvent
  88. {
  89. public:
  90.     CFlEvent(BOOL fManualReset= FALSE)
  91.     {
  92.         m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL);
  93.     };
  94.     
  95.     ~CFlEvent()
  96.     {
  97.         if (m_hEvent) {
  98.             CloseHandle(m_hEvent);
  99.         }
  100.     };
  101.     void Set() {SetEvent(m_hEvent);};
  102.     BOOL Wait(DWORD dwTimeout = INFINITE) {
  103.         return (WaitForSingleObject(m_hEvent, dwTimeout) == WAIT_OBJECT_0);
  104.     };
  105.     void Reset() { ResetEvent(m_hEvent); };
  106.     BOOL Check() { return Wait(0); };
  107. protected:
  108.     HANDLE m_hEvent;
  109.     
  110. };
  111.  
  112.  
  113. #ifndef InterlockedExchangePointer
  114. #define InterlockedExchangePointer(Target, Value) \
  115. (PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value))
  116. #endif
  117.  
  118. // FlasKMPEG Thread class
  119. // 
  120. // Using CFlThread:
  121. //   Derive a class from CFlThread and put the code to
  122. //   be run in the thread in the DWORD ThreadProc() routine.
  123. //   
  124. //   From the outside world you can use SendCommand() method
  125. //   to send commands to the working thread.
  126. //   The working thread at ThreadProc() has to check for commands
  127. //   from time to time using GetCommand() routine
  128. class CFlThread {
  129.   
  130. protected:
  131.     HANDLE m_hThread;
  132.     
  133.     // thread will run this function on startup
  134.     // must be supplied by derived class
  135.     virtual DWORD ThreadProc() = 0;
  136.     
  137. public:
  138.     struct TCommand 
  139.     {
  140.       ui32 nCommand;
  141.       ui64 nParam;
  142.       bool bNeedsReply;
  143.     };
  144.  
  145.     CFlThread()
  146.     {
  147.         m_hThread = NULL;
  148.         m_evCommandTrigger.Reset();
  149.         m_evCommandCompleted.Reset();
  150.         m_evFinish.Reset();
  151.  
  152.         m_nCommandResult =0;
  153.     };
  154.     virtual ~CFlThread() {
  155.         Close();
  156.     }
  157.     
  158.  
  159.     
  160.     CFlCritSec m_AccessLock;    // locks access by client threads
  161.     CFlCritSec m_WorkerLock;    // locks access to shared objects
  162.  
  163.     // when the thread starts, it calls this function. We unwrap the 'this'
  164.     //pointer and call ThreadProc.
  165.     static DWORD WINAPI InitialThreadProc(LPVOID pv)
  166.     {
  167.         CFlThread * pThread = (CFlThread *) pv;
  168.         HRESULT hr = pThread->ThreadProc();
  169.         pThread->SignalExit();
  170.         return hr;
  171.     }; 
  172.  
  173.     void SetPriority(DWORD dwPriority)
  174.     {
  175.       SetThreadPriority(m_hThread, dwPriority );
  176.     }
  177.  
  178.     // start thread running  - error if already running
  179.     BOOL Create()
  180.     {
  181.         DWORD threadid;
  182.         
  183.         CFlAutoLock lock(&m_AccessLock);
  184.         
  185.         if (ThreadExists()) {
  186.             return FALSE;
  187.         }
  188.         
  189.         m_hThread = CreateThread(
  190.             NULL,
  191.             0,
  192.             CFlThread::InitialThreadProc,
  193.             this,
  194.             0,
  195.             &threadid);
  196.         
  197.         if (!m_hThread) {
  198.             return FALSE;
  199.         }
  200.         return TRUE;
  201.     }
  202.  
  203.  
  204.     // accessor thread calls this when done with thread (having told thread
  205.     // to exit)
  206.     void Close() {
  207.         HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hThread, 0);
  208.         if (hThread) {
  209.             WaitForSingleObject(hThread, INFINITE);
  210.             CloseHandle(hThread);
  211.         }
  212.     };
  213.     
  214.     // ThreadExists
  215.     // Return TRUE if the thread exists. FALSE otherwise
  216.     BOOL ThreadExists(void) const
  217.     {
  218.         if (m_hThread == 0) {
  219.             return FALSE;
  220.         } else {
  221.             return TRUE;
  222.         }
  223.     }
  224.  
  225.  
  226.     // Returns NULL if no command
  227.     bool GetCommand(TCommand *pCommand)
  228.     {
  229.       CFlAutoLock commandLock(&m_csCommand);
  230.  
  231.       if(m_lCommands.size())
  232.       {
  233.         *pCommand = m_lCommands.front();
  234.         m_lCommands.pop_front();
  235.         return true;
  236.       }
  237.       return false;
  238.     }
  239.  
  240.     // Sends a command to the the thread
  241.     // and blocks until the command is executed
  242.     // Can return a parameter
  243.     ui64 SendCommand(ui32 nCommand, ui64 nParam=0)
  244.     {
  245.       {
  246.         CFlAutoLock commandLock(&m_csCommand);
  247.         TCommand sCommand;
  248.  
  249.         sCommand.nCommand    = nCommand;
  250.         sCommand.nParam      = nParam;
  251.         sCommand.bNeedsReply = true;
  252.  
  253.         // Add command to the list
  254.         m_lCommands.push_back(sCommand);
  255.         // Reset reply event
  256.         m_evCommandCompleted.Reset();
  257.         // Trigger the command and wait for reply
  258.         m_evCommandTrigger.Set();
  259.       }
  260.       m_evCommandCompleted.Wait();
  261.  
  262.       CFlAutoLock lock(&m_csReply);
  263.       return m_nCommandResult;
  264.     }
  265.  
  266.     // Schedules a command to be executed.
  267.     // Don't return anything
  268.     void ScheduleCommand(ui32 nCommand, ui64 nParam=0)
  269.     {
  270.       TCommand sCommand;
  271.       sCommand.nCommand = nCommand;
  272.       sCommand.nParam   = nParam;
  273.       sCommand.bNeedsReply = false;
  274.  
  275.       CFlAutoLock commandLock(&m_csCommand);
  276.       // Add comand
  277.       m_lCommands.push_back(sCommand);
  278.       m_evCommandTrigger.Set();
  279.     }
  280.  
  281.     // Signals a command if there are no previous
  282.     // commands sent. Returns true if the command
  283.     // was sent.
  284.     bool SignalCommand(ui32 nCommand, ui64 nParam=0)
  285.     {
  286.       TCommand sCommand;
  287.  
  288.       sCommand.nCommand = nCommand;
  289.       sCommand.nParam   = nParam;
  290.       sCommand.bNeedsReply = false;
  291.  
  292.       CFlAutoLock commandLock(&m_csCommand);
  293.       // Signal commands only if there arent
  294.       // messages waiting on the list
  295.       if(!m_lCommands.size())
  296.       {
  297.         m_lCommands.push_back(sCommand);
  298.         m_evCommandTrigger.Set();
  299.         return true;
  300.       }
  301.       return false;
  302.     }
  303.  
  304.     void WaitCommand()
  305.     {
  306.       m_evCommandTrigger.Wait();
  307.     }
  308.  
  309.     void ReplyCommand(TCommand *pCommand, ui64 nReply=0)
  310.     {
  311.       if(pCommand->bNeedsReply)
  312.       {
  313.         CFlAutoLock lock(&m_csReply);
  314.         m_nCommandResult = nReply;
  315.         m_evCommandCompleted.Set();
  316.       }
  317.     }
  318.  
  319.     void SignalExit()
  320.     {
  321.       // Signal exit event
  322.       m_evFinish.Set();
  323.     }
  324.  
  325. #define THREAD_COMMAND_COUNT 2
  326.     enum Commands{ noCommand=0, exit };
  327.  
  328.     // Calling Exit signals the thread to exit
  329.     // This function returns only when the thread has exited.
  330.     void Exit()
  331.     {
  332.       if( ThreadExists() )
  333.       {
  334.         SendCommand(exit, 0);
  335.         Close();        
  336.       }
  337.     }
  338. protected:
  339.  
  340.  
  341.   CFlCritSec  m_csCommand;
  342.   CFlCritSec  m_csReply;
  343.  
  344.   CFlEvent    m_evCommandTrigger;
  345.   CFlEvent    m_evCommandCompleted;
  346.   CFlEvent    m_evFinish;
  347.  
  348.   ui64           m_nCommandResult;
  349. private:
  350.  
  351.   list<TCommand> m_lCommands;
  352. };
  353.  
  354.  
  355. #endif 
  356.