Back to index

lightning-sunbird  0.9+nobinonly
thread.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <windows.h>
00039 #include <windowsx.h>
00040 #include <process.h>
00041 
00042 #include "thread.h"
00043 #include "dbg.h"
00044 
00045 static DWORD WINAPI ThreadFunction(void * lp)
00046 {
00047   if (lp == NULL)
00048     return 0L;
00049 
00050   CThread * thread = (CThread *)lp;
00051   BOOL res = thread->init();
00052   thread->setInitEvent();
00053 
00054   if(res)
00055     thread->run();
00056 
00057   thread->shut();
00058   DWORD ret;
00059   GetExitCodeThread(thread->getHandle(), &ret);
00060   thread->setShutEvent();
00061   return ret;
00062 }
00063 
00064 CThread::CThread(DWORD aInitTimeOut, DWORD aShutTimeOut) :
00065   mThread(NULL),
00066   mID(0),
00067   mState(ts_dead),
00068   mEventThreadInitializationFinished(NULL),
00069   mEventThreadShutdownFinished(NULL),
00070   mInitTimeOut(aInitTimeOut),
00071   mShutTimeOut(aShutTimeOut),
00072   mEventDo(NULL),
00073   mAction(0)
00074 {
00075   dbgOut1("CThread::CThread");
00076 }
00077 
00078 CThread::~CThread()
00079 {
00080   dbgOut1("CThread::~CThread");
00081 }
00082 
00083 BOOL CThread::open(CThread * aThread)
00084 {
00085   dbgOut1("CThread::open");
00086 
00087   mEventThreadInitializationFinished = CreateEvent(NULL, TRUE, FALSE, NULL);
00088   mEventThreadShutdownFinished = CreateEvent(NULL, TRUE, FALSE, NULL);
00089   mEventDo = CreateEvent(NULL, TRUE, FALSE, NULL);
00090 
00091   mThread = (HANDLE)::_beginthreadex(0, 1024, (UINT (__stdcall *)(void *))ThreadFunction, aThread, 0L, (UINT *)&mID);
00092 
00093   if(mThread == NULL)
00094     return FALSE;
00095 
00096   SetThreadPriority(mThread, THREAD_PRIORITY_NORMAL);
00097 
00098   if(mEventThreadInitializationFinished != NULL)
00099     WaitForSingleObject(mEventThreadInitializationFinished, mInitTimeOut);
00100 
00101   return TRUE;
00102 }
00103 
00104 void CThread::close(CThread * aThread)
00105 {
00106   switch (mState) {
00107     case ts_dead:
00108       break;
00109     case ts_ready:
00110       mState = ts_dead;
00111       SetEvent(mEventDo);
00112       if(mEventThreadShutdownFinished != NULL)
00113         WaitForSingleObject(mEventThreadShutdownFinished, mShutTimeOut);
00114       break;
00115     case ts_busy:
00116     {
00117       aThread->shut();
00118       DWORD ret;
00119       GetExitCodeThread(aThread->getHandle(), &ret);
00120       TerminateThread(mThread, ret);
00121       mState = ts_dead;
00122       break;
00123     }
00124     default:
00125       break;
00126   }
00127 
00128   mThread = NULL;
00129   CloseHandle(mEventThreadInitializationFinished);
00130   CloseHandle(mEventThreadShutdownFinished);
00131   CloseHandle(mEventDo);
00132   dbgOut1("CThread::close");
00133 }
00134 
00135 BOOL CThread::setInitEvent()
00136 {
00137   return SetEvent(mEventThreadInitializationFinished);
00138 }
00139 
00140 BOOL CThread::setShutEvent()
00141 {
00142   return SetEvent(mEventThreadShutdownFinished);
00143 }
00144 
00145 BOOL CThread::isAlive()
00146 {
00147   return (mThread != NULL);
00148 }
00149 
00150 BOOL CThread::isBusy()
00151 {
00152   return (mState == ts_busy);
00153 }
00154 
00155 HANDLE CThread::getHandle()
00156 {
00157   return mThread;
00158 }
00159 
00160 void CThread::run()
00161 {
00162   mState = ts_ready;
00163 
00164   while(mState != ts_dead) {
00165     WaitForSingleObject(mEventDo, INFINITE);
00166     //dbgOut2("CThread::run(): Do event signalled, %u", mState);
00167     ResetEvent(mEventDo);
00168     if(mState == ts_dead)
00169       return;
00170     mState = ts_busy;
00171     dispatch();
00172     mState = ts_ready;
00173   }
00174   mState = ts_dead;
00175 }
00176 
00177 BOOL CThread::tryAction(int aAction)
00178 {
00179   if(mState != ts_ready)
00180     return FALSE;
00181 
00182   mAction = aAction;
00183   SetEvent(mEventDo);
00184 
00185   return TRUE;
00186 }
00187 
00188 BOOL CThread::doAction(int aAction)
00189 {
00190   while(mState != ts_ready) {
00191     //dbgOut2("CThread::doAction %i -- waiting...", aAction);
00192     if(mState == ts_dead)
00193       return FALSE;
00194     Sleep(0);
00195   }
00196 
00197   mState = ts_busy;
00198   mAction = aAction;
00199   //dbgOut2("CThread::doAction -- about to signal %i", aAction);
00200   SetEvent(mEventDo);
00201 
00202   return TRUE;
00203 }