Noble Ape
The Central Directories of the Noble Ape Simulation.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
execute.c
Go to the documentation of this file.
1 /****************************************************************
2 
3  execute.c
4 
5  =============================================================
6 
7  Copyright 1996-2014 Tom Barbalet. All rights reserved.
8 
9  Permission is hereby granted, free of charge, to any person
10  obtaining a copy of this software and associated documentation
11  files (the "Software"), to deal in the Software without
12  restriction, including without limitation the rights to use,
13  copy, modify, merge, publish, distribute, sublicense, and/or
14  sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following
16  conditions:
17 
18  The above copyright notice and this permission notice shall be
19  included in all copies or substantial portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  OTHER DEALINGS IN THE SOFTWARE.
29 
30  This software and Noble Ape are a continuing work of Tom Barbalet,
31  begun on 13 June 1996. No apes or cats were harmed in the writing
32  of this software.
33 
34  ****************************************************************/
35 
36 #include "noble.h"
37 
38 
39 #ifdef EXECUTE_THREADED
40 
41 #ifdef _WIN32
42 
43 #include <windows.h>
44 #include <tchar.h>
45 #include <strsafe.h>
46 
47 #else
48 
49 #include <pthread.h>
50 #include <time.h>
51 
52 
53 #endif
54 
55 typedef enum
56 {
57  ES_DONE = 0,
61 
62 typedef struct
63 {
64  execute_function * function;
65  void * general_data;
66  void * read_data;
67  void * write_data;
71 
72 typedef struct
73 {
76  n_byte2 random[2];
78 
79 static n_int global_cycle = 1;
80 static n_int execution_cycle = 0;
81 
82 
83 #ifdef _WIN32
84 
85 static HANDLE *thread = 0L;
86 static DWORD *threadId = 0L;
87 
88 #else
89 
90 static pthread_t *thread = 0L;
91 
92 #endif
93 
94 static execution_thread *execution = 0L;
95 
96 static n_int execution_thread_size = 4;
97 
98 static void execute_wait_ns(void)
99 {
100  /* In time cycle testing this may be seen to be wasted time
101  the problem however is the execution is not available
102  */
103 #ifndef _WIN32
104  struct timespec tim, tim2;
105  tim.tv_sec = 0;
106  tim.tv_nsec = 1;
107  (void)nanosleep(&tim , &tim2);
108 #endif
109 }
110 #endif
111 
112 static void execute_add_generic(execute_function * function, void * general_data, void * read_data, void * write_data, n_int count, n_int size)
113 {
114 #ifndef EXECUTE_THREADED
115  if (size)
116  {
117  n_byte *location = (n_byte *)read_data;
118  n_int loop = 0;
119  while (loop < count)
120  {
121  if (function(general_data, (void *)&location[loop * size], 0L) == -1)
122  {
123  break;
124  }
125  loop++;
126  }
127  }
128  else
129  {
130  function(general_data,read_data,write_data);
131  }
132 #else
133  execution_cycle = 1;
134  do{
135  n_int loop = 0;
136  while (loop < execution_thread_size)
137  {
138  if (execution[loop].state == ES_DONE)
139  {
140  execute_object * new_object = io_new(sizeof(execute_object));
141  new_object->function = function;
142  new_object->general_data = general_data;
143  new_object->read_data = read_data;
144  new_object->write_data = write_data;
145  new_object->count = count;
146  new_object->size = size;
147  execution[loop].executed = new_object;
148  execution[loop].state = ES_WAITING;
149  return;
150  }
151 
152  loop++;
153  }
154  }while (global_cycle);
155 #endif
156 }
157 
158 void execute_add(execute_function * function, void * general_data, void * read_data, void * write_data)
159 {
160  execute_add_generic(function, general_data, read_data, write_data, 1, 0);
161 }
162 
163 void execute_group(execute_function * function, void * general_data, void * read_data, n_int count, n_int size)
164 {
165  execute_add_generic(function, general_data, read_data, 0L, count, size);
166 }
167 
169 {
170 #ifdef EXECUTE_THREADED
171  while (1 == 1)
172  {
173  if (execution_cycle == 0)
174  break;
175  execute_wait_ns();
176  }
177 #endif
178 }
179 
180 void execute_close(void)
181 {
182 #ifdef EXECUTE_THREADED
183  global_cycle = 0;
184 #ifdef _WIN32
185  {
186  n_int loop = 0;
187  while (loop < execution_thread_size)
188  {
189  CloseHandle(thread[loop]);
190  loop++;
191  }
192  }
193 #endif
194 #endif
195 }
196 
198 {
199 #ifdef EXECUTE_THREADED
200  execution_thread_size = value;
201 #else
202  (void)value;
203 #endif
204 }
205 
207 {
208 #ifdef EXECUTE_THREADED
209  return execution_thread_size;
210 #else
211  return 1;
212 #endif
213 }
214 
215 #ifdef EXECUTE_THREADED
216 
217 static void execute_thread_generic(void * id)
218 {
219  execution_thread * value = id;
220  do{
221  n_int loop = 0;
222  n_int all_idle = 1;
223  if (value->state != ES_WAITING)
224  {
225  if ((math_random(value->random) & 255) == 1)
226  {
227  execute_wait_ns();
228  }
229  }
230  if (value->state == ES_WAITING)
231  {
232  execute_object * object = value->executed;
233  value->state = ES_STARTED;
234 
235  if (object->size)
236  {
237  n_byte *location = (n_byte *)object->read_data;
238  n_int loop = 0;
239  while (loop < object->count)
240  {
241  if (object->function(object->general_data, (void *)&location[loop * object->size], 0L) == -1)
242  {
243  execute_close();
244  break;
245  }
246  loop++;
247  }
248  }
249  else
250  {
251  if (object->function(object->general_data, object->read_data, object->write_data) == -1)
252  {
253  execute_close();
254  }
255  }
256  value->state = ES_DONE;
257  io_free((void **)&object);
258  }
259  loop = 0;
260  while (loop < execution_thread_size)
261  {
262  if (execution[loop].state != ES_DONE)
263  {
264  all_idle = 0;
265  break;
266  }
267  loop++;
268  }
269  if (all_idle)
270  {
271  execution_cycle = 0;
272  }
273  }while (global_cycle);
274 
275 }
276 
277 #ifdef _WIN32
278 
279 static DWORD WINAPI execute_thread_win( LPVOID lpParam )
280 {
281  HANDLE hStdout;
282  hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
283  if( hStdout == INVALID_HANDLE_VALUE )
284  return 1;
285  execute_thread_generic((void *)lpParam);
286  return 0;
287 }
288 
289 #else
290 
291 static void * execute_thread_posix(void * id)
292 {
293  execute_thread_generic(id);
294  pthread_exit(0L);
295 }
296 
297 #endif
298 #endif
299 
300 void execute_init(void)
301 {
302 #ifdef EXECUTE_THREADED
303  n_int loop = 0;
304  n_byte2 master_random[2] = {0xf672, 0x3e71};
305 
306 
307 #ifdef _WIN32
308  thread = (HANDLE*)io_new(execution_thread_size * sizeof(HANDLE));
309 #else
310  thread = (pthread_t*)io_new(execution_thread_size * sizeof(pthread_t));
311 #endif
312 
313  if (thread == 0L)
314  {
315  (void)SHOW_ERROR("Threads failed to allocate");
316  return;
317  }
318 
319 #ifdef _WIN32
320  threadId = (DWORD*)io_new(execution_thread_size * sizeof(DWORD));
321  if (threadId == 0L)
322  {
323  io_free((void **)&thread);
324  (void)SHOW_ERROR("ThreadIds failed to allocate");
325  return;
326  }
327 #endif
328 
329  execution = (execution_thread *)io_new(execution_thread_size * sizeof(execution_thread));
330 
331  if (execution == 0L)
332  {
333  io_free((void **)&thread);
334 #ifdef _WIN32
335  io_free((void **)&threadId);
336 #endif
337  (void)SHOW_ERROR("Execution thread failed to allocate");
338  return;
339  }
340 #ifdef _WIN32
341  io_erase((n_byte*)thread, execution_thread_size * sizeof(HANDLE));
342  io_erase((n_byte*)threadId, execution_thread_size * sizeof(DWORD));
343 #else
344  io_erase((n_byte*)thread, execution_thread_size * sizeof(pthread_t));
345 #endif
346  io_erase((n_byte*)execution, execution_thread_size * sizeof(execution_thread));
347 
348  while (loop < execution_thread_size)
349  {
350  execution[loop].random[0] = master_random[1];
351  execution[loop].random[1] = master_random[0];
352 
353  math_random3(master_random);
354 
355 #ifdef _WIN32
356  threadId[loop] = loop;
357  thread[loop] = CreateThread(NULL, 0, execute_thread_win, &execution[loop], 0, &threadId[loop]);
358 #else
359  pthread_create(&thread[loop], 0L, execute_thread_posix, &execution[loop]);
360 #endif
361  loop++;
362  }
363 #endif
364 }