OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

thread_os2.cpp
Go to the documentation of this file.
1 /* $Id: thread_os2.cpp 27670 2016-10-30 17:29:33Z frosch $ */
2
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
9
12 #include "../stdafx.h"
13 #include "thread.h"
14
15 #define INCL_DOS
16 #include <os2.h>
17 #include <process.h>
18
19 #include "../safeguards.h"
20
24 class ThreadObject_OS2 : public ThreadObject {
25 private:
26 TID thread;
27 OTTDThreadFunc proc;
28 void *param;
29 bool self_destruct;
30
31 public:
35 ThreadObject_OS2(OTTDThreadFunc proc, void *param, bool self_destruct) :
36 thread(0),
37 proc(proc),
38 param(param),
39 self_destruct(self_destruct)
40 {
41 thread = _beginthread(stThreadProc, NULL, 1048576, this);
42 }
43
44 /* virtual */ bool Exit()
45 {
46 _endthread();
47 return true;
48 }
49
50 /* virtual */ void Join()
51 {
52 DosWaitThread(&this->thread, DCWW_WAIT);
53 this->thread = 0;
54 }
55 private:
60 static void stThreadProc(void *thr)
61 {
62 ((ThreadObject_OS2 *)thr)->ThreadProc();
63 }
64
69 void ThreadProc()
70 {
71 /* Call the proc of the creator to continue this thread */
72 try {
73 this->proc(this->param);
74 } catch (OTTDThreadExitSignal e) {
75 } catch (...) {
76 NOT_REACHED();
77 }
78
79 if (self_destruct) {
80 this->Exit();
81 delete this;
82 }
83 }
84 };
85
86 /* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread, const char *name)
87 {
88 ThreadObject *to = new ThreadObject_OS2(proc, param, thread == NULL);
89 if (thread != NULL) *thread = to;
90 return true;
91 }
92
96 class ThreadMutex_OS2 : public ThreadMutex {
97 private:
98 HMTX mutex;
99 HEV event;
100 uint recursive_count;
101
102 public:
103 ThreadMutex_OS2() : recursive_count(0)
104 {
105 DosCreateMutexSem(NULL, &mutex, 0, FALSE);
106 DosCreateEventSem(NULL, &event, 0, FALSE);
107 }
108
109 /* virtual */ ~ThreadMutex_OS2()
110 {
111 DosCloseMutexSem(mutex);
112 DosCloseEventSem(event);
113 }
114
115 /* virtual */ void BeginCritical(bool allow_recursive = false)
116 {
117 /* os2 mutex is recursive by itself */
118 DosRequestMutexSem(mutex, (unsigned long) SEM_INDEFINITE_WAIT);
119 this->recursive_count++;
120 if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
121 }
122
123 /* virtual */ void EndCritical(bool allow_recursive = false)
124 {
125 if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
126 this->recursive_count--;
127 DosReleaseMutexSem(mutex);
128 }
129
130 /* virtual */ void WaitForSignal()
131 {
132 assert(this->recursive_count == 1); // Do we need to call Begin/EndCritical multiple times otherwise?
133 this->EndCritical();
134 DosWaitEventSem(event, SEM_INDEFINITE_WAIT);
135 this->BeginCritical();
136 }
137
138 /* virtual */ void SendSignal()
139 {
140 DosPostEventSem(event);
141 }
142 };
143
144 /* static */ ThreadMutex *ThreadMutex::New()
145 {
146 return new ThreadMutex_OS2();
147 }