add a 'append' mode for the ringbuffer
[nobug.git] / src / nobug.h
blob294a9487f2b6af62f0f5686d453799ebaf798563
1 /*
2 This file is part of the NoBug debugging library.
4 Copyright (C)
5 2007, 2008, 2009 Christian Thaeter <ct@pipapo.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
20 #ifndef NOBUG_H
21 #define NOBUG_H
23 #ifndef NOBUG_LIBNOBUG_C /* not when building libnobug */
24 #ifdef NDEBUG
25 #ifdef EBUG_ALPHA
26 #error NDEBUG incompatible with -DEBUG_ALPHA
27 #endif
28 #ifdef EBUG_BETA
29 #error NDEBUG incompatible with -DEBUG_BETA
30 #endif
31 #endif
33 #if defined(EBUG_ALPHA)
34 # define NOBUG_MODE_ALPHA 1
35 # define NOBUG_MODE_BETA 0
36 # define NOBUG_MODE_RELEASE 0
37 #elif defined(EBUG_BETA)
38 # define NOBUG_MODE_ALPHA 0
39 # define NOBUG_MODE_BETA 1
40 # define NOBUG_MODE_RELEASE 0
41 #elif defined(NDEBUG)
42 # define NOBUG_MODE_ALPHA 0
43 # define NOBUG_MODE_BETA 0
44 # define NOBUG_MODE_RELEASE 1
45 #else
46 #error no debug level and no NDEBUG defined
47 #endif
48 #endif /* NOBUG_LIBNOBUG_C */
51 HEADERS
54 #include <syslog.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <stdio.h>
58 #include <stdarg.h>
60 #ifdef HAVE_EXECINFO_H
61 # ifndef NOBUG_USE_EXECINFO
62 # define NOBUG_USE_EXECINFO 1
63 # endif
64 #else
65 # undef NOBUG_USE_EXECINFO
66 # define NOBUG_USE_EXECINFO 0
67 #endif
69 #if NOBUG_USE_EXECINFO
70 #include <execinfo.h>
71 #endif
73 #if defined(HAVE_VALGRIND) && !defined(NVALGRIND)
74 # ifndef NOBUG_USE_VALGRIND
75 # define NOBUG_USE_VALGRIND 1
76 # endif
77 #else
78 # undef NOBUG_USE_VALGRIND
79 # define NOBUG_USE_VALGRIND 0
80 #endif
82 #if NOBUG_USE_VALGRIND
83 #include <valgrind.h>
84 #endif
86 #ifdef HAVE_PTHREAD
87 # ifndef NOBUG_USE_PTHREAD
88 # define NOBUG_USE_PTHREAD 1
89 # endif
90 #else
91 # ifdef NOBUG_USE_PTHREAD
92 # undef NOBUG_USE_PTHREAD
93 # endif
94 # define NOBUG_USE_PTHREAD 0
95 #endif
97 #if NOBUG_USE_PTHREAD
98 #include <pthread.h>
99 #endif
102 //assertions HEAD- Assertions;;
103 //assertions
104 //assertions PARA CHECK; CHECK; unnconditional assertion for testsuites
105 //assertions CHECK(expr, ...)
106 //assertions CHECK_IF(when, expr, ...)
107 //assertions
108 //assertions This assertion is never optimized out. Its main purpose is for implementing
109 //assertions testsuites where one want to assert tests independent of the build level
110 //assertions
112 #define NOBUG_CHECK(expr, ...) \
113 NOBUG_ASSERT_(expr, "CHECK", NOBUG_LOCATION_INFO, ## __VA_ARGS__)
115 #define NOBUG_CHECK_IF(when, expr, ...) \
116 NOBUG_WHEN(when, NOBUG_CHECK(expr, ## __VA_ARGS__))
120 //assertions PARA REQUIRE; REQUIRE; preconditions (input parameters)
121 //assertions REQUIRE(expr, ...)
122 //assertions REQUIRE_DBG(expr, ...)
123 //assertions REQUIRE_IF(when, expr, ...)
124 //assertions REQUIRE_IF_DBG(when, expr, ...)
125 //assertions
126 //assertions Precondition (input) check. Use these macros to validate input a
127 //assertions function receives. The checks are enabled in *ALPHA* and *BETA* builds and
128 //assertions optimized out in *RELEASE* builds.
129 //assertions
131 #define NOBUG_REQUIRE(expr, ...) \
132 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", \
133 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
136 #define NOBUG_REQUIRE_DBG(expr, ...) \
137 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_DBG_(expr, "PRECONDITION", \
138 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
141 #define NOBUG_REQUIRE_IF(when, expr, ...) \
142 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_REQUIRE(expr, ## __VA_ARGS__)))
144 #define NOBUG_REQUIRE_IF_DBG(when, expr, ...) \
145 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_REQUIRE_DBG(expr, ## __VA_ARGS__)))
149 //assertions PARA ENSURE; ENSURE; postconditions (computation outcomes)
150 //assertions ENSURE(expr, ...)
151 //assertions ENSURE_DBG(expr, ...)
152 //assertions ENSURE_IF(when, expr, ...)
153 //assertions ENSURE_IF_DBG(when, expr, ...)
154 //assertions
155 //assertions Postcondition (progress/output) check. Use these macros to validate the
156 //assertions data a function produces (example: return value). The checks enabled
157 //assertions unconditionally in *ALPHA* builds and optimized out in *BETA* builds for
158 //assertions scopes which are tagged as `CHECKED`. In *RELEASE* builds this checks are
159 //assertions always optimized out, but scopes tagged as `UNCHECKED` are not permitted.
160 //assertions
162 #define NOBUG_ENSURE(expr, ...) \
163 NOBUG_IF_ALPHA (NOBUG_ASSERT_(expr, "POSTCONDITION", \
164 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
165 NOBUG_IF_BETA ( \
166 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
167 NOBUG_ASSERT_(expr, "POSTCONDITION", \
168 NOBUG_LOCATION_INFO, ## __VA_ARGS__))\
171 #define NOBUG_ENSURE_DBG(expr, ...) \
172 NOBUG_IF_ALPHA (NOBUG_ASSERT_DBG_ (expr, "POSTCONDITION", \
173 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
174 NOBUG_IF_BETA ( \
175 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
176 NOBUG_ASSERT_DBG_(expr, "POSTCONDITION", \
177 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
181 #define NOBUG_ENSURE_IF(when, expr, ...) \
182 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE(expr, ## __VA_ARGS__)))
184 #define NOBUG_ENSURE_IF_DBG(when, expr, ...) \
185 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE_DBG(expr, ## __VA_ARGS__)))
189 //assertions PARA ASSERT; ASSERT; generic assertion
190 //assertions ASSERT(expr, ...)
191 //assertions ASSERT_DBG(expr, ...)
192 //assertions ASSERT_IF(when, expr, ...)
193 //assertions ASSERT_IF_DBG(when, expr, ...)
194 //assertions
195 //assertions Generic check. Use these macros when you want to validate something
196 //assertions which doesn't fall into one of the above categories. A example is when
197 //assertions a library function can return a unexpected result (scanf with syntax
198 //assertions error in the formatstring, when a constant/literal formatstring is
199 //assertions expected). The checks are enabled in *ALPHA* and *BETA* builds and
200 //assertions optimized out in *RELEASE* builds.
201 //assertions
203 #define NOBUG_ASSERT(expr, ...) \
204 NOBUG_IF_NOT_RELEASE( \
205 NOBUG_ASSERT_(expr, "ASSERTION", \
206 NOBUG_LOCATION_INFO, ## __VA_ARGS__) \
209 #define NOBUG_ASSERT_DBG(expr, ...) \
210 NOBUG_IF_NOT_RELEASE( \
211 NOBUG_ASSERT_DBG_(expr, "ASSERTION", \
212 NOBUG_LOCATION_INFO, ## __VA_ARGS__) \
215 #define NOBUG_ASSERT_IF(when, expr, ...) \
216 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT(expr, ## __VA_ARGS__)))
218 #define NOBUG_ASSERT_IF_DBG(when, expr, ...) \
219 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT_DBG(expr, ## __VA_ARGS__)))
223 //assertions PARA assert; assert; C standard assertion
224 //assertions assert(expr)
225 //assertions
226 //assertions NoBug overrides the standard assert macro in *ALPHA* and *BETA* builds.
227 //assertions This is just a compatibility feature, its use is not suggested.
228 //assertions
230 #if NOBUG_MODE_RELEASE==0
231 #undef assert
232 #define assert(expr) NOBUG_ASSERT(expr)
233 #endif
237 low level assert
239 #define NOBUG_ASSERT_(expr, what, location, ...) \
240 NOBUG_WHEN (!(expr), \
241 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
242 location, what, "(%s) " \
243 NOBUG_HEAD(__VA_ARGS__), \
244 #expr NOBUG_TAIL(__VA_ARGS__)); \
245 NOBUG_BACKTRACE; \
246 NOBUG_ABORT \
249 #define NOBUG_ASSERT_DBG_(expr, what, location, ...) \
250 NOBUG_WHEN (NOBUG_ACTIVE_DBG && !(expr), \
251 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
252 location, what, "(%s) " \
253 NOBUG_HEAD(__VA_ARGS__), \
254 #expr NOBUG_TAIL(__VA_ARGS__)); \
255 NOBUG_BACKTRACE; \
256 NOBUG_ABORT \
261 //assertions PARA INVARIANT; INVARIANT; validate invariant state
262 //assertions INVARIANT(type, pointer, depth)
263 //assertions INVARIANT_DBG(type, pointer, depth)
264 //assertions INVARIANT_IF(when,type, pointer, depth)
265 //assertions INVARIANT_IF_DBG(when, type, pointer, depth)
266 //assertions
267 //assertions Checking invariants. You can provide more complex checking functions
268 //assertions which test the validity of datastructures. Invariants are only enabled
269 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
270 //assertions otherwise optimized out.
271 //assertions
272 //assertions TODO: describe how to create invariant checks
273 //assertions
275 #define NOBUG_INVARIANT(type, pointer, depth) \
276 NOBUG_IF_ALPHA( \
277 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
278 NOBUG_CAT(type,_invariant)(pointer, depth, \
279 NOBUG_LOCATION_ARGS) \
283 #define NOBUG_INVARIANT_DBG(type, pointer, ...) \
284 NOBUG_IF_ALPHA( \
285 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED && NOBUG_ACTIVE_DBG, \
286 NOBUG_CAT(type,_invariant)(pointer, depth, \
287 NOBUG_LOCATION_ARGS) \
291 #define NOBUG_INVARIANT_IF(when, type, pointer, ...) \
292 NOBUG_IF_ALPHA (NOBUG_WHEN (when, \
293 NOBUG_INVARIANT(type, pointer, ## __VA_ARGS__)) \
296 #define NOBUG_INVARIANT_IF_DBG(when, type, pointer, ...) \
297 NOBUG_IF_ALPHA (NOBUG_WHEN (when, \
298 NOBUG_INVARIANT_DBG(type, pointer, ## __VA_ARGS__))\
301 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
302 NOBUG_ASSERT_(expr, "INVARIANT", (file, line, func), ## __VA_ARGS__)
306 checked/unchecked tagged scopes
308 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
310 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
312 #define NOBUG_UNCHECKED \
313 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
314 NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
318 /*TODO dump-level for flags instead limits[0]*/
320 //dumpmacros PARA DUMP; DUMP; dumping datastructures
321 //dumpmacros DUMP(flag, type, pointer, depth)
322 //dumpmacros DUMP_IF(when, flag, type, pointer, depth)
323 //dumpmacros
324 //dumpmacros This macros call a datastructure dump of the object (`pointer`) in question.
325 //dumpmacros `DUMP_IF` is the only enabled dumping macro for the RELEASE build level.
326 //dumpmacros
328 #define NOBUG_DUMP(flag, type, pointer, depth) \
329 NOBUG_IF_NOT_RELEASE( \
330 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
331 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
332 NOBUG_LOCATION_ARGS) \
336 #define NOBUG_DUMP_DBG(flag, type, pointer, depth) \
337 NOBUG_IF_NOT_RELEASE( \
338 NOBUG_WHEN (NOBUG_ACTIVE_DBG && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
339 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
340 NOBUG_LOCATION_ARGS) \
344 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth) \
345 NOBUG_WHEN (when && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
346 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
347 NOBUG_LOCATION_ARGS) \
350 #define NOBUG_DUMP_IF_DBG(when, flag, type, pointer, depth) \
351 NOBUG_IF_NOT_RELEASE( \
352 NOBUG_WHEN (NOBUG_ACTIVE_DBG && when && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET],\
353 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
354 NOBUG_LOCATION_ARGS) \
360 //dumpmacros PARA DUMP_LOG; DUMP_LOG; logging helper for dumping
361 //dumpmacros DUMP_LOG(fmt, ...)
362 //dumpmacros DUMP_LOG_DBG(fmt, ...)
363 //dumpmacros DUMP_LOG_IF(when, fmt, ...)
364 //dumpmacros DUMP_LOG_IF_DBG(when, fmt, ...)
365 //dumpmacros
366 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
367 //dumpmacros
368 //dumpmacros Dumping is by default done on level `LOG_DEBUG`, this can be overridden by
369 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other level.
370 //dumpmacros
372 #define NOBUG_DUMP_LOG(fmt, ...) \
373 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
374 (file, line, func), "DUMP", \
375 fmt, ## __VA_ARGS__)
378 #define NOBUG_DUMP_LOG_DBG(fmt, ...) \
379 NOBUG_WHEN (NOBUG_ACTIVE_DBG, \
380 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
381 (file, line, func), "DUMP", \
382 fmt, ## __VA_ARGS__) \
385 #define NOBUG_DUMP_LOG_IF(expr, fmt, ...) \
386 NOBUG_WHEN (expr, \
387 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
388 (file, line, func), "DUMP", \
389 fmt, ## __VA_ARGS__) \
392 #define NOBUG_DUMP_LOG_IF_DBG(expr, fmt, ...) \
393 NOBUG_WHEN (NOBUG_ACTIVE_DBG && expr, \
394 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
395 (file, line, func), "DUMP", \
396 fmt, ## __VA_ARGS__) \
400 #ifndef NOBUG_DUMP_LEVEL
401 #define NOBUG_DUMP_LEVEL LOG_DEBUG
402 #endif
405 //logmacros HEAD- Logging Macros;;
406 //logmacros
407 //logmacros PARA ECHO; ECHO; unconditional logging for tests
408 //logmacros ECHO(...)
409 //logmacros
410 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
411 //logmacros testsuites where one want to print and log messages independent of the build level
412 //logmacros
414 #define NOBUG_ECHO(...) \
415 NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_NOTICE, NOBUG_LOCATION_INFO, "ECHO", ## __VA_ARGS__)
418 //logmacros PARA ALERT; ALERT; about to die
419 //logmacros ALERT(flag, ...)
420 //logmacros ALERT_DBG(flag, ...)
421 //logmacros ALERT_IF(when, flag, ...)
422 //logmacros ALERT_IF_DBG(when, flag, ...)
423 //logmacros
424 //logmacros This is the most critical condition an application might log. This might be used
425 //logmacros if an error occurs which can not be handled except a safe shutdown for example.
426 //logmacros
428 #define NOBUG_ALERT(flag, ...) \
429 NOBUG_LOG(flag, LOG_ALERT, ## __VA_ARGS__)
430 #define NOBUG_ALERT_IF(expr, flag, ...) \
431 NOBUG_LOG_IF(expr, flag, LOG_ALERT, ## __VA_ARGS__)
432 #define NOBUG_ALERT_DBG(flag, ...) \
433 NOBUG_LOG_DBG(flag, LOG_ALERT, ## __VA_ARGS__)
434 #define NOBUG_ALERT_IF_DBG(expr, flag, ...) \
435 NOBUG_LOG_IF_DBG(expr, flag, LOG_ALERT, ## __VA_ARGS__)
438 //logmacros PARA CRITICAL; CRITICAL; can not continue
439 //logmacros CRITICAL(flag, ...)
440 //logmacros CRITICAL_DBG(flag, ...)
441 //logmacros CRITICAL_IF(when, flag, ...)
442 //logmacros CRITICAL_IF_DBG(when, flag, ...)
443 //logmacros
444 //logmacros An error which can not be handled occured but the application does not need to be
445 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
446 //logmacros
448 #define NOBUG_CRITICAL(flag, ...) \
449 NOBUG_LOG(flag, LOG_CRIT, ## __VA_ARGS__)
450 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
451 NOBUG_LOG_IF(expr, flag, LOG_CRIT, ## __VA_ARGS__)
452 #define NOBUG_CRITICAL_DBG(flag, ...) \
453 NOBUG_LOG_DBG(flag, LOG_CRIT, ## __VA_ARGS__)
454 #define NOBUG_CRITICAL_IF_DBG(expr, flag, ...) \
455 NOBUG_LOG_IF_DBG(expr, flag, LOG_CRIT, ## __VA_ARGS__)
458 //logmacros PARA ERROR; ERROR; something gone wrong
459 //logmacros ERROR(flag, fmt, ...)
460 //logmacros ERROR_DBG(flag, fmt, ...)
461 //logmacros ERROR_IF(when, flag, fmt, ...)
462 //logmacros ERROR_IF_DBG(when, flag, fmt, ...)
463 //logmacros
464 //logmacros Application takes a error handling brach
465 //logmacros
467 #define NOBUG_ERROR(flag, ...) \
468 NOBUG_LOG(flag, LOG_ERR, ## __VA_ARGS__)
469 #define NOBUG_ERROR_IF(expr, flag, ...) \
470 NOBUG_LOG_IF(expr, flag, LOG_ERR, ## __VA_ARGS__)
471 #define NOBUG_ERROR_DBG(flag, ...) \
472 NOBUG_LOG_DBG(flag, LOG_ERR, ## __VA_ARGS__)
473 #define NOBUG_ERROR_IF_DBG(expr, flag, ...) \
474 NOBUG_LOG_IF_DBG(expr, flag, LOG_ERR, ## __VA_ARGS__)
477 //logmacros PARA WARN; WARN; unexpected fixable error
478 //logmacros WARN(flag, fmt, ...)
479 //logmacros WARN_DBG(flag, fmt, ...)
480 //logmacros WARN_IF(when, flag, fmt, ...)
481 //logmacros WARN_IF_DBG(when, flag, fmt, ...)
482 //logmacros
483 //logmacros Rare, handled but unexpected branch
484 //logmacros
486 #define NOBUG_WARN(flag, ...) \
487 NOBUG_LOG(flag, LOG_WARNING, ## __VA_ARGS__)
488 #define NOBUG_WARN_IF(expr, flag, ...) \
489 NOBUG_LOG_IF(expr, flag, LOG_WARNING, ## __VA_ARGS__)
490 #define NOBUG_WARN_DBG(flag, ...) \
491 NOBUG_LOG_DBG(flag, LOG_WARNING, ## __VA_ARGS__)
492 #define NOBUG_WARN_IF_DBG(expr, flag, ...) \
493 NOBUG_LOG_IF_DBG(expr, flag, LOG_WARNING, ## __VA_ARGS__)
496 //logmacros PARA INFO; INFO; progress message
497 //logmacros INFO(flag, fmt, ...)
498 //logmacros INFO_DBG(flag, fmt, ...)
499 //logmacros INFO_IF(when, flag, fmt, ...)
500 //logmacros INFO_IF_DBG(when, flag, fmt, ...)
501 //logmacros
502 //logmacros Message about program progress
503 //logmacros
505 #define NOBUG_INFO(flag, ...) \
506 NOBUG_LOG(flag, LOG_INFO, ## __VA_ARGS__)
507 #define NOBUG_INFO_IF(expr, flag, ...) \
508 NOBUG_LOG_IF(expr, flag, LOG_INFO, ## __VA_ARGS__)
509 #define NOBUG_INFO_DBG(flag, ...) \
510 NOBUG_LOG_DBG(flag, LOG_INFO, ## __VA_ARGS__)
511 #define NOBUG_INFO_IF_DBG(expr, flag, ...) \
512 NOBUG_LOG_IF_DBG(expr, flag, LOG_INFO, ## __VA_ARGS__)
515 //logmacros PARA NOTICE; NOTICE; detailed progress message
516 //logmacros NOTICE(flag, fmt, ...)
517 //logmacros NOTICE_DBG(flag, fmt, ...)
518 //logmacros NOTICE_IF(when, flag, fmt, ...)
519 //logmacros NOTICE_IF_DBG(when, flag, fmt, ...)
520 //logmacros
521 //logmacros More detailed progress message
522 //logmacros
524 #define NOBUG_NOTICE(flag, ...) \
525 NOBUG_LOG(flag, LOG_NOTICE, ## __VA_ARGS__)
526 #define NOBUG_NOTICE_IF(expr, flag, ...) \
527 NOBUG_LOG_IF(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
528 #define NOBUG_NOTICE_DBG(flag, ...) \
529 NOBUG_LOG_DBG(flag, LOG_NOTICE, ## __VA_ARGS__)
530 #define NOBUG_NOTICE_IF_DBG(expr, flag, ...) \
531 NOBUG_LOG_IF_DBG(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
534 //logmacros PARA TRACE; TRACE; debugging level message
535 //logmacros TRACE(flag, fmt, ...)
536 //logmacros TRACE_DBG(flag, fmt, ...)
537 //logmacros TRACE_IF(when, flag, fmt, ...)
538 //logmacros TRACEIF_DBG(when, flag, fmt, ...)
539 //logmacros
540 //logmacros Very fine grained messages
541 //logmacros
542 //logmacros NOTE: that `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
543 //logmacros
545 #define NOBUG_TRACE(flag, ...) \
546 NOBUG_LOG(flag, LOG_DEBUG, ## __VA_ARGS__)
547 #define NOBUG_TRACE_IF(expr, flag, ...) \
548 NOBUG_LOG_IF(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
549 #define NOBUG_TRACE_DBG(flag, ...) \
550 NOBUG_LOG_DBG(flag, LOG_DEBUG, ## __VA_ARGS__)
551 #define NOBUG_TRACE_IF_DBG(expr, flag, ...) \
552 NOBUG_LOG_IF_DBG(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
556 //logmacros PARA LOG; LOG; generic logging
557 //logmacros LOG(flag, lvl, fmt, ...)
558 //logmacros LOG_DBG(flag, lvl, fmt, ...)
559 //logmacros LOG_IF(when, flag, lvl, fmt, ...)
560 //logmacros LOG_IF_DBG(when, flag, lvl, fmt, ...)
561 //logmacros
562 //logmacros Generic logging macro which takes the level explicitly,
563 //logmacros avoid this, unless you implement your own logging facilities.
564 //logmacros
566 #define NOBUG_LOG(flag, lvl, ...) \
567 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
568 NOBUG_LVL(lvl), ## __VA_ARGS__)
570 #define NOBUG_LOG_DBG(flag, lvl, ...) \
571 NOBUG_WHEN (NOBUG_ACTIVE_DBG, \
572 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
573 NOBUG_LVL(lvl), ## __VA_ARGS__) \
576 #define NOBUG_LOG_IF(expr, flag, lvl, ...) \
577 NOBUG_WHEN (expr, \
578 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
579 NOBUG_LVL(lvl), ## __VA_ARGS__) \
582 #define NOBUG_LOG_IF_DBG(expr, flag, lvl, ...) \
583 NOBUG_WHEN (NOBUG_ACTIVE_DBG && expr, \
584 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
585 NOBUG_LVL(lvl), ## __VA_ARGS__) \
590 low level logging handler
592 #define NOBUG_LOG_(flag, lvl, location, what, ...) \
593 NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER], \
594 NOBUG_LOGGING_LOCK; \
595 nobug_log (flag, lvl, \
596 "%.10llu: %s: %s:%d:"NOBUG_THREAD_ID_FMT(" ",":")" %s: " \
597 NOBUG_HEAD(__VA_ARGS__), ++nobug_counter, what, \
598 NOBUG_LOCATION_FILE location, \
599 NOBUG_LOCATION_LINE location NOBUG_THREAD_ID_COMMA, \
600 NOBUG_LOCATION_FUNC location NOBUG_TAIL(__VA_ARGS__)); \
601 NOBUG_LOGGING_UNLOCK; \
602 if (nobug_postlogging_callback) \
603 nobug_postlogging_callback (flag, lvl, NULL, nobug_callback_data) \
607 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
608 #define NOBUG_LVL_0 "EMERG"
609 #define NOBUG_LVL_1 "ALERT"
610 #define NOBUG_LVL_2 "CRIT"
611 #define NOBUG_LVL_3 "ERR"
612 #define NOBUG_LVL_4 "WARNING"
613 #define NOBUG_LVL_5 "NOTICE"
614 #define NOBUG_LVL_6 "INFO"
615 #define NOBUG_LVL_7 "TRACE"
618 //logmacros PARA LOG_BASELIMIT; LOG_BASELIMIT; minimum compliled-in logging limit
619 //logmacros NOBUG_LOG_BASELIMIT_ALPHA
620 //logmacros NOBUG_LOG_BASELIMIT_BETA
621 //logmacros NOBUG_LOG_BASELIMIT_RELEASE
622 //logmacros NOBUG_LOG_BASELIMIT
623 //logmacros
624 //logmacros anything more detailed than this base limits will be optimized out.
625 //logmacros This is used to reduce the logging overhead for *RELEASE* builds.
626 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
627 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
628 //logmacros builds to log the application progress only coarsely then.
629 //logmacros
630 //logmacros This macros can be defined before including 'nobug.h' to some other
631 //logmacros log level (as defined in 'syslog.h').
632 //logmacros
633 //logmacros NOTE: there is no logging macro for `LOG_EMERG` since this is used by the assertions as fatal message
634 //logmacros
636 #ifndef NOBUG_LOG_BASELIMIT_ALPHA
637 #define NOBUG_LOG_BASELIMIT_ALPHA LOG_DEBUG
638 #endif
640 #ifndef NOBUG_LOG_BASELIMIT_BETA
641 #define NOBUG_LOG_BASELIMIT_BETA LOG_DEBUG
642 #endif
644 #ifndef NOBUG_LOG_BASELIMIT_RELEASE
645 #define NOBUG_LOG_BASELIMIT_RELEASE LOG_NOTICE
646 #endif
648 #ifndef NOBUG_LOG_BASELIMIT
649 #define NOBUG_LOG_BASELIMIT \
650 NOBUG_IF_ALPHA(NOBUG_LOG_BASELIMIT_ALPHA) \
651 NOBUG_IF_BETA(NOBUG_LOG_BASELIMIT_BETA) \
652 NOBUG_IF_RELEASE(NOBUG_LOG_BASELIMIT_RELEASE)
653 #endif
656 //annotations HEAD- Source Annotations;;
657 //annotations
658 //annotations One can tagging features as:
659 //annotations
663 alpha beta release
664 DEPRECATED log nothing wont compile
666 //annotations PARA DEPRECATED; DEPRECATED; to be discarded in future
667 //annotations DEPRECATED(...)
668 //annotations
669 //annotations Something which shouldn't be used in future
670 //annotations
672 #define NOBUG_DEPRECATED(...) \
673 NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN, \
674 NOBUG_LOCATION_INFO, "DEPRECATED", ## __VA_ARGS__) \
676 NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
680 alpha beta release
681 UNIMPLEMENTED abort abort wont compile
683 //annotations PARA UNIMPLEMENTED; UNIMPLEMENTED; not yet implemented
684 //annotations UNIMPLEMENTED(...)
685 //annotations
686 //annotations not yet finished feature
687 //annotations
689 #define NOBUG_UNIMPLEMENTED(...) \
690 NOBUG_IF_NOT_RELEASE ( do { \
691 NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG, NOBUG_LOCATION_INFO, \
692 "UNIMPLEMENTED", ## __VA_ARGS__); \
693 NOBUG_ABORT; \
694 } while (0)) \
695 NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
699 alpha beta release
700 FIXME log wont compile wont compile
702 //annotations PARA FIXME; FIXME; known bug
703 //annotations FIXME(...)
704 //annotations
705 //annotations known bug to be fixed later
706 //annotations
708 #define NOBUG_FIXME(...) \
709 NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT, \
710 NOBUG_LOCATION_INFO, "FIXME", ## __VA_ARGS__)))\
711 NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(__VA_ARGS__)) \
712 NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
716 alpha beta release
717 TODO log log wont compile
719 //annotations PARA TODO; TODO; things to be done
720 //annotations TODO(...)
721 //annotations
722 //annotations enhancement to be done soon
723 //annotations
725 #define NOBUG_TODO(...) \
726 NOBUG_IF_NOT_RELEASE ( \
727 NOBUG_ONCE ( \
728 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE, NOBUG_LOCATION_INFO, \
729 "TODO", ## __VA_ARGS__); \
730 )) \
731 NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
735 alpha beta release
736 PLANNED log nothing nothing
738 //annotations PARA PLANNED; PLANNED; ideas for future
739 //annotations PLANNED(...)
740 //annotations
741 //annotations future enhancement
742 //annotations
744 #define NOBUG_PLANNED(...) \
745 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO, \
746 NOBUG_LOCATION_INFO, "PLANNED", ## __VA_ARGS__)))
750 alpha beta release
751 NOTREACHED abort abort nothing
753 //annotations PARA NOTREACHED; NOTREACHED; code path never taken
754 //annotations NOTREACHED(...)
755 //annotations
756 //annotations used to tag code-path which shall be never executed.
757 //annotations
759 #define NOBUG_NOTREACHED(...) \
760 NOBUG_IF_NOT_RELEASE( do { \
761 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
762 NOBUG_LOCATION_INFO, "NOTREACHED", ## __VA_ARGS__); \
763 NOBUG_ABORT; \
764 } while (0))
767 //annotations PARA ELSE_NOTREACHED; ELSE_NOTREACHED; alternative never taken
768 //annotations ELSE_NOTREACHED(...)
769 //annotations
770 //annotations same as `else NOTREACHED()`, but wholly optimized out in release builds.
771 //annotations
773 #define NOBUG_ELSE_NOTREACHED(...) \
774 NOBUG_IF_NOT_RELEASE( else do { \
775 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
776 NOBUG_LOCATION_INFO, "ELSE_NOTREACHED", ## __VA_ARGS__); \
777 NOBUG_ABORT; \
778 } while (0))
783 //faultinjection HEAD- Fault injection;;
784 //faultinjection
785 //faultinjection NoBug has some macros which can be used to simulate errorneous behaviour:
786 //faultinjection
787 //faultinjection PARA INJECT_GOODBAD; INJECT_GOODBAD; fault injection expression
788 //faultinjection INJECT_GOODBAD(expr, good, bad)
789 //faultinjection
790 //faultinjection substitutes to an expression and returns good when expr is false and
791 //faultinjection bad when expr is true. In BETA and RELEASE builds 'good' is always returned.
792 //faultinjection
794 #define NOBUG_INJECT_GOODBAD(expr, good, bad) \
795 NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);}),bad:good) \
796 NOBUG_IF_NOT_ALPHA(good)
800 //faultinjection PARA INJECT_FAULT; INJECT_FAULT; fault injection statement
801 //faultinjection INJECT_FAULT(expr, bad)
802 //faultinjection
803 //faultinjection substitutes to a statement which executes 'bad'
804 //faultinjection when expr is true. Optimitzed out in BETA and RELEASE builds.
805 //faultinjection
807 #define NOBUG_INJECT_FAULT(expr, bad) \
808 NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
812 //faultinjection PARA INJECT_LEVEL; INJECT_LEVEL; log level for fault injection
813 //faultinjection In both cases, when a fault is injected it will be logged at
814 //faultinjection `NOBUG_INJECT_LEVEL` (default: `LOG_NOTICE`). This can be defined
815 //faultinjection before including 'nobug.h' to override it.
816 //faultinjection
818 #define NOBUG_INJECT_LOG(msg) \
819 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
820 NOBUG_LOCATION_INFO, "INJECT_FAULT", \
821 msg)
824 #ifndef NOBUG_INJECT_LEVEL
825 #define NOBUG_INJECT_LEVEL LOG_NOTICE
826 #endif
830 Flag handling
832 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_, name)
834 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
837 #define NOBUG_DEFINE_FLAG(name) \
838 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
839 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
840 struct nobug_flag NOBUG_FLAG(name) = \
841 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
842 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
843 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
844 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
845 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
846 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
850 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
851 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
852 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
853 NOBUG_DECLARE_FLAG(parent); \
854 struct nobug_flag NOBUG_FLAG(name) = \
855 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
856 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
857 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
858 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
859 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
860 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
864 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) \
865 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
866 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
867 struct nobug_flag NOBUG_FLAG(name) = \
868 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
869 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
870 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
871 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
872 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
873 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
877 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
878 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
879 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
880 NOBUG_DECLARE_FLAG(parent); \
881 struct nobug_flag NOBUG_FLAG(name) = \
882 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
883 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
884 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
885 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
886 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
887 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
891 #define NOBUG_INIT_FLAG(name) \
892 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT)
895 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
896 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default)
899 #define NOBUG_CPP_DEFINE_FLAG(name) \
900 NOBUG_FLAG_IF_DECLAREONLY( \
901 NOBUG_DECLARE_FLAG(name); \
902 extern int nobug_cppflag_##name \
904 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
905 NOBUG_DEFINE_FLAG(name); \
906 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
910 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
911 NOBUG_FLAG_IF_DECLAREONLY( \
912 NOBUG_DECLARE_FLAG(name); \
913 extern int nobug_cppflag_##name \
915 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
916 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
917 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
921 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
922 NOBUG_FLAG_IF_DECLAREONLY( \
923 NOBUG_DECLARE_FLAG(name); \
924 extern int nobug_cppflag_##name \
926 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
927 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
928 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
932 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
933 NOBUG_FLAG_IF_DECLAREONLY( \
934 NOBUG_DECLARE_FLAG(name); \
935 extern int nobug_cppflag_##name \
937 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
938 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
939 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
943 #ifndef NOBUG_DECLARE_ONLY
944 #define NOBUG_DECLARE_ONLY 0
945 #endif
947 #define NOBUG_FLAG_IF_DECLAREONLY(...) \
948 NOBUG_IF(NOBUG_DECLARE_ONLY, __VA_ARGS__)
950 #define NOBUG_FLAG_IF_NOT_DECLAREONLY(...) \
951 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
953 #ifdef __cplusplus
954 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
955 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
956 #else
957 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
958 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, NOBUG_ERROR_CANT_DEFINE_AUTOINITIALIZED_CPP_FLAGS_IN_C)
959 #endif
961 #ifndef NOBUG_LOG_LIMIT_ALPHA
962 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
963 #endif
964 #ifndef NOBUG_LOG_LIMIT_BETA
965 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
966 #endif
967 #ifndef NOBUG_LOG_LIMIT_RELEASE
968 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
969 #endif
971 #ifndef NOBUG_LOG_LIMIT
972 # define NOBUG_LOG_LIMIT \
973 NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA) \
974 NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA) \
975 NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
976 #endif
978 #ifndef NOBUG_LOG_TARGET_ALPHA
979 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
980 #endif
981 #ifndef NOBUG_LOG_TARGET_BETA
982 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
983 #endif
984 #ifndef NOBUG_LOG_TARGET_RELEASE
985 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
986 #endif
988 #ifndef NOBUG_LOG_TARGET
989 # define NOBUG_LOG_TARGET \
990 NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA) \
991 NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA) \
992 NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
993 #endif
995 #define NOBUG_SET_LIMIT(flag, min) \
996 NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
1000 //resourcemacros HEAD~ Resource tracking macros;;
1001 //resourcemacros
1002 //resourcemacros INDEX RESOURCE_LOGGING; RESOURCE_LOGGING; switch resource logging on and off
1003 //resourcemacros INDEX RESOURCE_LOG_LEVEL; RESOURCE_LOG_LEVEL; select the log level for resource logging
1004 //resourcemacros
1005 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
1006 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
1007 //resourcemacros `LOG_DEBUG`.
1008 //resourcemacros
1010 #ifndef NOBUG_RESOURCE_LOGGING
1011 #define NOBUG_RESOURCE_LOGGING 1
1012 #endif
1014 #ifndef NOBUG_RESOURCE_LOG_LEVEL
1015 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
1016 #endif
1020 //resourcemacros PARA RESOURCE_HANDLE; RESOURCE_HANDLE; define resource handles
1021 //resourcemacros RESOURCE_HANDLE(name)
1022 //resourcemacros RESOURCE_HANDLE_INIT(name)
1023 //resourcemacros RESOURCE_USER(name)
1024 //resourcemacros RESOURCE_USER_INIT(name)
1025 //resourcemacros
1026 //resourcemacros Define and initialize handles for to track resources.
1027 //resourcemacros
1028 //resourcemacros `name`::
1029 //resourcemacros identifer to be used for the handle
1030 //resourcemacros
1031 //resourcemacros There are two kinds of handles, each resource itself is abstracted with a
1032 //resourcemacros `RESOURCE_HANDLE` and every access to this resources is tracked through a
1033 //resourcemacros `RESOURCE_USER` handle. These macros takes care that the declaration is optimized
1034 //resourcemacros out in the same manner as the rest of the resource tracker would be disabled.
1035 //resourcemacros You can still instantiate handles as `struct nobug_resource_record*` or
1036 //resourcemacros `struct nobug_resource_user*` in structures which must have a constant size
1037 //resourcemacros unconditional of the build level. The two `*_INIT` macros can be used to initialize
1038 //resourcemacros resource handles and are optimized out when the resource tracker gets disabled.
1039 //resourcemacros
1041 #define NOBUG_RESOURCE_HANDLE(handle) \
1042 NOBUG_IF_ALPHA(struct nobug_resource_record* handle)
1044 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1046 #define NOBUG_RESOURCE_USER(handle) \
1047 NOBUG_IF_ALPHA(struct nobug_resource_user* handle)
1049 #define NOBUG_RESOURCE_USER_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1053 //resourcemacros PARA RESOURCE_ANNOUNCE; RESOURCE_ANNOUNCE; publish new resources
1054 //resourcemacros RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
1055 //resourcemacros
1056 //resourcemacros Publishes resources.
1057 //resourcemacros
1058 //resourcemacros `flag`::
1059 //resourcemacros the NoBug flag which turns logging on for this macro
1060 //resourcemacros `type`::
1061 //resourcemacros a string which should denote the domain of the resource,
1062 //resourcemacros examples are "file", "mutex", "lock", "database" and so on
1063 //resourcemacros `name`::
1064 //resourcemacros the actual name of a named resource this as string which
1065 //resourcemacros together with type forms a unique identifier of the resource. `type` and
1066 //resourcemacros `name` must be available through the entire lifetime of the resource, using
1067 //resourcemacros literal strings is recommended
1068 //resourcemacros `identifier`::
1069 //resourcemacros a pointer which should be unique for this resource, any
1070 //resourcemacros kind of pointer will suffice, it is only used for identification. In
1071 //resourcemacros multithreaded applications the thread identifier becomes an additional
1072 //resourcemacros identifier
1073 //resourcemacros `handle`::
1074 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to point to
1075 //resourcemacros the newly created resource.
1076 //resourcemacros
1077 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
1078 //resourcemacros announced more than one time.
1079 //resourcemacros
1081 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
1082 NOBUG_RESOURCE_ANNOUNCE_RAW(&NOBUG_FLAG(flag), type, name, ptr, handle)
1084 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
1085 NOBUG_IF_ALPHA( do { \
1086 NOBUG_RESOURCE_LOCK; \
1087 NOBUG_REQUIRE(!handle, "Announced resource handle not initialized"); \
1088 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1089 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1090 NOBUG_LOCATION_INFO, "RESOURCE_ANNOUNCE", \
1091 "%s: %s@%p", type, name, ptr);) \
1092 NOBUG_RESOURCE_ASSERT(handle = nobug_resource_announce (type, name, ptr, \
1093 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__))), \
1094 "RESOURCE_ASSERT_ANNOUNCE", NOBUG_LOCATION_INFO, \
1095 "%s: %s@%p %s", type, name, ptr, nobug_resource_error); \
1096 NOBUG_RESOURCE_UNLOCK; \
1097 } while (0))
1101 //resourcemacros PARA RESOURCE_FORGET; RESOURCE_FORGET; remove resources
1102 //resourcemacros RESOURCE_FORGET(flag, handle)
1103 //resourcemacros
1104 //resourcemacros Removes resources that have become unavailable from the registry.
1105 //resourcemacros
1106 //resourcemacros `flag`::
1107 //resourcemacros the NoBug flag which turns logging on for this macro
1108 //resourcemacros `handle`::
1109 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1110 //resourcemacros
1111 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1112 //resourcemacros error is raised.
1113 //resourcemacros
1115 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1116 NOBUG_RESOURCE_FORGET_RAW(&NOBUG_FLAG(flag), handle)
1118 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1119 NOBUG_IF_ALPHA( do { \
1120 NOBUG_RESOURCE_LOCK; \
1121 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1122 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1123 "RESOURCE_FORGET", "%s: %s@%p", \
1124 handle?handle->type:"", \
1125 handle?handle->hdr.name:"", \
1126 handle?handle->object_id:NULL);) \
1127 NOBUG_RESOURCE_ASSERT(nobug_resource_forget (handle), \
1128 "RESOURCE_ASSERT_FORGET", NOBUG_LOCATION_INFO, "%s: %s@%p: %s", \
1129 handle?handle->type:"", \
1130 handle?handle->hdr.name:"", \
1131 handle?handle->object_id:NULL, \
1132 nobug_resource_error); \
1133 handle = NULL; \
1134 NOBUG_RESOURCE_UNLOCK; \
1135 } while (0))
1139 //resourcemacros PARA RESOURCE_ENTER; RESOURCE_ENTER; claim a resource
1140 //resourcemacros RESOURCE_ENTER(flag, announced, user, state, handle){...}
1141 //resourcemacros
1142 //resourcemacros Acquire a resource.
1143 //resourcemacros
1144 //resourcemacros `flag`::
1145 //resourcemacros nobug flag which turns logging on for this macro
1146 //resourcemacros `announced`::
1147 //resourcemacros the handle set by `RESOURCE_ANNOUNCE`
1148 //resourcemacros `user`::
1149 //resourcemacros a free-form identifier
1150 //resourcemacros `state`::
1151 //resourcemacros the initial state, one of `NOBUG_RESOURCE_WAITING`,
1152 //resourcemacros `NOBUG_RESOURCE_EXCLUSIVE`, `NOBUG_RESOURCE_RECURSIVE` or `NOBUG_RESOURCE_SHARED`
1153 //resourcemacros `handle`::
1154 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to the
1155 //resourcemacros entering node
1156 //resourcemacros
1157 //resourcemacros 'RESOURCE_ENTER()' acts like the head of a C loop statement, it ties to the following
1158 //resourcemacros (block-) statement. Entering and the user defined following statement are atomic.
1159 //resourcemacros This statement must not be left by break, return or any other kind of jump. NoBug does
1160 //resourcemacros not assert this (for for Performance reasons).
1161 //resourcemacros
1162 //resourcemacros .How to use it
1163 //resourcemacros [source,c]
1164 //resourcemacros ----
1165 //resourcemacros // in the simplest form just terminate it with a semicolon,
1166 //resourcemacros // no user statement is executed
1167 //resourcemacros NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle);
1168 //resourcemacros
1169 //resourcemacros // followed by a single statement
1170 //resourcemacros NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle)
1171 //resourcemacros lock_my_resource();
1172 //resourcemacros
1173 //resourcemacros // or a block statement
1174 //resourcemacros NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle)
1175 //resourcemacros {
1176 //resourcemacros lock_my_resource();
1177 //resourcemacros }
1178 //resourcemacros ----
1179 //resourcemacros
1181 #define NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle) \
1182 for ( \
1183 int nobug_locked_ = ({ \
1184 NOBUG_REQUIRE(resource, "Announced resource handle not initialized"); \
1185 NOBUG_REQUIRE(!handle, "Resource handle already entered"); \
1186 NOBUG_RESOURCE_LOCK; \
1187 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1188 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, \
1189 NOBUG_LOCATION_INFO, "RESOURCE_ENTER", \
1190 "%s: %s@%p: %s: %s", \
1191 resource?resource->type:"", \
1192 resource?resource->hdr.name:"", \
1193 resource?resource->object_id:NULL, \
1194 user, \
1195 nobug_resource_states[state]);) \
1196 NOBUG_RESOURCE_ASSERT(handle = \
1197 nobug_resource_enter (resource, \
1198 user, state, \
1199 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__))), \
1200 "RESOURCE_ASSERT_ENTER", NOBUG_LOCATION_INFO, \
1201 "%s: %s@%p: %s: %s: %s", \
1202 resource?resource->type:"", \
1203 resource?resource->hdr.name:"", \
1204 resource?resource->object_id:NULL, \
1205 user, nobug_resource_states[state], \
1206 nobug_resource_error); \
1207 1; \
1208 }); \
1209 nobug_locked_; \
1210 NOBUG_RESOURCE_UNLOCK, nobug_locked_ = 0)
1213 //resourcemacros PARA RESOURCE_WAIT; RESOURCE_WAIT; wait for a resource to become available
1214 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle)
1215 //resourcemacros
1216 //resourcemacros This is just an alias for RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1217 //resourcemacros
1218 //resourcemacros .How to use it
1219 //resourcemacros [source,c]
1220 //resourcemacros ----
1221 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle)
1222 //resourcemacros {
1223 //resourcemacros if (lock_my_resource() == ERROR)
1224 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle);
1225 //resourcemacros else
1226 //resourcemacros RESOURCE_STATE(flag, NOBUG_RESOURCE_EXCLUSIVE, handle);
1227 //resourcemacros }
1228 //resourcemacros ----
1229 #define NOBUG_RESOURCE_WAIT(flag, resource, user, handle) \
1230 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1234 //resourcemacros PARA RESOURCE_STATE; RESOURCE_STATE; change the state of a resource
1235 //resourcemacros RESOURCE_STATE(flag, entered, state)
1236 //resourcemacros
1237 //resourcemacros Changes resource's state.
1238 //resourcemacros
1239 //resourcemacros `flag`::
1240 //resourcemacros is nobug flag which turns logging on for this macro
1241 //resourcemacros `state`::
1242 //resourcemacros the new state Note that only certain state transitions are
1243 //resourcemacros allowed, see discussion/diagram above
1244 //resourcemacros `entered`::
1245 //resourcemacros the handle set by `RESOURCE_ENTER`
1246 //resourcemacros
1247 //resourcemacros 'RESOURCE_STATE()' acts like the head of a C loop statement, it ties to the following
1248 //resourcemacros (block-) statement. Entering and the user defined following statement are atomic.
1249 //resourcemacros This statement must not be left by break, return or any other kind of jump. NoBug does
1250 //resourcemacros not assert this (for for Performance reasons).
1251 //resourcemacros
1253 #define NOBUG_RESOURCE_STATE(flag, state, entered) \
1254 NOBUG_RESOURCE_STATE_RAW(&NOBUG_FLAG(flag), state, entered)
1257 #define NOBUG_RESOURCE_STATE_RAW(flag, nstate, entered) \
1258 NOBUG_IF_ALPHA( \
1259 for ( \
1260 int nobug_locked_ = ({ \
1261 NOBUG_RESOURCE_LOCK; \
1262 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1263 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1264 "RESOURCE_STATE", "%s: %s@%p: %s: %s->%s", \
1265 entered?entered->current->resource->type:"", \
1266 entered?entered->current->resource->hdr.name:"", \
1267 entered?entered->current->resource->object_id:"", \
1268 entered?entered->hdr.name:"", \
1269 nobug_resource_states[entered?entered->state \
1270 :NOBUG_RESOURCE_INVALID], \
1271 nobug_resource_states[nstate]); \
1273 NOBUG_RESOURCE_ASSERT(nobug_resource_state (entered, nstate), \
1274 "RESOURCE_ASSERT_STATE", NOBUG_LOCATION_INFO, \
1275 "%s: %s@%p: %s: %s->%s: %s", \
1276 entered?entered->current->resource->type:"", \
1277 entered?entered->current->resource->hdr.name:"", \
1278 entered?entered->current->resource->object_id:"", \
1279 entered?entered->hdr.name:"", \
1280 nobug_resource_states[entered?entered->state \
1281 :NOBUG_RESOURCE_INVALID], \
1282 nobug_resource_states[nstate], \
1283 nobug_resource_error); \
1284 1; \
1285 }); \
1286 nobug_locked_; \
1287 NOBUG_RESOURCE_UNLOCK, nobug_locked_ = 0))
1291 //resourcemacros PARA RESOURCE_LEAVE; RESOURCE_LEAVE; relinquish a claimed resource
1292 //resourcemacros RESOURCE_LEAVE(flag, handle)
1293 //resourcemacros
1294 //resourcemacros Disconnect from a resource identified with its handle.
1295 //resourcemacros
1296 //resourcemacros `flag`::
1297 //resourcemacros nobug flag which turns logging on for this macro
1298 //resourcemacros `handle`::
1299 //resourcemacros the handle you got while entering the resource
1300 //resourcemacros
1301 //resourcemacros 'RESOURCE_LEAVE()' acts like the head of a C loop statement, it ties to the following
1302 //resourcemacros (block-) statement. Entering and the user defined following statement are atomic.
1303 //resourcemacros This statement must not be left by break, return or any other kind of jump. NoBug does
1304 //resourcemacros not assert this (for for Performance reasons).
1305 //resourcemacros
1307 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1308 NOBUG_RESOURCE_LEAVE_RAW(&NOBUG_FLAG(flag), handle)
1310 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1311 NOBUG_IF_ALPHA( \
1312 for ( \
1313 int nobug_locked_ = (NOBUG_RESOURCE_LOCK, 1); \
1314 nobug_locked_; \
1315 ({ \
1316 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1317 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1318 "RESOURCE_LEAVE", "%s: %s@%p: %s: %s", \
1319 handle?handle->current->resource->type:"", \
1320 handle?handle->current->resource->hdr.name:"", \
1321 handle?handle->current->resource->object_id:"", \
1322 handle?handle->hdr.name:"", \
1323 nobug_resource_states[handle?handle->state \
1324 :NOBUG_RESOURCE_INVALID]); \
1326 NOBUG_RESOURCE_ASSERT(nobug_resource_leave (handle), \
1327 "RESOURCE_ASSERT_LEAVE", NOBUG_LOCATION_INFO, "%s: %s@%p: %s: %s: %s", \
1328 handle?handle->current->resource->type:"", \
1329 handle?handle->current->resource->hdr.name:"", \
1330 handle?handle->current->resource->object_id:"", \
1331 handle?handle->hdr.name:"", \
1332 nobug_resource_states[handle?handle->state \
1333 :NOBUG_RESOURCE_INVALID], \
1334 nobug_resource_error); \
1335 handle = NULL; \
1336 NOBUG_RESOURCE_UNLOCK; \
1337 nobug_locked_ = 0; \
1338 })))
1341 /* assertion which dumps all resources */
1342 #define NOBUG_RESOURCE_ASSERT(resource, what, location, ...) \
1343 NOBUG_WHEN (!(resource), \
1344 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
1345 location, what, \
1346 ## __VA_ARGS__); \
1347 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1348 {&nobug_flag_NOBUG_ON, \
1349 LOG_EMERG, \
1350 NOBUG_LOCATION_ARGS}); \
1351 NOBUG_BACKTRACE; \
1352 NOBUG_ABORT \
1357 //resourcemacros PARA RESOURCE_DUMP; RESOURCE_DUMP; dump the state of a single resource
1358 //resourcemacros NOBUG_RESOURCE_DUMP(flag, handle)
1359 //resourcemacros NOBUG_RESOURCE_DUMP_IF(when, flag, handle)
1360 //resourcemacros
1361 //resourcemacros Dump the state of a single resource.
1362 //resourcemacros
1363 //resourcemacros `when`::
1364 //resourcemacros Condition which must be true to dump the resource
1365 //resourcemacros `flag`::
1366 //resourcemacros Nobug flag for the log channel
1367 //resourcemacros `handle`::
1368 //resourcemacros handle of the resource to be dumped
1369 //resourcemacros
1371 #define NOBUG_RESOURCE_DUMP(flag, handle) \
1372 do { NOBUG_RESOURCE_LOCK; \
1373 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1374 {&NOBUG_FLAG(flag), \
1375 NOBUG_RESOURCE_LOG_LEVEL, \
1376 NOBUG_LOCATION_ARGS}); \
1377 NOBUG_RESOURCE_UNLOCK; } while (0)
1379 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle) \
1380 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1381 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1382 {&NOBUG_FLAG(flag), \
1383 NOBUG_RESOURCE_LOG_LEVEL, \
1384 NOBUG_LOCATION_ARGS}); \
1385 NOBUG_RESOURCE_UNLOCK)
1389 //resourcemacros PARA RESOURCE_DUMPALL; RESOURCE_DUMPALL; dump the state of all resources
1390 //resourcemacros NOBUG_RESOURCE_DUMPALL(flag)
1391 //resourcemacros NOBUG_RESOURCE_DUMPALL_IF(when, flag)
1392 //resourcemacros
1393 //resourcemacros Dump the state of all resources.
1394 //resourcemacros
1395 //resourcemacros `when`::
1396 //resourcemacros Condition which must be true to dump the resources
1397 //resourcemacros `flag`::
1398 //resourcemacros Nobug flag for the log channel
1399 //resourcemacros
1401 #define NOBUG_RESOURCE_DUMPALL(flag) \
1402 do { NOBUG_RESOURCE_LOCK; \
1403 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1404 {&NOBUG_FLAG(flag), \
1405 NOBUG_RESOURCE_LOG_LEVEL, \
1406 NOBUG_LOCATION_ARGS}); \
1407 NOBUG_RESOURCE_UNLOCK; } while (0)
1410 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag) \
1411 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1412 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1413 {&NOBUG_FLAG(flag), \
1414 NOBUG_RESOURCE_LOG_LEVEL, \
1415 NOBUG_LOCATION_ARGS}); \
1416 NOBUG_RESOURCE_UNLOCK)
1420 //resourcemacros PARA RESOURCE_LIST; RESOURCE_LIST; enumerate all registered resources
1421 //resourcemacros NOBUG_RESOURCE_LIST(flag)
1422 //resourcemacros NOBUG_RESOURCE_LIST_IF(when, flag)
1423 //resourcemacros
1424 //resourcemacros List all registered resources.
1425 //resourcemacros
1426 //resourcemacros `when`::
1427 //resourcemacros Condition which must be true to list the resources
1428 //resourcemacros `flag`::
1429 //resourcemacros Nobug flag for the log channel
1430 //resourcemacros
1432 #define NOBUG_RESOURCE_LIST(flag) \
1433 do { NOBUG_RESOURCE_LOCK; \
1434 nobug_resource_list (&(struct nobug_resource_dump_context) \
1435 {&NOBUG_FLAG(flag), \
1436 NOBUG_RESOURCE_LOG_LEVEL, \
1437 NOBUG_LOCATION_ARGS}); \
1438 NOBUG_RESOURCE_UNLOCK; } while (0)
1440 #define NOBUG_RESOURCE_LIST_IF(when, flag) \
1441 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1442 nobug_resource_list (&(struct nobug_resource_dump_context) \
1443 {&NOBUG_FLAG(flag), \
1444 NOBUG_RESOURCE_LOG_LEVEL, \
1445 NOBUG_LOCATION_ARGS}); \
1446 NOBUG_RESOURCE_UNLOCK)
1450 threading support
1452 #if NOBUG_USE_PTHREAD
1453 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1454 #define NOBUG_THREAD_ID_FMT(pre,post) pre "%s" post
1455 #define NOBUG_THREAD_ID_COMMA , NOBUG_THREAD_ID_GET
1456 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1458 #else
1459 #define NOBUG_THREAD_ID_SET(name)
1460 #define NOBUG_THREAD_ID_FMT(pre,post) ""
1461 #define NOBUG_THREAD_ID_COMMA
1462 #define NOBUG_THREAD_ID_GET ""
1463 #endif
1465 #define NOBUG_THREAD_DATA (*nobug_thread_data())
1468 Source location
1470 #define NOBUG_LOCATION_ARGS NOBUG_BASENAME(__FILE__), __LINE__, __func__
1471 #define NOBUG_LOCATION_INFO (NOBUG_LOCATION_ARGS)
1473 #define NOBUG_LOCATION_FILE(file, _1, _2) file
1474 #define NOBUG_LOCATION_LINE(_1, line, _2) line
1475 #define NOBUG_LOCATION_FUNC(_1, _2, func) func
1479 Debuggers
1482 #define NOBUG_DBG_NONE 0
1483 #define NOBUG_DBG_GDB 1
1484 #define NOBUG_DBG_VALGRIND 2
1486 #define NOBUG_ACTIVE_DBG \
1487 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1488 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1491 //toolmacros HEAD- Tool Macros;;
1492 //toolmacros
1493 //toolmacros PARA NOBUG_FLAG_RAW; NOBUG_FLAG_RAW; pass direct flag pointer
1494 //toolmacros NOBUG_FLAG_RAW(ptr)
1495 //toolmacros
1496 //toolmacros Using this macro one can pass a direct pointer to a flag where a name would
1497 //toolmacros be expected. This is sometimes convinient when flag pointers are passed around
1498 //toolmacros in management strutures and one wants to tie logging to dynamic targets.
1499 //toolmacros
1500 //toolmacros [source,c]
1501 //toolmacros ----
1502 //toolmacros NOBUG_DEFINE_FLAG(myflag);
1503 //toolmacros ...
1504 //toolmacros struct nobug_flag* ptr = &NOBUG_FLAG(myflag);
1505 //toolmacros TRACE(NOBUG_FLAG_RAW(ptr), "Passed flag by pointer")
1506 //toolmacros ----
1507 //toolmacros
1509 #define nobug_flag_NOBUG_FLAG_RAW(name) *name
1512 //toolmacros PARA Backtraces; BACKTRACE; generate a backtrace
1513 //toolmacros BACKTRACE
1514 //toolmacros
1515 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1516 //toolmacros This is automatically called when NoBug finds an error and is due
1517 //toolmacros to abort. But one might call it manually too.
1518 //toolmacros
1520 #define NOBUG_BACKTRACE \
1521 NOBUG_IF_ALPHA( \
1522 switch (NOBUG_ACTIVE_DBG) { \
1523 case NOBUG_DBG_VALGRIND: \
1524 NOBUG_BACKTRACE_VALGRIND; \
1525 break; \
1526 default: \
1527 NOBUG_BACKTRACE_GLIBC; \
1528 }) \
1529 NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC)
1531 #define NOBUG_BACKTRACE_DBG \
1532 NOBUG_IF_NOT_RELEASE( \
1533 switch (NOBUG_ACTIVE_DBG) { \
1534 case NOBUG_DBG_VALGRIND: \
1535 NOBUG_BACKTRACE_VALGRIND; \
1536 break; \
1539 #define NOBUG_BACKTRACE_GDB fprintf(stderr, "UNIMPLEMENTED : GDB Backtraces\n")
1541 #define NOBUG_BACKTRACE_VALGRIND \
1542 NOBUG_IF(NOBUG_USE_VALGRIND, \
1543 VALGRIND_PRINTF_BACKTRACE("BACKTRACE: %s@%d %s", \
1544 NOBUG_LOCATION_ARGS))
1547 #ifndef NOBUG_BACKTRACE_DEPTH
1548 #define NOBUG_BACKTRACE_DEPTH 256
1549 #endif
1551 #define NOBUG_BACKTRACE_GLIBC \
1552 NOBUG_IF_NOT_RELEASE( \
1553 NOBUG_IF(NOBUG_USE_EXECINFO, do { \
1554 NOBUG_LOG_(&nobug_flag_NOBUG_ON, LOG_NOTICE, NOBUG_LOCATION_INFO, "BACKTRACE"); \
1555 nobug_backtrace_glibc (); \
1556 } while (0)))
1559 #ifndef NOBUG_TAB
1560 #define NOBUG_TAB " "
1561 #endif
1563 //toolmacros PARA Aborting; ABORT; abort the program
1564 //toolmacros NOBUG_ABORT_
1565 //toolmacros
1566 //toolmacros This is the default implementation for aborting the program, it first calls the
1567 //toolmacros abort callback if defined and then `abort()`.
1568 //toolmacros
1569 //toolmacros NOBUG_ABORT
1570 //toolmacros
1571 //toolmacros If not overridden, evaluates to `NOBUG_ABORT_`. One can override this before including
1572 //toolmacros `nobug.h` to customize abortion behaviour. This will be local to the translation unit then.
1573 //toolmacros
1574 #define NOBUG_ABORT_ \
1575 do { \
1576 if (nobug_abort_callback) \
1577 nobug_abort_callback (nobug_callback_data); \
1578 abort(); \
1579 } while(0)
1581 #ifndef NOBUG_ABORT
1582 #define NOBUG_ABORT NOBUG_ABORT_
1583 #endif
1587 init and other function wrapers
1589 #define NOBUG_INIT nobug_init()
1590 #define NOBUG_BASENAME(name) (strrchr((name), '/')?strrchr((name), '/') + 1 : (name))
1593 short macros without NOBUG_
1595 #ifndef NOBUG_DISABLE_SHORTNAMES
1596 #ifndef REQUIRE
1597 #define REQUIRE NOBUG_REQUIRE
1598 #endif
1599 #ifndef REQUIRE_DBG
1600 #define REQUIRE_DBG NOBUG_REQUIRE_DBG
1601 #endif
1602 #ifndef REQUIRE_IF
1603 #define REQUIRE_IF NOBUG_REQUIRE_IF
1604 #endif
1605 #ifndef REQUIRE_IF_DBG
1606 #define REQUIRE_IF_DBG NOBUG_REQUIRE_IF_DBG
1607 #endif
1608 #ifndef ENSURE
1609 #define ENSURE NOBUG_ENSURE
1610 #endif
1611 #ifndef ENSURE_DBG
1612 #define ENSURE_DBG NOBUG_ENSURE_DBG
1613 #endif
1614 #ifndef ENSURE_IF
1615 #define ENSURE_IF NOBUG_ENSURE_IF
1616 #endif
1617 #ifndef ENSURE_IF_DBG
1618 #define ENSURE_IF_DBG NOBUG_ENSURE_IF_DBG
1619 #endif
1620 #ifndef ASSERT
1621 #define ASSERT NOBUG_ASSERT
1622 #endif
1623 #ifndef ASSERT_DBG
1624 #define ASSERT_DBG NOBUG_ASSERT_DBG
1625 #endif
1626 #ifndef ASSERT_IF
1627 #define ASSERT_IF NOBUG_ASSERT_IF
1628 #endif
1629 #ifndef ASSERT_IF_DBG
1630 #define ASSERT_IF_DBG NOBUG_ASSERT_IF_DBG
1631 #endif
1632 #ifndef CHECK
1633 #define CHECK NOBUG_CHECK
1634 #endif
1635 #ifndef CHECK
1636 #define CHECK NOBUG_CHECK
1637 #endif
1638 #ifndef INVARIANT
1639 #define INVARIANT NOBUG_INVARIANT
1640 #endif
1641 #ifndef INVARIANT_DBG
1642 #define INVARIANT_DBG NOBUG_INVARIANT_DBG
1643 #endif
1644 #ifndef INVARIANT_IF
1645 #define INVARIANT_IF NOBUG_INVARIANT_IF
1646 #endif
1647 #ifndef INVARIANT_IF_DBG
1648 #define INVARIANT_IF_DBG NOBUG_INVARIANT_IF_DBG
1649 #endif
1650 #ifndef INVARIANT_ASSERT
1651 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
1652 #endif
1653 #ifndef DUMP
1654 #define DUMP NOBUG_DUMP
1655 #endif
1656 #ifndef DUMP_DBG
1657 #define DUMP_DBG NOBUG_DUMP_DBG
1658 #endif
1659 #ifndef DUMP_IF
1660 #define DUMP_IF NOBUG_DUMP_IF
1661 #endif
1662 #ifndef DUMP_IF_DBG
1663 #define DUMP_IF_DBG NOBUG_DUMP_IF_DBG
1664 #endif
1665 #ifndef DUMP_LOG
1666 #define DUMP_LOG NOBUG_DUMP_LOG
1667 #endif
1668 #ifndef DUMP_LOG_DBG
1669 #define DUMP_LOG_DBG NOBUG_DUMP_LOG_DBG
1670 #endif
1671 #ifndef DUMP_LOG_IF
1672 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1673 #endif
1674 #ifndef DUMP_LOG_IF_DBG
1675 #define DUMP_LOG_IF_DBG NOBUG_DUMP_LOG_IF_DBG
1676 #endif
1677 #ifndef LOG
1678 #define LOG NOBUG_LOG
1679 #endif
1680 #ifndef LOG_DBG
1681 #define LOG_DBG NOBUG_LOG_DBG
1682 #endif
1683 #ifndef LOG_IF
1684 #define LOG_IF NOBUG_LOG_IF
1685 #endif
1686 #ifndef LOG_IF_DBG
1687 #define LOG_IF_DBG NOBUG_LOG_IF_DBG
1688 #endif
1689 #ifndef ECHO
1690 #define ECHO NOBUG_ECHO
1691 #endif
1692 #ifndef ALERT
1693 #define ALERT NOBUG_ALERT
1694 #endif
1695 #ifndef ALERT_DBG
1696 #define ALERT_DBG NOBUG_ALERT_DBG
1697 #endif
1698 #ifndef ALERT_IF
1699 #define ALERT_IF NOBUG_ALERT_IF
1700 #endif
1701 #ifndef ALERT_IF_DBG
1702 #define ALERT_IF_DBG NOBUG_ALERT_IF_DBG
1703 #endif
1704 #ifndef CRITICAL
1705 #define CRITICAL NOBUG_CRITICAL
1706 #endif
1707 #ifndef CRITICAL_DBG
1708 #define CRITICAL_DBG NOBUG_CRITICAL_DBG
1709 #endif
1710 #ifndef CRITICAL_IF
1711 #define CRITICAL_IF NOBUG_CRITICAL_IF
1712 #endif
1713 #ifndef CRITICAL_IF_DBG
1714 #define CRITICAL_IF_DBG NOBUG_CRITICAL_IF_DBG
1715 #endif
1716 #ifndef ERROR
1717 #define ERROR NOBUG_ERROR
1718 #endif
1719 #ifndef ERROR_DBG
1720 #define ERROR_DBG NOBUG_ERROR_DBG
1721 #endif
1722 #ifndef ERROR_IF
1723 #define ERROR_IF NOBUG_ERROR_IF
1724 #endif
1725 #ifndef ERROR_IF_DBG
1726 #define ERROR_IF_DBG NOBUG_ERROR_IF_DBG
1727 #endif
1728 #ifndef WARN
1729 #define WARN NOBUG_WARN
1730 #endif
1731 #ifndef WARN_DBG
1732 #define WARN_DBG NOBUG_WARN_DBG
1733 #endif
1734 #ifndef WARN_IF
1735 #define WARN_IF NOBUG_WARN_IF
1736 #endif
1737 #ifndef WARN_IF_DBG
1738 #define WARN_IF_DBG NOBUG_WARN_IF_DBG
1739 #endif
1740 #ifndef INFO
1741 #define INFO NOBUG_INFO
1742 #endif
1743 #ifndef INFO_DBG
1744 #define INFO_DBG NOBUG_INFO_DBG
1745 #endif
1746 #ifndef INFO_IF
1747 #define INFO_IF NOBUG_INFO_IF
1748 #endif
1749 #ifndef INFO_IF_DBG
1750 #define INFO_IF_DBG NOBUG_INFO_IF_DBG
1751 #endif
1752 #ifndef NOTICE
1753 #define NOTICE NOBUG_NOTICE
1754 #endif
1755 #ifndef NOTICE_DBG
1756 #define NOTICE_DBG NOBUG_NOTICE_DBG
1757 #endif
1758 #ifndef NOTICE_IF
1759 #define NOTICE_IF NOBUG_NOTICE_IF
1760 #endif
1761 #ifndef NOTICE_IF_DBG
1762 #define NOTICE_IF_DBG NOBUG_NOTICE_IF_DBG
1763 #endif
1764 #ifndef TRACE
1765 #define TRACE NOBUG_TRACE
1766 #endif
1767 #ifndef TRACE_DBG
1768 #define TRACE_DBG NOBUG_TRACE_DBG
1769 #endif
1770 #ifndef TRACE_IF
1771 #define TRACE_IF NOBUG_TRACE_IF
1772 #endif
1773 #ifndef TRACE_IF_DBG
1774 #define TRACE_IF_DBG NOBUG_TRACE_IF_DBG
1775 #endif
1776 #ifndef BACKTRACE
1777 #define BACKTRACE NOBUG_BACKTRACE
1778 #endif
1779 #ifndef BACKTRACE_DBG
1780 #define BACKTRACE_DBG NOBUG_BACKTRACE_DBG
1781 #endif
1782 #ifndef DEPRECATED
1783 #define DEPRECATED NOBUG_DEPRECATED
1784 #endif
1785 #ifndef UNIMPLEMENTED
1786 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1787 #endif
1788 #ifndef FIXME
1789 #define FIXME NOBUG_FIXME
1790 #endif
1791 #ifndef TODO
1792 #define TODO NOBUG_TODO
1793 #endif
1794 #ifndef PLANNED
1795 #define PLANNED NOBUG_PLANNED
1796 #endif
1797 #ifndef NOTREACHED
1798 #define NOTREACHED NOBUG_NOTREACHED
1799 #endif
1800 #ifndef ELSE_NOTREACHED
1801 #define ELSE_NOTREACHED NOBUG_ELSE_NOTREACHED
1802 #endif
1803 #ifndef INJECT_GOODBAD
1804 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
1805 #endif
1806 #ifndef INJECT_FAULT
1807 #define INJECT_FAULT NOBUG_INJECT_FAULT
1808 #endif
1809 #ifndef CLEANUP
1810 #define CLEANUP NOBUG_CLEANUP
1811 #endif
1812 #ifndef CHECKED
1813 #define CHECKED NOBUG_CHECKED
1814 #endif
1815 #ifndef UNCHECKED
1816 #define UNCHECKED NOBUG_UNCHECKED
1817 #endif
1818 #ifndef RESOURCE_ANNOUNCE
1819 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1820 #endif
1821 #ifndef RESOURCE_FORGET
1822 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1823 #endif
1824 #ifndef RESOURCE_ENTER
1825 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1826 #endif
1827 #ifndef RESOURCE_WAIT
1828 #define RESOURCE_WAIT NOBUG_RESOURCE_WAIT
1829 #endif
1830 #ifndef RESOURCE_STATE
1831 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1832 #endif
1833 #ifndef RESOURCE_LEAVE
1834 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1835 #endif
1836 #ifndef RESOURCE_LEAVE_LOOKUP
1837 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1838 #endif
1839 #ifndef RESOURCE_HANDLE
1840 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1841 #endif
1842 #ifndef RESOURCE_HANDLE_INIT
1843 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
1844 #endif
1845 #ifndef RESOURCE_USER
1846 #define RESOURCE_USER NOBUG_RESOURCE_USER
1847 #endif
1848 #ifndef RESOURCE_USER_INIT
1849 #define RESOURCE_USER_INIT NOBUG_RESOURCE_USER_INIT
1850 #endif
1851 #ifndef RESOURCE_DUMP
1852 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
1853 #endif
1854 #ifndef RESOURCE_DUMP_IF
1855 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
1856 #endif
1857 #ifndef RESOURCE_DUMPALL
1858 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
1859 #endif
1860 #ifndef RESOURCE_DUMPALL_IF
1861 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
1862 #endif
1863 #ifndef RESOURCE_LIST
1864 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
1865 #endif
1866 #ifndef RESOURCE_LIST_IF
1867 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
1868 #endif
1869 #endif /* NOBUG_DISABLE_SHORTNAMES */
1873 Tool macros
1875 #ifdef __GNUC__
1876 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
1877 #define NOBUG_ATTR_PRINTF(fmt, ell) __attribute__ ((format (printf, fmt, ell)))
1878 #else
1879 #define NOBUG_CLEANUP(fn)
1880 #define NOBUG_ATTR_PRINTF(fmt, ell)
1881 #endif
1884 //toolmacros PARA NOBUG_ALPHA_COMMA; NOBUG_ALPHA_COMMA; append something after a comma in *ALPHA* builds
1885 //toolmacros NOBUG_ALPHA_COMMA(something)
1886 //toolmacros NOBUG_ALPHA_COMMA_NULL
1887 //toolmacros
1888 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
1889 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
1890 //toolmacros use this macros to append a comman and something else only in *ALPHA* builds as in:
1891 //toolmacros struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
1892 //toolmacros
1894 #define NOBUG_COMMA ,
1895 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
1896 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
1898 #define NOBUG_ONCE(code) \
1899 do { \
1900 static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 0; \
1901 if (NOBUG_EXPECT_FALSE(!NOBUG_CAT(nobug_once_,__LINE__))) \
1903 NOBUG_CAT(nobug_once_,__LINE__) = 1; \
1904 code; \
1906 } while (0)
1908 #if __GNUC__
1909 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
1910 #else
1911 #define NOBUG_EXPECT_FALSE(x) x
1912 #endif
1914 #define NOBUG_WHEN(when, ...) \
1915 do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
1918 //toolmacros PARA NOBUG_IF_*; NOBUG_IF; include code conditionally on build level
1919 //toolmacros NOBUG_IF_ALPHA(...)
1920 //toolmacros NOBUG_IF_NOT_ALPHA(...)
1921 //toolmacros NOBUG_IF_BETA(...)
1922 //toolmacros NOBUG_IF_NOT_BETA(...)
1923 //toolmacros NOBUG_IF_RELEASE(...)
1924 //toolmacros NOBUG_IF_NOT_RELEASE(...)
1925 //toolmacros
1926 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
1927 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
1928 //toolmacros internally, but can also be used for custom things.
1929 //toolmacros
1931 #define NOBUG_IF_ALPHA(...) \
1932 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1934 #define NOBUG_IF_NOT_ALPHA(...) \
1935 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1937 #define NOBUG_IF_BETA(...) \
1938 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__) \
1940 #define NOBUG_IF_NOT_BETA(...) \
1941 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__) \
1943 #define NOBUG_IF_RELEASE(...) \
1944 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1946 #define NOBUG_IF_NOT_RELEASE(...) \
1947 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1950 preprocessor hacks/metaprogramming
1953 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
1954 #define NOBUG_IF_1(...) __VA_ARGS__
1955 #define NOBUG_IF_0(...)
1957 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
1959 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
1960 #define NOBUG_NOT_1 0
1961 #define NOBUG_NOT_0 1
1963 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
1964 #define NOBUG_AND_00 0
1965 #define NOBUG_AND_01 0
1966 #define NOBUG_AND_10 0
1967 #define NOBUG_AND_11 1
1969 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
1970 #define NOBUG_OR_00 0
1971 #define NOBUG_OR_01 1
1972 #define NOBUG_OR_10 1
1973 #define NOBUG_OR_11 1
1975 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
1976 #define NOBUG_XOR_00 0
1977 #define NOBUG_XOR_01 1
1978 #define NOBUG_XOR_10 1
1979 #define NOBUG_XOR_11 0
1981 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
1982 #define NOBUG_CAT_(a,b) a##b
1984 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
1985 #define NOBUG_CAT3_(a,b,c) a##b##c
1987 #define NOBUG_HEAD(head, ...) head
1988 #define NOBUG_TAIL(_, ...) , ## __VA_ARGS__
1990 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
1991 #define NOBUG_STRINGIZE_(s) #s
1995 LIBNOBUG DECLARATIONS
1997 #ifdef __cplusplus
1998 extern "C" {
1999 #elif 0
2000 } /* fix emacs indent */
2001 #endif
2004 envvar control
2006 enum nobug_log_targets
2008 NOBUG_TARGET_RINGBUFFER,
2009 NOBUG_TARGET_CONSOLE,
2010 NOBUG_TARGET_FILE,
2011 NOBUG_TARGET_SYSLOG,
2012 NOBUG_TARGET_APPLICATION
2015 struct nobug_flag
2017 const char* name;
2018 struct nobug_flag* parent;
2019 volatile int initialized;
2020 int limits[5];
2021 struct nobug_ringbuffer* ringbuffer_target;
2022 FILE* console_target;
2023 FILE* file_target;
2027 nobug_env_parse_flag (const char* env, struct nobug_flag* flag, int default_target, int default_limit);
2030 nobug_env_init_flag (struct nobug_flag* flag, int default_target, int default_limit);
2034 ringbuffer
2036 struct nobug_ringbuffer
2038 char* pos;
2039 char* start;
2040 size_t size;
2041 size_t maxmsg;
2042 char name[256];
2045 enum nobug_ringbuffer_flags
2047 NOBUG_RINGBUFFER_DEFAULT, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
2048 NOBUG_RINGBUFFER_APPEND = 1, /* use existing backing file, append if possible */
2049 NOBUG_RINGBUFFER_TEMP = 2, /* unlink file instantly */
2050 NOBUG_RINGBUFFER_KEEP = 4 /* dont unlink the file at destroy */
2054 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
2055 with sane (but undefined) semantics.
2057 struct nobug_ringbuffer*
2058 nobug_ringbuffer_init (struct nobug_ringbuffer* self, size_t size,
2059 const char * name, int flags);
2061 struct nobug_ringbuffer*
2062 nobug_ringbuffer_new (size_t size, const char * name, int flags);
2064 struct nobug_ringbuffer*
2065 nobug_ringbuffer_destroy (struct nobug_ringbuffer* self);
2067 void
2068 nobug_ringbuffer_delete (struct nobug_ringbuffer* self);
2071 nobug_ringbuffer_vprintf (struct nobug_ringbuffer* self, const char* fmt, va_list ap);
2074 nobug_ringbuffer_printf (struct nobug_ringbuffer* self, const char* fmt, ...);
2076 char*
2077 nobug_ringbuffer_append (struct nobug_ringbuffer* self);
2079 char*
2080 nobug_ringbuffer_prev (struct nobug_ringbuffer* self, char* pos);
2082 char*
2083 nobug_ringbuffer_next (struct nobug_ringbuffer* self, char* pos);
2086 nobug_ringbuffer_save (struct nobug_ringbuffer* self, FILE* out);
2089 nobug_ringbuffer_load (struct nobug_ringbuffer* self, FILE* in);
2091 char*
2092 nobug_ringbuffer_pos (struct nobug_ringbuffer* self);
2094 void
2095 nobug_ringbuffer_pop (struct nobug_ringbuffer* self);
2099 multithreading extras
2102 #ifndef LLIST_DEFINED
2103 #define LLIST_DEFINED
2104 struct llist_struct
2106 struct llist_struct *next;
2107 struct llist_struct *prev;
2109 #endif
2111 #if NOBUG_USE_PTHREAD
2113 struct nobug_tls_data
2115 const char* thread_id;
2116 void* data;
2117 struct llist_struct res_stack; /* resources of this thread */
2120 extern pthread_key_t nobug_tls_key;
2122 struct nobug_tls_data*
2123 nobug_thread_set (const char* name);
2125 struct nobug_tls_data*
2126 nobug_thread_get (void);
2128 const char*
2129 nobug_thread_id_set (const char* name);
2131 const char*
2132 nobug_thread_id_get (void);
2134 extern pthread_mutex_t nobug_logging_mutex;
2135 extern pthread_mutex_t nobug_resource_mutex;
2136 #endif
2138 void**
2139 nobug_thread_data (void);
2142 resource registry
2145 #if NOBUG_USE_PTHREAD
2146 #define NOBUG_RESOURCE_LOCK pthread_mutex_lock (&nobug_resource_mutex)
2147 #define NOBUG_RESOURCE_UNLOCK pthread_mutex_unlock (&nobug_resource_mutex)
2148 #define NOBUG_LOGGING_LOCK pthread_mutex_lock (&nobug_logging_mutex)
2149 #define NOBUG_LOGGING_UNLOCK pthread_mutex_unlock (&nobug_logging_mutex)
2152 Note: errors are all fatal, we dont unlock the mutex when returning an error,
2153 this should be handled better in future but does not hurt
2155 #else
2156 #define NOBUG_RESOURCE_LOCK
2157 #define NOBUG_RESOURCE_UNLOCK
2158 #define NOBUG_LOGGING_LOCK
2159 #define NOBUG_LOGGING_UNLOCK
2160 #endif
2162 enum nobug_resource_state
2164 NOBUG_RESOURCE_INVALID,
2165 NOBUG_RESOURCE_WAITING,
2166 NOBUG_RESOURCE_EXCLUSIVE,
2167 NOBUG_RESOURCE_RECURSIVE,
2168 NOBUG_RESOURCE_SHARED
2172 struct nobug_resource_header
2174 struct llist_struct node; /* link node for resource registry or users */
2175 const char* name; /* name */
2176 const char* extra; /* extra information, file/line usually */
2179 struct nobug_resource_node;
2180 struct nobug_resource_user;
2182 struct nobug_resource_record
2184 struct nobug_resource_header hdr;
2186 struct llist_struct users; /* list of users of this resource */
2187 const void* object_id; /* unique identifer, usually a this pointer or similar */
2188 const char* type; /* type */
2190 #if NOBUG_USE_PTHREAD
2191 struct llist_struct nodes;
2192 #endif
2196 struct nobug_resource_node
2198 struct llist_struct node; /* all nodes for one resource */
2200 struct nobug_resource_record* resource; /* backpointer */
2201 struct nobug_resource_node* parent; /* upwards the tree */
2203 struct llist_struct childs; /* down the tree, all nodes pointing to here (TODO make this a slist) */
2204 struct llist_struct cldnode; /* node to accumulate all childrens of a parent (TODO slist) */
2208 struct nobug_resource_user
2210 struct nobug_resource_header hdr;
2212 struct nobug_resource_node* current; /* this resource */
2213 enum nobug_resource_state state; /* state */
2215 #if NOBUG_USE_PTHREAD
2216 struct nobug_tls_data* thread; /* pointer to this theads id */
2217 struct llist_struct res_stack; /* resources of this thread */
2218 #endif
2222 extern const char* nobug_resource_error;
2224 extern const char* nobug_resource_states[];
2227 void
2228 nobug_resource_init (void);
2230 void
2231 nobug_resource_destroy (void);
2234 struct nobug_resource_record*
2235 nobug_resource_announce (const char* type, const char* name, const void* object_id, const char* extra);
2238 nobug_resource_forget (struct nobug_resource_record* node);
2241 struct nobug_resource_user*
2242 nobug_resource_enter (struct nobug_resource_record* resource,
2243 const char* name,
2244 enum nobug_resource_state state,
2245 const char* extra);
2248 nobug_resource_leave (struct nobug_resource_user* handle);
2251 unsigned
2252 nobug_resource_record_available (void);
2255 unsigned
2256 nobug_resource_user_available (void);
2259 #if NOBUG_USE_PTHREAD
2260 unsigned
2261 nobug_resource_node_available (void);
2262 #endif
2265 struct nobug_resource_dump_context
2267 struct nobug_flag* flag;
2268 int level;
2269 const char* file;
2270 int line;
2271 const char* func;
2275 void
2276 nobug_resource_dump (struct nobug_resource_record* resource, struct nobug_resource_dump_context* context);
2278 void
2279 nobug_resource_dump_all (struct nobug_resource_dump_context* context);
2282 nobug_resource_state (struct nobug_resource_user* resource,
2283 enum nobug_resource_state state);
2286 void
2287 nobug_resource_list (struct nobug_resource_dump_context* context);
2291 global config, data and defaults
2293 void nobug_init (void);
2296 the destroy function is optional, since nobug should stay alive for the whole application lifetime
2297 (and destroying is global!) it is only provided for the nobug testsuite itself
2299 void nobug_destroy (void);
2301 void
2302 nobug_backtrace_glibc (void);
2304 void
2305 nobug_log (struct nobug_flag* flag, int lvl, const char* fmt, ...) NOBUG_ATTR_PRINTF(3, 4);
2308 extern struct nobug_ringbuffer nobug_default_ringbuffer;
2309 extern FILE* nobug_default_file;
2310 extern struct nobug_flag nobug_flag_NOBUG_ON;
2311 extern struct nobug_flag nobug_flag_NOBUG_ANN;
2312 extern struct nobug_flag nobug_flag_nobug;
2313 extern unsigned long long nobug_counter;
2315 //callbacks HEAD- Callbacks;;
2316 //callbacks
2317 //callbacks NoBug provides callbacks, applications can use these
2318 //callbacks to present logging information in some custom way or hook some special processing in.
2319 //callbacks The callbacks are initialized to NULL and never modified by NoBug, its the solve responsibility
2320 //callbacks of the user to manage them.
2321 //callbacks
2322 //callbacks CAUTION: There are certain constraints what and what not can be done in callbacks
2323 //callbacks documented below which must be followed.
2324 //callbacks
2325 //callbacks PARA type of logging callbacks; logging_cb; type of a logging callback function
2326 typedef void (*nobug_logging_cb)(const struct nobug_flag* flag, int priority, const char *log, void* data); //callbacks VERBATIM;
2327 //callbacks
2328 //callbacks used for the logging callbacks
2329 //callbacks
2330 //callbacks `flag`::
2331 //callbacks Flag structure which defines the logging configuration for this event
2332 //callbacks `priority`::
2333 //callbacks Log level of the current event
2334 //callbacks `log`::
2335 //callbacks Pointing to the current log line in the ringbuffer or `NULL`
2336 //callbacks `data`::
2337 //callbacks Global pointer defined by the user, passed arround (see below)
2338 //callbacks
2340 //callbacks PARA type of abort callback; abort_cb; type of a abort callback function
2341 typedef void (*nobug_abort_cb)(void* data); //callbacks VERBATIM;
2342 //callbacks
2343 //callbacks used for the abort callback
2344 //callbacks
2345 //callbacks `data`::
2346 //callbacks Global data defined by the user, passed arround (see below)
2347 //callbacks
2349 //callbacks PARA passing data to callbacks; callback_data; data to be passed to callbacks
2350 extern
2351 void* nobug_callback_data; //callbacks VERBATIM;
2352 //callbacks
2353 //callbacks This global variable is initialized to `NULL` and will never be touched by NoBug. One can use it
2354 //callbacks to pass extra data to the callback functions.
2355 //callbacks
2357 //callbacks PARA callback when logging; logging_callback; hook when something get logged
2358 extern
2359 nobug_logging_cb nobug_logging_callback; //callbacks VERBATIM;
2360 //callbacks
2361 //callbacks This callback gets called when something gets logged.
2362 //callbacks NoBug will still hold its mutexes when calling this hook, calling NoBug logging or resource tracking
2363 //callbacks functions from here recursively will deadlock and must be avoided.
2364 //callbacks The `log` parameter points to the logging message in the ringbuffer.
2365 //callbacks Unlike other logging targets it is not automatically limited to the log level configured
2366 //callbacks in the flag but called unconditionally. The callback should implement its own limiting.
2367 //callbacks
2368 //callbacks When one wants to do complex calls which may include recursion into logging and resource tracking
2369 //callbacks functions, the intended way is to pass contextual information possibly including a __copy__ of the
2370 //callbacks `log` parameter in xref:THREAD_DATA[NOBUG_THREAD_DATA] to the postlogging callback (see below).
2371 //callbacks Other internal NoBug facilties, like the ringbuffer etc, are protected by the mutexes and may be accessed
2372 //callbacks from this function.
2373 //callbacks
2375 //callbacks PARA callback after logging; postlogging_callback; hook after something get logged
2376 extern
2377 nobug_logging_cb nobug_postlogging_callback; //callbacks VERBATIM;
2378 //callbacks
2379 //callbacks This callback gets called after something got logged. The `log` parameter is always NULL and all
2380 //callbacks NoBug mutexes are released. This means that this function may call any complex things, including
2381 //callbacks calling logging and resource tracking, but may not call internal NoBug facilities.
2382 //callbacks Contextual created in the `nobug_logging_callback` and stored in xref:THREAD_DATA[NOBUG_THREAD_DATA] can be
2383 //callbacks retrieved here and may need to be cleaned up here.
2384 //callbacks
2386 //callbacks PARA callback for aborting; abort_callback; hook to handle a termination
2387 extern
2388 nobug_abort_cb nobug_abort_callback; //callbacks VERBATIM;
2389 //callbacks
2390 //callbacks This callback gets called when the application shall be terminated due an error.
2391 //callbacks It can be used to hook exceptions or similar things in. When it returns, `abort()`
2392 //callbacks is called.
2393 //callbacks
2394 //callbacks IMPORTANT: Errors detected by NoBug are always fatal. If one handles and possible
2395 //callbacks throws an exception here, the application must shut down as soon as possible.
2396 //callbacks Most causes for aborts are optimitzed out in `RELEASE` builds.
2397 //callbacks
2399 #ifdef __cplusplus
2400 } /* extern "C" */
2401 #endif
2403 #ifndef NOBUG_LIBNOBUG_C
2406 tag this translation unit as unchecked in ALPHA and BETA builds
2408 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED);
2410 #endif /* NOBUG_LIBNOBUG_C */
2411 #endif