My Project
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
20struct Board;
21struct Move;
22struct Line;
23
24// for winsock & winsock2 collision
25#ifdef _WIN32
26#include <winsock2.h>
27#endif
28
29/*
30 * Time management
31 */
32extern long long (*time_clock)(void);
33long long real_clock(void);
34long long cpu_clock(void);
35void time_print(long long, bool, FILE*);
36long long time_read(FILE*);
37void time_stamp(FILE*);
38void relax(int);
39
40/*
41 * Special printing function
42 */
43char* format_scientific(double, const char*, char*);
44void print_scientific(double, const char*, FILE*);
45
46/*
47 * Strings
48 */
49char* string_duplicate(const char*);
50long long string_to_time(const char*);
51char* string_read_line(FILE*);
52char* string_copy_line(FILE*);
53void string_to_lowercase(char*);
54void string_to_uppercase(char*);
55int string_to_coordinate(const char*);
56char* string_to_word(char*);
57bool string_to_boolean(const char*);
58int string_to_int(const char*, const int);
59double string_to_real(const char*, const double);
60/*
61 * Parsing
62 */
63char* parse_word(const char*, char*, unsigned int);
64char* parse_field(const char*, char*, unsigned int, char);
65char* parse_line(const char*, char*, unsigned int);
66char* parse_board(const char*, struct Board*, int*);
67char* parse_move(const char*, const struct Board*, struct Move*);
68char* parse_game(const char*, const struct Board*, struct Line*);
69char* parse_boolean(const char*, bool*);
70char* parse_int(const char*, int*);
71char* parse_real(const char*, double*);
72char* parse_command(const char*, char*, char*, const unsigned int);
73char* parse_find(const char*, const int);
74char* parse_skip_spaces(const char*);
75char* parse_skip_word(const char*);
76
77/*
78 * File.
79 */
80FILE* file_open(const char*, const char*);
81void path_get_dir(const char*, char*);
82char* file_add_ext(const char*, const char*, char*);
84
85/*
86 * random
87 */
88typedef struct Random {
89 unsigned long long x;
91
92unsigned long long random_get(Random*);
93void random_seed(Random*, const unsigned long long);
94
95/*
96 * Usefull macros
97 */
99#define MAX(a, b) ((a) > (b) ? (a) : (b))
100
102#define MIN(a, b) ((a) < (b) ? (a) : (b))
103
105#define BOUND(var, min, max, name) do {\
106 if (var < min && min <= max) {\
107 if (name) fprintf(stderr, "\nWARNING: %s = %lld is out of range. Set to %lld\n", name, (long long)var, (long long)min);\
108 var = min;\
109 } else if (var > max) {\
110 if (name) fprintf(stderr, "\nWARNING: %s = %lld is out of range. Set to %lld\n", name, (long long)var, (long long)max);\
111 var = max;\
112 }\
113} while (0)
114
115
116/*
117 *Threads
118 */
119#if defined(__unix__) || (defined(_WIN32) && defined(USE_PTHREAD)) || defined(__APPLE__)
120
121#include <pthread.h>
122
124typedef pthread_t Thread;
125
127typedef pthread_mutex_t Lock;
128
130typedef pthread_cond_t Condition;
131
133#define thread_detach(thread) pthread_detach(thread)
134
135#if DEBUG && defined(__unix__) && !defined(__APPLE__)
137#define lock(c) if (pthread_mutex_lock(&(c)->lock)) { \
138 error("lock"); \
139} else (void) 0
140
142#define unlock(c) if (pthread_mutex_unlock(&(c)->lock)) { \
143 error("unlock"); \
144} else (void) 0
145
147#define lock_init(c) do {\
148 pthread_mutexattr_t attr;\
149 pthread_mutexattr_init(&attr);\
150 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);\
151 pthread_mutex_init(&(c)->lock, &attr);\
152} while (0)
153
155#define lock_free(c) if (pthread_mutex_destroy(&(c)->lock)) { \
156 error("lock_free"); \
157} else (void) 0
158
159#else //NDEBUG
160
162#define lock(c) pthread_mutex_lock(&(c)->lock)
163
165#define unlock(c) pthread_mutex_unlock(&(c)->lock)
166
168#define lock_init(c) pthread_mutex_init(&(c)->lock, NULL)
169
171#define lock_free(c) pthread_mutex_destroy(&(c)->lock)
172
173#endif
174
175#ifdef __APPLE__ // Mac OS spinlock
176
177#include <libkern/OSAtomic.h>
178
180typedef OSSpinLock SpinLock;
181
183#define spin_lock(c) OSSpinLockLock(&(c)->spin)
184
186#define spin_unlock(c) OSSpinLockUnlock(&(c)->spin)
187
189#define spin_init(c) do {(c)->spin = OS_SPINLOCK_INIT;} while (0)
190
192#define spin_free(c) // FIXME ?? should this stay empty ?
193
194
195#elif defined(__USE_XOPEN2K) // Posix spinlock
196
198typedef pthread_spinlock_t SpinLock;
199
201#define spin_lock(c) pthread_spin_lock(&(c)->spin)
202
204#define spin_unlock(c) pthread_spin_unlock(&(c)->spin)
205
207#define spin_init(c) pthread_spin_init(&(c)->spin, PTHREAD_PROCESS_PRIVATE)
208
210#define spin_free(c) pthread_spin_destroy(&(c)->spin)
211
212#else // No spin lock available, use mutex instead
213
215typedef pthread_mutex_t SpinLock;
216
218#define spin_lock(c) pthread_mutex_lock(&(c)->spin)
219
221#define spin_unlock(c) pthread_mutex_unlock(&(c)->spin)
222
224#define spin_init(c) pthread_mutex_init(&(c)->spin, NULL)
225
227#define spin_free(c) pthread_mutex_destroy(&(c)->spin)
228
229#endif
230
232#define condition_init(c) pthread_cond_init(&(c)->cond, NULL)
233
235#define condition_wait(c) pthread_cond_wait(&(c)->cond, &(c)->lock)
236
238#define condition_signal(c) pthread_cond_signal(&(c)->cond)
239
241#define condition_broadcast(c) pthread_cond_broadcast(&(c)->cond)
242
244#define condition_free(c) pthread_cond_destroy(&(c)->cond)
245
246#elif defined(_WIN32)
247
248#include <windows.h>
249
251typedef HANDLE Thread;
252
254typedef CRITICAL_SECTION Lock;
255
257typedef CRITICAL_SECTION SpinLock;
258
260#if defined(_WIN64)
261
262#ifndef _MSC_VER
263
264//typedef DWORD CONDITION_VARIABLE;
265void InitializeConditionVariable(CONDITION_VARIABLE*);
266void WakeConditionVariable(CONDITION_VARIABLE*);
267void WakeAllConditionVariable(CONDITION_VARIABLE*);
268BOOL SleepConditionVariableCS(CONDITION_VARIABLE*, CRITICAL_SECTION*, DWORD);
269
270#endif
271
273typedef CONDITION_VARIABLE Condition;
274
276#define condition_init(c) InitializeConditionVariable(&(c)->cond)
277
279#define condition_wait(c) SleepConditionVariableCS(&(c)->cond, &(c)->lock, INFINITE)
280
282#define condition_signal(c) WakeConditionVariable(&(c)->cond)
283
285#define condition_broadcast(c) WakeAllConditionVariable(&(c)->cond)
286
288#define condition_free(c)
289
290#endif
291
293#define thread_detach(thread) CloseHandle(thread)
294
296#define lock(c) EnterCriticalSection(&(c)->lock)
297
299#define unlock(c) LeaveCriticalSection(&(c)->lock)
300
302#define lock_init(c) InitializeCriticalSection(&(c)->lock)
303
305#define lock_free(c) DeleteCriticalSection(&(c)->lock)
306
308#define spin_lock(c) EnterCriticalSection(&(c)->spin)
309
311#define spin_unlock(c) LeaveCriticalSection(&(c)->spin)
312
314#define spin_init(c) InitializeCriticalSection(&(c)->spin)
315
317#define spin_free(c) DeleteCriticalSection(&(c)->spin)
318
319
320#endif
321
322void thread_create2(Thread*, void* (*f)(void*), void*); // modified for iOS by lavox. 2018/1/16
323void thread_join(Thread);
324void thread_set_cpu(Thread, int);
325Thread thread_self(void);
326
328static inline void atomic_add(volatile unsigned long long *value, long long i)
329{
330#if defined(USE_GAS_X64)
331 __asm__ __volatile__("lock xaddq %1, %0":"=m"(*value) :"r"(i), "m" (*value));
332#elif defined(USE_MSVC_X64)
333 _InterlockedAdd64(value, i);
334#else
335 *value += i;
336#endif
337}
338
339void cpu(void);
340int get_cpu_number(void);
341
342/*
343 * Error management
344 */
345
350#define fatal_error(...) \
351 do { \
352 fprintf(stderr, "\nFATAL ERROR: %s : %s : %d : ", __FILE__, __func__, __LINE__); \
353 if (errno) fprintf(stderr, "\terror #%d : %s", errno, strerror(errno)); \
354 fputc('\n', stderr); \
355 fprintf(stderr, __VA_ARGS__); \
356 abort(); \
357 } while (0)
358
362#define error(...) \
363 do { \
364 fprintf(stderr, "\nERROR: %s : %s : %d :", __FILE__, __func__, __LINE__); \
365 if (errno) fprintf(stderr, " error #%d : %s", errno, strerror(errno)); \
366 fputc('\n', stderr); \
367 fprintf(stderr, __VA_ARGS__); \
368 errno = 0; \
369 } while (0)
370
374#define warn(...) \
375 do { \
376 fprintf(stderr, "\nWARNING: "); \
377 fprintf(stderr, __VA_ARGS__); \
378 } while (0)
379
383#define info(...) if (options.info) { \
384 fprintf(stderr, __VA_ARGS__); \
385} else (void) 0
386
390#define cassio_debug(...) if (options.debug_cassio) { \
391 printf("DEBUG: "); \
392 printf(__VA_ARGS__); \
393 log_print(engine_log, "DEBUG: "); \
394 log_print(engine_log, __VA_ARGS__);\
395} else (void) 0
396
397
398#ifndef NDEBUG
402#define trace(...) do {\
403 fprintf(stderr, "trace %s : %s : %d : ", __FILE__, __func__, __LINE__); \
404 fprintf(stderr, __VA_ARGS__); \
405} while (0)
406
410#define debug(...) \
411 do { \
412 fprintf(stderr, "\nDEBUG : "); \
413 fprintf(stderr, __VA_ARGS__); \
414 } while (0)
415
416#else
417#define trace(...)
418#define debug(...)
419#endif
420
424typedef struct Log {
425 FILE *f;
426 Lock lock;
428
430#define log_open(l, file) if ((l)->f == NULL && file != NULL) { \
431 lock_init(l); \
432 (l)->f = fopen(file, "w"); \
433} else (void) 0
434
436#define log_close(l) if ((l)->f) { \
437 lock_free(l); \
438 fclose((l)->f); \
439 (l)->f = NULL; \
440} else (void) 0
441
443#define log_print(l, ...) if ((l)->f) { \
444 fprintf((l)->f, __VA_ARGS__); \
445 fflush((l)->f); \
446} else (void) 0
447
449#define log_is_open(l) ((l)->f != NULL)
450
452#define log_receive(l, title, ...) if ((l)->f) { \
453 fprintf((l)->f, "%s", title); \
454 time_stamp((l)->f); \
455 fprintf((l)->f, " <== "); \
456 fprintf((l)->f, __VA_ARGS__); \
457 fflush((l)->f); \
458} else (void) 0
459
461#define log_send(l, title, ...) if ((l)->f) { \
462 fprintf((l)->f, "%s", title); \
463 time_stamp((l)->f); \
464 fprintf((l)->f, " ==> "); \
465 fprintf((l)->f, __VA_ARGS__); \
466 fflush((l)->f); \
467} else (void) 0
468
469#endif // EDAX_UTIL_H
Definition board.h:26
Definition move.h:35
LogFile.
Definition util.h:424
Lock lock
Definition util.h:426
FILE * f
Definition util.h:425
Definition move.h:20
Definition util.h:88
unsigned long long x
Definition util.h:89
char * parse_boolean(const char *, bool *)
Parse a boolean.
Definition util.c:807
char * file_add_ext(const char *, const char *, char *)
Add an extension to a string.
Definition util.c:973
char * parse_move(const char *, const struct Board *, struct Move *)
char * parse_int(const char *, int *)
Parse an integer.
Definition util.c:827
struct Log Log
LogFile.
char * parse_command(const char *, char *, char *, const unsigned int)
Parse a command.
Definition util.c:933
char * string_copy_line(FILE *)
void time_print(long long, bool, FILE *)
Print time as "D:HH:MM:SS.CC".
Definition util.c:197
long long real_clock(void)
char * parse_skip_spaces(const char *)
Skip spaces.
Definition util.c:580
long long time_read(FILE *)
read time as "D:HH:MM:SS.C".
Definition util.c:222
long long cpu_clock(void)
int string_to_int(const char *, const int)
Convert a string into an integer.
Definition util.c:523
struct Random Random
void time_stamp(FILE *)
Print local time.
Definition util.c:255
long long(* time_clock)(void)
Time clock.
Definition util.c:188
FILE * file_open(const char *, const char *)
Open a file from a UTF-8 path on Windows.
Definition util.c:78
void random_seed(Random *, const unsigned long long)
Pseudo-random number seed.
Definition util.c:1128
char * parse_real(const char *, double *)
Parse a real number (as a double floating point).
Definition util.c:862
int string_to_coordinate(const char *)
Convert the two first chars of a string into a coordinate.
Definition util.c:450
void print_scientific(double, const char *, FILE *)
Print a value with a unit.
Definition util.c:316
char * parse_line(const char *, char *, unsigned int)
Parse a line.
Definition util.c:670
bool is_stdin_keyboard(void)
void relax(int)
sleep for t ms.
Definition util.c:269
char * parse_skip_word(const char *)
Skip word.
Definition util.c:594
char * parse_game(const char *, const struct Board *, struct Line *)
char * string_read_line(FILE *)
Read a line.
Definition util.c:331
void thread_create2(Thread *, void *(*f)(void *), void *)
Create a thread.
Definition util.c:988
static void atomic_add(volatile unsigned long long *value, long long i)
Definition util.h:328
char * parse_board(const char *, struct Board *, int *)
Parse a board.
Definition util.c:748
int get_cpu_number(void)
Get the number of cpus or cores on the machine.
Definition util.c:1053
void path_get_dir(const char *, char *)
Extract the directory of a file path.
Definition util.c:954
void thread_join(Thread)
Join a thread.
Definition util.c:1006
void string_to_uppercase(char *)
Change all char of a string to uppercase.
Definition util.c:435
char * string_to_word(char *)
remove spaces from a string.
Definition util.c:477
char * parse_field(const char *, char *, unsigned int, char)
Parse a field.
Definition util.c:648
double string_to_real(const char *, const double)
Convert a string into a real number.
Definition util.c:554
unsigned long long random_get(Random *)
Pseudo-random number generator.
Definition util.c:1109
char * string_duplicate(const char *)
Duplicate a string.
Definition util.c:365
char * parse_find(const char *, const int)
Find a char.
Definition util.c:611
void cpu(void)
long long string_to_time(const char *)
Read time as "D:HH:MM:SS.C".
Definition util.c:386
char * format_scientific(double, const char *, char *)
Format a value with a unit.
Definition util.c:288
char * parse_word(const char *, char *, unsigned int)
Parse a word.
Definition util.c:628
bool string_to_boolean(const char *)
Convert a string into a boolean.
Definition util.c:498
void string_to_lowercase(char *)
Change all char of a string to lowercase.
Definition util.c:421
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:1033
Thread thread_self(void)
Current thread.
Definition util.c:1020