thread_os2.cpp

Go to the documentation of this file.
00001 /* $Id: thread_os2.cpp 26353 2014-02-18 17:58:46Z frosch $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "../stdafx.h"
00013 #include "thread.h"
00014 
00015 #define INCL_DOS
00016 #include <os2.h>
00017 #include <process.h>
00018 
00022 class ThreadObject_OS2 : public ThreadObject {
00023 private:
00024   TID thread;          
00025   OTTDThreadFunc proc; 
00026   void *param;         
00027   bool self_destruct;  
00028 
00029 public:
00033   ThreadObject_OS2(OTTDThreadFunc proc, void *param, bool self_destruct) :
00034     thread(0),
00035     proc(proc),
00036     param(param),
00037     self_destruct(self_destruct)
00038   {
00039     thread = _beginthread(stThreadProc, NULL, 32768, this);
00040   }
00041 
00042   /* virtual */ bool Exit()
00043   {
00044     _endthread();
00045     return true;
00046   }
00047 
00048   /* virtual */ void Join()
00049   {
00050     DosWaitThread(&this->thread, DCWW_WAIT);
00051     this->thread = 0;
00052   }
00053 private:
00058   static void stThreadProc(void *thr)
00059   {
00060     ((ThreadObject_OS2 *)thr)->ThreadProc();
00061   }
00062 
00067   void ThreadProc()
00068   {
00069     /* Call the proc of the creator to continue this thread */
00070     try {
00071       this->proc(this->param);
00072     } catch (OTTDThreadExitSignal e) {
00073     } catch (...) {
00074       NOT_REACHED();
00075     }
00076 
00077     if (self_destruct) {
00078       this->Exit();
00079       delete this;
00080     }
00081   }
00082 };
00083 
00084 /* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
00085 {
00086   ThreadObject *to = new ThreadObject_OS2(proc, param, thread == NULL);
00087   if (thread != NULL) *thread = to;
00088   return true;
00089 }
00090 
00094 class ThreadMutex_OS2 : public ThreadMutex {
00095 private:
00096   HMTX mutex; 
00097   HEV event;  
00098   uint recursive_count;     
00099 
00100 public:
00101   ThreadMutex_OS2() : recursive_count(0)
00102   {
00103     DosCreateMutexSem(NULL, &mutex, 0, FALSE);
00104     DosCreateEventSem(NULL, &event, 0, FALSE);
00105   }
00106 
00107   /* virtual */ ~ThreadMutex_OS2()
00108   {
00109     DosCloseMutexSem(mutex);
00110     DosCloseEventSem(event);
00111   }
00112 
00113   /* virtual */ void BeginCritical(bool allow_recursive = false)
00114   {
00115     /* os2 mutex is recursive by itself */
00116     DosRequestMutexSem(mutex, (unsigned long) SEM_INDEFINITE_WAIT);
00117     this->recursive_count++;
00118     if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
00119   }
00120 
00121   /* virtual */ void EndCritical(bool allow_recursive = false)
00122   {
00123     if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
00124     this->recursive_count--;
00125     DosReleaseMutexSem(mutex);
00126   }
00127 
00128   /* virtual */ void WaitForSignal()
00129   {
00130     assert(this->recursive_count == 1); // Do we need to call Begin/EndCritical multiple times otherwise?
00131     this->EndCritical();
00132     DosWaitEventSem(event, SEM_INDEFINITE_WAIT);
00133     this->BeginCritical();
00134   }
00135 
00136   /* virtual */ void SendSignal()
00137   {
00138     DosPostEventSem(event);
00139   }
00140 };
00141 
00142 /* static */ ThreadMutex *ThreadMutex::New()
00143 {
00144   return new ThreadMutex_OS2();
00145 }