util.h
Go to the documentation of this file.
1 
11 #ifndef EDAX_UTIL_H
12 #define EDAX_UTIL_H
13 
14 #include <stdio.h>
15 #include <stdbool.h>
16 #include <stdlib.h>
17 #include <errno.h>
18 #include <string.h>
19 
20 struct Board;
21 struct Move;
22 struct Line;
23 
24 // for winsock & winsock2 collision
25 #ifdef _WIN32
26 #include <winsock2.h>
27 #endif
28 
29 /*
30  * Time management
31  */
32 extern long long (*time_clock)(void);
33 long long real_clock(void);
34 long long cpu_clock(void);
35 void time_print(long long, bool, FILE*);
36 long long time_read(FILE*);
37 void time_stamp(FILE*);
38 void relax(int);
39 
40 /*
41  * Special printing function
42  */
43 char* format_scientific(double, const char*, char*);
44 void print_scientific(double, const char*, FILE*);
45 
46 /*
47  * Strings
48  */
49 char* string_duplicate(const char*);
50 long long string_to_time(const char*);
51 char* string_read_line(FILE*);
52 char* string_copy_line(FILE*);
53 void string_to_lowercase(char*);
54 void string_to_uppercase(char*);
55 int string_to_coordinate(const char*);
56 char* string_to_word(char*);
57 bool string_to_boolean(const char*);
58 int string_to_int(const char*, const int);
59 double string_to_real(const char*, const double);
60 /*
61  * Parsing
62  */
63 char* parse_word(const char*, char*, unsigned int);
64 char* parse_field(const char*, char*, unsigned int, char);
65 char* parse_line(const char*, char*, unsigned int);
66 char* parse_board(const char*, struct Board*, int*);
67 char* parse_move(const char*, const struct Board*, struct Move*);
68 char* parse_game(const char*, const struct Board*, struct Line*);
69 char* parse_boolean(const char*, bool*);
70 char* parse_int(const char*, int*);
71 char* parse_real(const char*, double*);
72 char* parse_command(const char*, char*, char*, const unsigned int);
73 char* parse_find(const char*, const int);
74 char* parse_skip_spaces(const char*);
75 char* parse_skip_word(const char*);
76 
77 /*
78  * File.
79  */
80 void path_get_dir(const char*, char*);
81 char* file_add_ext(const char*, const char*, char*);
82 bool is_stdin_keyboard(void);
83 
84 /*
85  * random
86  */
87 typedef struct Random {
88  unsigned long long x;
89 } Random;
90 
91 unsigned long long random_get(Random*);
92 void random_seed(Random*, const unsigned long long);
93 
94 /*
95  * Usefull macros
96  */
98 #define MAX(a, b) ((a) > (b) ? (a) : (b))
99 
101 #define MIN(a, b) ((a) < (b) ? (a) : (b))
102 
104 #define BOUND(var, min, max, name) do {\
105  if (var < min && min <= max) {\
106  if (name) fprintf(stderr, "\nWARNING: %s = %lld is out of range. Set to %lld\n", name, (long long)var, (long long)min);\
107  var = min;\
108  } else if (var > max) {\
109  if (name) fprintf(stderr, "\nWARNING: %s = %lld is out of range. Set to %lld\n", name, (long long)var, (long long)max);\
110  var = max;\
111  }\
112 } while (0)
113 
114 
115 /*
116  *Threads
117  */
118 #if defined(__unix__) || (defined(_WIN32) && defined(USE_PTHREAD)) || defined(__APPLE__)
119 
120 #include <pthread.h>
121 
123 typedef pthread_t Thread;
124 
126 typedef pthread_mutex_t Lock;
127 
129 typedef pthread_cond_t Condition;
130 
132 #define thread_detach(thread) pthread_detach(thread)
133 
134 #if DEBUG && defined(__unix__) && !defined(__APPLE__)
135 
136 #define lock(c) if (pthread_mutex_lock(&(c)->lock)) { \
137  error("lock"); \
138 } else (void) 0
139 
141 #define unlock(c) if (pthread_mutex_unlock(&(c)->lock)) { \
142  error("unlock"); \
143 } else (void) 0
144 
146 #define lock_init(c) do {\
147  pthread_mutexattr_t attr;\
148  pthread_mutexattr_init(&attr);\
149  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);\
150  pthread_mutex_init(&(c)->lock, &attr);\
151 } while (0)
152 
154 #define lock_free(c) if (pthread_mutex_destroy(&(c)->lock)) { \
155  error("lock_free"); \
156 } else (void) 0
157 
158 #else //NDEBUG
159 
161 #define lock(c) pthread_mutex_lock(&(c)->lock)
162 
164 #define unlock(c) pthread_mutex_unlock(&(c)->lock)
165 
167 #define lock_init(c) pthread_mutex_init(&(c)->lock, NULL)
168 
170 #define lock_free(c) pthread_mutex_destroy(&(c)->lock)
171 
172 #endif
173 
174 #ifdef __APPLE__ // Mac OS spinlock
175 
176 #include <libkern/OSAtomic.h>
177 
179 typedef OSSpinLock SpinLock;
180 
182 #define spin_lock(c) OSSpinLockLock(&(c)->spin)
183 
185 #define spin_unlock(c) OSSpinLockUnlock(&(c)->spin)
186 
188 #define spin_init(c) do {(c)->spin = OS_SPINLOCK_INIT;} while (0)
189 
191 #define spin_free(c) // FIXME ?? should this stay empty ?
192 
193 
194 #elif defined(__USE_XOPEN2K) // Posix spinlock
195 
197 typedef pthread_spinlock_t SpinLock;
198 
200 #define spin_lock(c) pthread_spin_lock(&(c)->spin)
201 
203 #define spin_unlock(c) pthread_spin_unlock(&(c)->spin)
204 
206 #define spin_init(c) pthread_spin_init(&(c)->spin, PTHREAD_PROCESS_PRIVATE)
207 
209 #define spin_free(c) pthread_spin_destroy(&(c)->spin)
210 
211 #else // No spin lock available, use mutex instead
212 
214 typedef pthread_mutex_t SpinLock;
215 
217 #define spin_lock(c) pthread_mutex_lock(&(c)->spin)
218 
220 #define spin_unlock(c) pthread_mutex_unlock(&(c)->spin)
221 
223 #define spin_init(c) pthread_mutex_init(&(c)->spin, NULL)
224 
226 #define spin_free(c) pthread_mutex_destroy(&(c)->spin)
227 
228 #endif
229 
231 #define condition_init(c) pthread_cond_init(&(c)->cond, NULL)
232 
234 #define condition_wait(c) pthread_cond_wait(&(c)->cond, &(c)->lock)
235 
237 #define condition_signal(c) pthread_cond_signal(&(c)->cond)
238 
240 #define condition_broadcast(c) pthread_cond_broadcast(&(c)->cond)
241 
243 #define condition_free(c) pthread_cond_destroy(&(c)->cond)
244 
245 #elif defined(_WIN32)
246 
247 #include <windows.h>
248 
250 typedef HANDLE Thread;
251 
253 typedef CRITICAL_SECTION Lock;
254 
256 typedef CRITICAL_SECTION SpinLock;
257 
259 #if defined(_WIN64)
260 
261 #ifndef _MSC_VER
262 
263 //typedef DWORD CONDITION_VARIABLE;
264 void InitializeConditionVariable(CONDITION_VARIABLE*);
265 void WakeConditionVariable(CONDITION_VARIABLE*);
266 void WakeAllConditionVariable(CONDITION_VARIABLE*);
267 BOOL SleepConditionVariableCS(CONDITION_VARIABLE*, CRITICAL_SECTION*, DWORD);
268 
269 #endif
270 
272 typedef CONDITION_VARIABLE Condition;
273 
275 #define condition_init(c) InitializeConditionVariable(&(c)->cond)
276 
278 #define condition_wait(c) SleepConditionVariableCS(&(c)->cond, &(c)->lock, INFINITE)
279 
281 #define condition_signal(c) WakeConditionVariable(&(c)->cond)
282 
284 #define condition_broadcast(c) WakeAllConditionVariable(&(c)->cond)
285 
287 #define condition_free(c)
288 
289 #endif
290 
292 #define thread_detach(thread) CloseHandle(thread)
293 
295 #define lock(c) EnterCriticalSection(&(c)->lock)
296 
298 #define unlock(c) LeaveCriticalSection(&(c)->lock)
299 
301 #define lock_init(c) InitializeCriticalSection(&(c)->lock)
302 
304 #define lock_free(c) DeleteCriticalSection(&(c)->lock)
305 
307 #define spin_lock(c) EnterCriticalSection(&(c)->spin)
308 
310 #define spin_unlock(c) LeaveCriticalSection(&(c)->spin)
311 
313 #define spin_init(c) InitializeCriticalSection(&(c)->spin)
314 
316 #define spin_free(c) DeleteCriticalSection(&(c)->spin)
317 
318 
319 #endif
320 
321 void thread_create2(Thread*, void* (*f)(void*), void*); // modified for iOS by lavox. 2018/1/16
322 void thread_join(Thread);
323 void thread_set_cpu(Thread, int);
324 Thread thread_self(void);
325 
327 static inline void atomic_add(volatile unsigned long long *value, long long i)
328 {
329 #if defined(USE_GAS_X64)
330  __asm__ __volatile__("lock xaddq %1, %0":"=m"(*value) :"r"(i), "m" (*value));
331 #elif defined(USE_MSVC_X64)
332  _InterlockedAdd64(value, i);
333 #else
334  *value += i;
335 #endif
336 }
337 
338 void cpu(void);
339 int get_cpu_number(void);
340 
341 /*
342  * Error management
343  */
344 
349 #define fatal_error(...) \
350  do { \
351  fprintf(stderr, "\nFATAL ERROR: %s : %s : %d : ", __FILE__, __func__, __LINE__); \
352  if (errno) fprintf(stderr, "\terror #%d : %s", errno, strerror(errno)); \
353  fputc('\n', stderr); \
354  fprintf(stderr, __VA_ARGS__); \
355  abort(); \
356  } while (0)
357 
361 #define error(...) \
362  do { \
363  fprintf(stderr, "\nERROR: %s : %s : %d :", __FILE__, __func__, __LINE__); \
364  if (errno) fprintf(stderr, " error #%d : %s", errno, strerror(errno)); \
365  fputc('\n', stderr); \
366  fprintf(stderr, __VA_ARGS__); \
367  errno = 0; \
368  } while (0)
369 
373 #define warn(...) \
374  do { \
375  fprintf(stderr, "\nWARNING: "); \
376  fprintf(stderr, __VA_ARGS__); \
377  } while (0)
378 
382 #define info(...) if (options.info) { \
383  fprintf(stderr, __VA_ARGS__); \
384 } else (void) 0
385 
389 #define cassio_debug(...) if (options.debug_cassio) { \
390  printf("DEBUG: "); \
391  printf(__VA_ARGS__); \
392  log_print(engine_log, "DEBUG: "); \
393  log_print(engine_log, __VA_ARGS__);\
394 } else (void) 0
395 
396 
397 #ifndef NDEBUG
398 
401 #define trace(...) do {\
402  fprintf(stderr, "trace %s : %s : %d : ", __FILE__, __func__, __LINE__); \
403  fprintf(stderr, __VA_ARGS__); \
404 } while (0)
405 
409 #define debug(...) \
410  do { \
411  fprintf(stderr, "\nDEBUG : "); \
412  fprintf(stderr, __VA_ARGS__); \
413  } while (0)
414 
415 #else
416 #define trace(...)
417 #define debug(...)
418 #endif
419 
423 typedef struct Log {
424  FILE *f;
425  Lock lock;
426 } Log;
427 
429 #define log_open(l, file) if ((l)->f == NULL && file != NULL) { \
430  lock_init(l); \
431  (l)->f = fopen(file, "w"); \
432 } else (void) 0
433 
435 #define log_close(l) if ((l)->f) { \
436  lock_free(l); \
437  fclose((l)->f); \
438  (l)->f = NULL; \
439 } else (void) 0
440 
442 #define log_print(l, ...) if ((l)->f) { \
443  fprintf((l)->f, __VA_ARGS__); \
444  fflush((l)->f); \
445 } else (void) 0
446 
448 #define log_is_open(l) ((l)->f != NULL)
449 
451 #define log_receive(l, title, ...) if ((l)->f) { \
452  fprintf((l)->f, "%s", title); \
453  time_stamp((l)->f); \
454  fprintf((l)->f, " <== "); \
455  fprintf((l)->f, __VA_ARGS__); \
456  fflush((l)->f); \
457 } else (void) 0
458 
460 #define log_send(l, title, ...) if ((l)->f) { \
461  fprintf((l)->f, "%s", title); \
462  time_stamp((l)->f); \
463  fprintf((l)->f, " ==> "); \
464  fprintf((l)->f, __VA_ARGS__); \
465  fflush((l)->f); \
466 } else (void) 0
467 
468 #endif // EDAX_UTIL_H
char * parse_command(const char *, char *, char *, const unsigned int)
Parse a command.
Definition: util.c:867
char * parse_find(const char *, const int)
Find a char.
Definition: util.c:545
unsigned long long random_get(Random *)
Pseudo-random number generator.
Definition: util.c:1043
char * parse_skip_word(const char *)
Skip word.
Definition: util.c:528
char * parse_word(const char *, char *, unsigned int)
Parse a word.
Definition: util.c:562
Definition: util.h:87
int string_to_coordinate(const char *)
Convert the two first chars of a string into a coordinate.
Definition: util.c:384
struct Random Random
void path_get_dir(const char *, char *)
Extract the directory of a file path.
Definition: util.c:888
Lock lock
Definition: util.h:425
int string_to_int(const char *, const int)
Convert a string into an integer.
Definition: util.c:457
Definition: move.h:20
char * string_to_word(char *)
remove spaces from a string.
Definition: util.c:411
char * parse_real(const char *, double *)
Parse a real number (as a double floating point).
Definition: util.c:796
char * format_scientific(double, const char *, char *)
Format a value with a unit.
Definition: util.c:222
void random_seed(Random *, const unsigned long long)
Pseudo-random number seed.
Definition: util.c:1062
Definition: board.h:26
char * parse_line(const char *, char *, unsigned int)
Parse a line.
Definition: util.c:604
void time_print(long long, bool, FILE *)
Print time as "D:HH:MM:SS.CC".
Definition: util.c:131
char * parse_field(const char *, char *, unsigned int, char)
Parse a field.
Definition: util.c:582
void thread_create2(Thread *, void *(*f)(void *), void *)
Create a thread.
Definition: util.c:922
char * string_duplicate(const char *)
Duplicate a string.
Definition: util.c:299
long long real_clock(void)
long long string_to_time(const char *)
Read time as "D:HH:MM:SS.C".
Definition: util.c:320
void thread_set_cpu(Thread, int)
Choose a single core or cpu to run on, under linux systems, to avoid context changes.
Definition: util.c:967
void print_scientific(double, const char *, FILE *)
Print a value with a unit.
Definition: util.c:250
void thread_join(Thread)
Join a thread.
Definition: util.c:940
char * file_add_ext(const char *, const char *, char *)
Add an extension to a string.
Definition: util.c:907
char * string_read_line(FILE *)
Read a line.
Definition: util.c:265
char * parse_game(const char *, const struct Board *, struct Line *)
void cpu(void)
Definition: move.h:35
static void atomic_add(volatile unsigned long long *value, long long i)
Definition: util.h:327
bool is_stdin_keyboard(void)
void relax(int)
sleep for t ms.
Definition: util.c:203
struct Log Log
LogFile.
int get_cpu_number(void)
Get the number of cpus or cores on the machine.
Definition: util.c:987
unsigned long long x
Definition: util.h:88
FILE * f
Definition: util.h:424
char * parse_int(const char *, int *)
Parse an integer.
Definition: util.c:761
char * parse_boolean(const char *, bool *)
Parse a boolean.
Definition: util.c:741
long long cpu_clock(void)
long long time_read(FILE *)
read time as "D:HH:MM:SS.C".
Definition: util.c:156
void string_to_uppercase(char *)
Change all char of a string to uppercase.
Definition: util.c:369
char * parse_move(const char *, const struct Board *, struct Move *)
long long(* time_clock)(void)
Time clock.
Definition: util.c:122
char * string_copy_line(FILE *)
char * parse_skip_spaces(const char *)
Skip spaces.
Definition: util.c:514
void time_stamp(FILE *)
Print local time.
Definition: util.c:189
void string_to_lowercase(char *)
Change all char of a string to lowercase.
Definition: util.c:355
char * parse_board(const char *, struct Board *, int *)
Parse a board.
Definition: util.c:682
bool string_to_boolean(const char *)
Convert a string into a boolean.
Definition: util.c:432
double string_to_real(const char *, const double)
Convert a string into a real number.
Definition: util.c:488
Thread thread_self(void)
Current thread.
Definition: util.c:954
LogFile.
Definition: util.h:423