SheafSystem  0.0.0.0
thread.cc
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
18 // Implementation for class THREAD
19 
20 #ifndef THREAD_H
21 #include "SheafSystem/thread.h"
22 #endif
23 
24 #ifdef _PTHREADS
25 
26 #include "SheafSystem/assert_contract.h"
27 
28 #ifndef RUNNABLE_H
29 #include "SheafSystem/runnable.h"
30 #endif
31 
32 #include "SheafSystem/singly_linked_list.h"
33 
34 singly_linked_list<thread *> *
35 sheaf::thread::
36 _thread_list = 0;
37 
39 sheaf::thread::
40 thread()
41 {
42 
43  // body:
44 
45  _is_alive = false;
46  _runnable = 0;
47 
48  if (_thread_list == 0)
49  _thread_list = new singly_linked_list<thread *>;
50 
51  int old_list_size = _thread_list->size();
52 
53  _thread_list->push_front(this);
54 
55  // postconditions:
56 
57  ensure(invariant());
58  ensure(_thread_list->size() == old_list_size+1);
59  ensure(! is_alive(this));
60 };
61 
62 
64 sheaf::thread::
65 thread(runnable* xrunnable)
66 {
67 
68  // preconditions:
69 
70  require(xrunnable != 0);
71 
72  // body:
73 
74  _is_alive = false;
75  _runnable = xrunnable;
76 
77  if (_thread_list == 0)
78  _thread_list = new singly_linked_list<thread *>;
79 
80  int old_list_size = _thread_list->size();
81 
82  _thread_list->push_front(this);
83 
84  // postconditions:
85 
86  ensure(invariant());
87  ensure(_thread_list->size() == old_list_size+1);
88  ensure(! is_alive(this));
89 
90 }
91 
92 
94 sheaf::thread::
95 ~thread()
96 {
97 
98  // preconditions:
99 
100  require(_thread_list != 0);
101 
102  // body:
103 
104 }
105 
106 bool
107 sheaf::thread::
108 invariant() const
109 {
110 
111  bool result;
112 
113  result = (_thread_list != 0);
114 
115  return result;
116 }
117 
118 
120 void
121 sheaf::thread::
122 join()
123 {
124 
125  // preconditions:
126 
130 
131  // body:
132 
133  int rtn_code = pthread_join(pthread,0);
134 
135  // postconditions:
136 
137  ensure(rtn_code == 0);
138 }
139 
140 
142 void
143 sheaf::thread::
144 run()
145 {
146 
147  // body:
148 
149  // No-op intended to be overriden in descendant classes.
150 }
151 
152 
154 void
155 sheaf::thread::
156 start()
157 {
158 
159  // body:
160 
161  int rtncode = pthread_create(&pthread, // start a new thread
162  reinterpret_cast<pthread_attr_t *>(0), // with default attributes
163  static_run, // beginning execution at static function "static_run"
164  reinterpret_cast<void *>(this)); // with "this" as argument
165 
166  // postconditions:
167 
168  ensure(rtncode == 0);
169 
170 }
171 
172 
173 void *
174 sheaf::thread::
175 static_run(thread* This)
176 {
177 
178  // preconditions:
179 
180  require(This != 0);
181  require(! is_alive(This));
182 
183  // body:
184 
185  pthread_cleanup_push(cleanup,This);
186 
187  This->_is_alive = true;
188 
189  if (This->_runnable == 0)
190  This->run();
191  else
192  This->_runnable->run();
193 
194  This->_is_alive = false;
195 
196  pthread_cleanup_pop(1);
197 
198  // postconditions:
199 
200  ensure(! is_alive(This));
201 
202 }
203 
204 
206 void
207 sheaf::thread::
208 sleep(unsigned int seconds)
209 {
210 
211  // body:
212 
213  ::sleep(seconds);
214 }
215 
216 
218 bool
219 sheaf::thread::
220 is_alive(thread* other)
221 {
222 
223  // preconditions:
224 
225  require(other != 0);
226 
227  // body:
228 
235 
236  bool result;
237 
238  if(_thread_list != 0)
239  {
240 
241  singly_linked_list<thread *>::iterator it = _thread_list->begin();
242  singly_linked_list<thread *>::iterator end = _thread_list->end();
243 
244  for (; it != end && *it != other; ++it)
245  ;
246 
247  if (it != end && (*it)->_is_alive)
248  result = true;
249  else
250  result = false;
251  }
252  else
253  result = false;
254 
255  return result;
256 }
257 
258 
260 thread *
261 sheaf::thread::
262 current_thread()
263 {
264 
265  // body:
266 
267  pthread_t self = pthread_self();
268 
269  thread *result;
270 
271  singly_linked_list<thread *> *list = sheaf::thread::_thread_list;
272 
273  if (list != 0)
274  {
275 
276  singly_linked_list<thread *>::iterator it = list->begin();
277  singly_linked_list<thread *>::iterator end = list->end();
278 
279  for (; it != end && (pthread_equal(self,(*it)->pthread) == 0); ++it)
280  ;
281 
282  if (it == end)
283  result = 0; // called from main thread - outside a "thread"
284  else
285  result = *it;
286  }
287  else
288  result = 0;
289 
290  return result;
291 
292 }
293 
294 
295 void
296 sheaf::thread::
297 cleanup(thread* This)
298 {
299 
300  // preconditions:
301 
302  require(This != 0);
303  require(! is_alive(This));
304 
305  // body:
306 
307  singly_linked_list<thread *>::iterator it = _thread_list->begin();
308  singly_linked_list<thread *>::iterator end = _thread_list->end();
309 
310  for (; it != end && *it != This; ++it)
311  ;
312 
313  assertion(it != end);
314 
315  This->_thread_list->erase(it);
316 
317  // postconditions:
318 
319 }
320 
321 
323 int
324 sheaf::thread::
325 active_count()
326 {
327 
328  // body:
329 
330  int result;
331 
332  singly_linked_list<thread *> *list = sheaf::thread::_thread_list;
333 
334  result = list->size();
335 
336  // postconditions:
337 
340 
341  ensure(result >= 0);
342 
343  return result;
344 
345 }
346 
347 
349 void
350 sheaf::thread::
351 stop()
352 {
353 
354  // body:
355 
356  int rtncode = pthread_cancel(pthread);
357 
358  // postconditions:
359 
360  ensure(rtncode == 0);
361 
362 }
363 
364 #endif // _PTHREADS