WIP: add source contexts, remove debugger-only macros
[nobug.git] / src / nobug.h
blobe28f750bb92aad25da910f195109b3fb9b3aba78
1 /*
2 This file is part of the NoBug debugging library.
4 Copyright (C)
5 2007, 2008, 2009, 2010 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_CONTEXT, ""__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_CTX(expr, context,...)
123 //assertions REQUIRE_IF(when, expr, ...)
124 //assertions REQUIRE_IF_CTX(when, expr, context, ...)
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_REQUIRE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
134 #define NOBUG_REQUIRE_CTX(expr, context, ...) \
135 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", context, ""__VA_ARGS__))
138 #define NOBUG_REQUIRE_IF(when, expr, context,...) \
139 NOBUG_REQUIRE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
141 #define NOBUG_REQUIRE_IF_CTX(when, expr, context,...) \
142 NOBUG_IF_NOT_RELEASE ( \
143 NOBUG_WHEN(when, NOBUG_REQUIRE_CTX(expr, context, ""__VA_ARGS__)) \
148 //assertions PARA ENSURE; ENSURE; postconditions (computation outcomes)
149 //assertions ENSURE(expr, ...)
150 //assertions ENSURE_CTX(expr, context, ...)
151 //assertions ENSURE_IF(when, expr, ...)
152 //assertions ENSURE_IF_CTX(when, expr, context, ...)
153 //assertions
154 //assertions Postcondition (progress/output) check. Use these macros to validate the
155 //assertions data a function produces (example: return value). `ENSURE` is enabled
156 //assertions unconditionally in *ALPHA* builds and optimized out in *BETA* builds for
157 //assertions scopes which are tagged as `CHECKED`.
158 //assertions
159 //assertions The `ENSURE_IF` variants are enabled in *ALPHA* and *BETA* builds.
160 //assertions
161 //assertions In *RELEASE* builds this checks are
162 //assertions always optimized out, scopes tagged as `UNCHECKED` are not permitted.
163 //assertions
165 #define NOBUG_ENSURE(expr, ...) \
166 NOBUG_ENSURE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
168 #define NOBUG_ENSURE_CTX(expr, context, ...) \
169 NOBUG_IF_ALPHA (NOBUG_ASSERT_(expr, "POSTCONDITION", \
170 context, ""__VA_ARGS__)) \
171 NOBUG_IF_BETA ( \
172 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
173 NOBUG_ASSERT_(expr, "POSTCONDITION", \
174 context, ""__VA_ARGS__) \
179 #define NOBUG_ENSURE_IF(when, expr, ...) \
180 NOBUG_ENSURE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
182 #define NOBUG_ENSURE_IF_CTX(when, expr, context, ...) \
183 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE(expr, context, ""__VA_ARGS__)))
187 //assertions PARA ASSERT; ASSERT; generic assertion
188 //assertions ASSERT(expr, ...)
189 //assertions ASSERT_CTX(expr, context, ...)
190 //assertions ASSERT_IF(when, expr, ...)
191 //assertions ASSERT_IF_CTX(when, expr, context, ...)
192 //assertions
193 //assertions Generic check. Use these macros when you want to validate something
194 //assertions which doesn't fall into one of the above categories. A example is when
195 //assertions a library function can return a unexpected result (scanf with syntax
196 //assertions error in the formatstring, when a constant/literal formatstring is
197 //assertions expected). The checks are enabled in *ALPHA* and *BETA* builds and
198 //assertions optimized out in *RELEASE* builds.
199 //assertions
201 #define NOBUG_ASSERT(expr, ...) \
202 NOBUG_ASSERT_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
204 #define NOBUG_ASSERT_CTX(expr, context, ...) \
205 NOBUG_IF_NOT_RELEASE( \
206 NOBUG_ASSERT_(expr, "ASSERTION", \
207 context, ""__VA_ARGS__) \
211 #define NOBUG_ASSERT_IF(when, expr, ...) \
212 NOBUG_ASSERT_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
214 #define NOBUG_ASSERT_IF_CTX(when, expr, context, ...) \
215 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT_CTX(expr, context, ""__VA_ARGS__)))
219 //assertions PARA assert; assert; C standard assertion
220 //assertions assert(expr)
221 //assertions
222 //assertions NoBug overrides the standard `assert` macro, using `NOBUG_ASSERT`.
223 //assertions This is just a compatibility feature, its use is not suggested.
224 //assertions
226 #undef assert
227 #define assert(expr) NOBUG_ASSERT(expr)
231 low level assert
233 #ifdef __GNUC__
234 #define NOBUG_ASSERT_(expr, what, context, fmt, ...) \
235 NOBUG_WHEN (!(expr), \
236 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
237 what, context, "(%s) " fmt, \
238 #expr, ## __VA_ARGS__); \
239 NOBUG_BACKTRACE_CTX(context); \
240 NOBUG_ABORT \
242 #else /* , ## __VA_ARGS__ eating the comma when the arglist is empty is a gcc extension, fallback for other compilers */
243 #define NOBUG_ASSERT_(expr, what, context, ...) \
244 NOBUG_WHEN (!(expr), \
245 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
246 what, context, \
247 , ""__VA_ARGS__); \
248 NOBUG_BACKTRACE_CTX(context); \
249 NOBUG_ABORT \
251 #endif
254 //assertions PARA INVARIANT; INVARIANT; validate invariant state
255 //assertions INVARIANT(type, pointer, depth)
256 //assertions INVARIANT_IF(when,type, pointer, depth)
257 //assertions INVARIANT_ASSERT(expr, ...)
258 //assertions
259 //assertions Checking invariants. You can provide more complex checking functions
260 //assertions which test the validity of datastructures. Invariants are only enabled
261 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
262 //assertions otherwise optimized out.
263 //assertions
264 //assertions TODO: describe how to create invariant checks
265 //assertions
267 #define NOBUG_INVARIANT(type, pointer, depth) \
268 NOBUG_IF_ALPHA( \
269 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
270 NOBUG_CAT(type,_invariant)(pointer, depth, \
271 NOBUG_CONTEXT) \
276 #define NOBUG_INVARIANT_IF(when, type, pointer, depth) \
277 NOBUG_IF_ALPHA( \
278 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
279 NOBUG_WHEN (when, \
280 NOBUG_CAT(type,_invariant)(pointer, depth, \
281 NOBUG_CONTEXT) \
285 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
286 NOBUG_ASSERT_(expr, "INVARIANT", invariant_context, ""__VA_ARGS__)
290 checked/unchecked tagged scopes
292 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
294 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
296 #define NOBUG_UNCHECKED \
297 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
298 NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
302 /*TODO dump-level for flags instead limits[0]*/
304 //dumpmacros PARA DUMP; DUMP; dumping datastructures
305 //dumpmacros DUMP(flag, type, pointer, depth)
306 //dumpmacros DUMP_IF(when, flag, type, pointer, depth)
307 //dumpmacros
308 //dumpmacros This macros call a datastructure dump of the object (`pointer`) in question.
309 //dumpmacros `DUMP_IF` is the only enabled dumping macro for the RELEASE build level.
310 //dumpmacros
312 #define NOBUG_DUMP(flag, type, pointer, depth) \
313 NOBUG_IF_NOT_RELEASE( \
314 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
315 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT) \
319 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth) \
320 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET] && when, \
321 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT) \
326 //dumpmacros PARA DUMP_LOG; DUMP_LOG; logging helper for dumping
327 //dumpmacros DUMP_LOG(fmt, ...)
328 //dumpmacros DUMP_LOG_IF(when, fmt, ...)
329 //dumpmacros
330 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
331 //dumpmacros
332 //dumpmacros Dumping is by default done on level `LOG_DEBUG`, this can be overridden by
333 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other level.
334 //dumpmacros
338 #define NOBUG_DUMP_LOG(...) \
339 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
340 "DUMP", dump_context, \
341 ""__VA_ARGS__)
343 #define NOBUG_DUMP_LOG_IF(expr, ...) \
344 NOBUG_WHEN (expr, \
345 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
346 "DUMP", dump_context, \
347 ""__VA_ARGS__) \
352 #ifndef NOBUG_DUMP_LEVEL
353 #define NOBUG_DUMP_LEVEL LOG_DEBUG
354 #endif
357 //logmacros HEAD- Logging Macros;;
358 //logmacros
359 //logmacros PARA ECHO; ECHO; unconditional logging for tests
360 //logmacros ECHO(...)
361 //logmacros
362 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
363 //logmacros testsuites where one want to print and log messages independent of the build level
364 //logmacros
366 #define NOBUG_ECHO(...) \
367 NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_NOTICE, "ECHO", NOBUG_CONTEXT, ""__VA_ARGS__)
370 //logmacros PARA ALERT; ALERT; about to die
371 //logmacros ALERT(flag, ...)
372 //logmacros ALERT_IF(when, flag, ...)
373 //logmacros
374 //logmacros This is the most critical condition an application might log. This might be used
375 //logmacros if an error occurs which can not be handled except a safe shutdown for example.
376 //logmacros
378 #define NOBUG_ALERT(flag, ...) \
379 NOBUG_LOG(flag, LOG_ALERT, ""__VA_ARGS__)
381 #define NOBUG_ALERT_IF(expr, flag, ...) \
382 NOBUG_LOG_IF(expr, flag, LOG_ALERT, ""__VA_ARGS__)
385 //logmacros PARA CRITICAL; CRITICAL; can not continue
386 //logmacros CRITICAL(flag, ...)
387 //logmacros CRITICAL_IF(when, flag, ...)
388 //logmacros
389 //logmacros An error which can not be handled occured but the application does not need to be
390 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
391 //logmacros
393 #define NOBUG_CRITICAL(flag, ...) \
394 NOBUG_LOG(flag, LOG_CRIT, ""__VA_ARGS__)
396 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
397 NOBUG_LOG_IF(expr, flag, LOG_CRIT, ""__VA_ARGS__)
400 //logmacros PARA ERROR; ERROR; something gone wrong
401 //logmacros ERROR(flag, fmt, ...)
402 //logmacros ERROR_IF(when, flag, fmt, ...)
403 //logmacros
404 //logmacros Application takes a error handling brach
405 //logmacros
407 #define NOBUG_ERROR(flag, ...) \
408 NOBUG_LOG(flag, LOG_ERR, ""__VA_ARGS__)
410 #define NOBUG_ERROR_IF(expr, flag, ...) \
411 NOBUG_LOG_IF(expr, flag, LOG_ERR, ""__VA_ARGS__)
414 //logmacros PARA WARN; WARN; unexpected fixable error
415 //logmacros WARN(flag, fmt, ...)
416 //logmacros WARN_IF(when, flag, fmt, ...)
417 //logmacros
418 //logmacros Rare, handled but unexpected branch
419 //logmacros
421 #define NOBUG_WARN(flag, ...) \
422 NOBUG_LOG(flag, LOG_WARNING, ""__VA_ARGS__)
424 #define NOBUG_WARN_IF(expr, flag, ...) \
425 NOBUG_LOG_IF(expr, flag, LOG_WARNING, ""__VA_ARGS__)
428 //logmacros PARA INFO; INFO; progress message
429 //logmacros INFO(flag, fmt, ...)
430 //logmacros INFO_IF(when, flag, fmt, ...)
431 //logmacros
432 //logmacros Message about program progress
433 //logmacros
435 #define NOBUG_INFO(flag, ...) \
436 NOBUG_LOG(flag, LOG_INFO, ""__VA_ARGS__)
438 #define NOBUG_INFO_IF(expr, flag, ...) \
439 NOBUG_LOG_IF(expr, flag, LOG_INFO, ""__VA_ARGS__)
442 //logmacros PARA NOTICE; NOTICE; detailed progress message
443 //logmacros NOTICE(flag, fmt, ...)
444 //logmacros NOTICE_IF(when, flag, fmt, ...)
445 //logmacros
446 //logmacros More detailed progress message
447 //logmacros
449 #define NOBUG_NOTICE(flag, ...) \
450 NOBUG_LOG(flag, LOG_NOTICE, ""__VA_ARGS__)
452 #define NOBUG_NOTICE_IF(expr, flag, ...) \
453 NOBUG_LOG_IF(expr, flag, LOG_NOTICE, ""__VA_ARGS__)
456 //logmacros PARA TRACE; TRACE; debugging level message
457 //logmacros TRACE(flag, fmt, ...)
458 //logmacros TRACE_IF(when, flag, fmt, ...)
459 //logmacros
460 //logmacros Very fine grained messages
461 //logmacros
462 //logmacros NOTE: that `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
463 //logmacros
465 #define NOBUG_TRACE(flag, ...) \
466 NOBUG_LOG(flag, LOG_DEBUG, ""__VA_ARGS__)
468 #define NOBUG_TRACE_IF(expr, flag, ...) \
469 NOBUG_LOG_IF(expr, flag, LOG_DEBUG, ""__VA_ARGS__)
473 //logmacros PARA LOG; LOG; generic logging
474 //logmacros LOG(flag, lvl, ...)
475 //logmacros LOG_CTX(flag, lvl, context, ...)
476 //logmacros LOG_IF(when, flag, lvl, ...)
477 //logmacros LOG_IF_CTX(when, flag, lvl, context, ...)
478 //logmacros
479 //logmacros Generic logging macro which takes the level explicitly,
480 //logmacros avoid this, unless you implement your own logging facilities.
481 //logmacros
483 #define NOBUG_LOG(flag, lvl, ...) \
484 NOBUG_LOG_CTX(flag, lvl, NOBUG_CONTEXT, ""__VA_ARGS__)
486 #define NOBUG_LOG_CTX(flag, lvl, context, ...) \
487 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LVL(lvl), context, ""__VA_ARGS__)
490 #define NOBUG_LOG_IF(expr, flag, lvl, ...) \
491 NOBUG_LOG_IF_CTX(expr, flag, lvl, NOBUG_CONTEXT, ""__VA_ARGS__)
493 #define NOBUG_LOG_IF_CTX(expr, flag, lvl, context, ...) \
494 NOBUG_WHEN (expr, \
495 NOBUG_LOG_CTX(flag, lvl, context, ""__VA_ARGS__) \
500 low level logging handler
502 Note: all fmt concatenations us a empty string ""__VA_ARG__
503 except this one which must use a single space " " before __VA_ARGS__ for formatting the log message correctly (and silence a gcc warning)
506 #define NOBUG_LOG_(flag, lvl, what, context, ...) \
507 NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER], \
508 nobug_log (flag, lvl, what, context, " "__VA_ARGS__) \
512 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
513 #define NOBUG_LVL_0 "EMERG"
514 #define NOBUG_LVL_1 "ALERT"
515 #define NOBUG_LVL_2 "CRIT"
516 #define NOBUG_LVL_3 "ERR"
517 #define NOBUG_LVL_4 "WARNING"
518 #define NOBUG_LVL_5 "NOTICE"
519 #define NOBUG_LVL_6 "INFO"
520 #define NOBUG_LVL_7 "TRACE"
523 //logmacros PARA LOG_BASELIMIT; LOG_BASELIMIT; minimum compliled-in logging limit
524 //logmacros NOBUG_LOG_BASELIMIT_ALPHA
525 //logmacros NOBUG_LOG_BASELIMIT_BETA
526 //logmacros NOBUG_LOG_BASELIMIT_RELEASE
527 //logmacros NOBUG_LOG_BASELIMIT
528 //logmacros
529 //logmacros anything more detailed than this base limits will be optimized out.
530 //logmacros This is used to reduce the logging overhead for *RELEASE* builds.
531 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
532 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
533 //logmacros builds to log the application progress only coarsely then.
534 //logmacros
535 //logmacros This macros can be defined before including 'nobug.h' to some other
536 //logmacros log level (as defined in 'syslog.h').
537 //logmacros
538 //logmacros NOTE: there is no logging macro for `LOG_EMERG` since this is used by the assertions as fatal message
539 //logmacros
541 #ifndef NOBUG_LOG_BASELIMIT_ALPHA
542 #define NOBUG_LOG_BASELIMIT_ALPHA LOG_DEBUG
543 #endif
545 #ifndef NOBUG_LOG_BASELIMIT_BETA
546 #define NOBUG_LOG_BASELIMIT_BETA LOG_DEBUG
547 #endif
549 #ifndef NOBUG_LOG_BASELIMIT_RELEASE
550 #define NOBUG_LOG_BASELIMIT_RELEASE LOG_NOTICE
551 #endif
553 #ifndef NOBUG_LOG_BASELIMIT
554 #define NOBUG_LOG_BASELIMIT \
555 NOBUG_IF_ALPHA(NOBUG_LOG_BASELIMIT_ALPHA) \
556 NOBUG_IF_BETA(NOBUG_LOG_BASELIMIT_BETA) \
557 NOBUG_IF_RELEASE(NOBUG_LOG_BASELIMIT_RELEASE)
558 #endif
561 //srccontext HEAD- Source Contexts;;
562 //srccontext
565 #define NOBUG_CONTEXT ((const struct nobug_context){__FILE__, __LINE__, __func__})
569 //annotations HEAD- Source Annotations;;
570 //annotations
571 //annotations One can tag features as:
572 //annotations
576 alpha beta release
577 DEPRECATED log nothing wont compile
579 //annotations PARA DEPRECATED; DEPRECATED; to be discarded in future
580 //annotations DEPRECATED(...)
581 //annotations
582 //annotations Something which shouldn't be used in future
583 //annotations
585 #define NOBUG_DEPRECATED(...) \
586 NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN, \
587 "DEPRECATED", NOBUG_CONTEXT, ""__VA_ARGS__) \
589 NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
593 alpha beta release
594 UNIMPLEMENTED abort abort wont compile
596 //annotations PARA UNIMPLEMENTED; UNIMPLEMENTED; not yet implemented
597 //annotations UNIMPLEMENTED(...)
598 //annotations
599 //annotations not yet finished feature
600 //annotations
602 #define NOBUG_UNIMPLEMENTED(...) \
603 NOBUG_IF_NOT_RELEASE ( do { \
604 NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG, \
605 "UNIMPLEMENTED", NOBUG_CONTEXT, ""__VA_ARGS__); \
606 NOBUG_ABORT; \
607 } while (0)) \
608 NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
612 alpha beta release
613 FIXME log wont compile wont compile
615 //annotations PARA FIXME; FIXME; known bug
616 //annotations FIXME(...)
617 //annotations
618 //annotations known bug to be fixed later
619 //annotations
621 #define NOBUG_FIXME(...) \
622 NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT, \
623 "FIXME", NOBUG_CONTEXT, ""__VA_ARGS__))) \
624 NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(__VA_ARGS__)) \
625 NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
629 alpha beta release
630 TODO log log wont compile
632 //annotations PARA TODO; TODO; things to be done
633 //annotations TODO(...)
634 //annotations
635 //annotations enhancement to be done soon
636 //annotations
638 #define NOBUG_TODO(...) \
639 NOBUG_IF_NOT_RELEASE ( \
640 NOBUG_ONCE ( \
641 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE, \
642 "TODO", NOBUG_CONTEXT, ""__VA_ARGS__); \
643 )) \
644 NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
648 alpha beta release
649 PLANNED log nothing nothing
651 //annotations PARA PLANNED; PLANNED; ideas for future
652 //annotations PLANNED(...)
653 //annotations
654 //annotations future enhancement
655 //annotations
657 #define NOBUG_PLANNED(...) \
658 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO, \
659 "PLANNED", NOBUG_CONTEXT, ""__VA_ARGS__)))
663 alpha beta release
664 NOTREACHED abort abort nothing
666 //annotations PARA NOTREACHED; NOTREACHED; code path never taken
667 //annotations NOTREACHED(...)
668 //annotations
669 //annotations used to tag code-path which shall be never executed.
670 //annotations
672 #define NOBUG_NOTREACHED(...) \
673 NOBUG_IF_NOT_RELEASE( do { \
674 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
675 "NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__); \
676 NOBUG_ABORT; \
677 } while (0))
680 //annotations PARA ELSE_NOTREACHED; ELSE_NOTREACHED; alternative never taken
681 //annotations ELSE_NOTREACHED(...)
682 //annotations
683 //annotations same as `else NOTREACHED()`, but wholly optimized out in release builds.
684 //annotations
686 #define NOBUG_ELSE_NOTREACHED(...) \
687 NOBUG_IF_NOT_RELEASE( else do { \
688 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
689 "ELSE_NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__); \
690 NOBUG_ABORT; \
691 } while (0))
696 //faultinjection HEAD- Fault injection;;
697 //faultinjection
698 //faultinjection NoBug has some macros which can be used to simulate errorneous behaviour:
699 //faultinjection
700 //faultinjection PARA INJECT_GOODBAD; INJECT_GOODBAD; fault injection expression
701 //faultinjection INJECT_GOODBAD(expr, good, bad)
702 //faultinjection
703 //faultinjection substitutes to an expression and returns good when expr is false and
704 //faultinjection bad when expr is true. In BETA and RELEASE builds 'good' is always returned.
705 //faultinjection
707 #define NOBUG_INJECT_GOODBAD(expr, good, bad) \
708 NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);bad;}):good) \
709 NOBUG_IF_NOT_ALPHA(good)
713 //faultinjection PARA INJECT_FAULT; INJECT_FAULT; fault injection statement
714 //faultinjection INJECT_FAULT(expr, bad)
715 //faultinjection
716 //faultinjection substitutes to a statement which executes 'bad'
717 //faultinjection when expr is true. Optimitzed out in BETA and RELEASE builds.
718 //faultinjection
720 #define NOBUG_INJECT_FAULT(expr, bad) \
721 NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
725 //faultinjection PARA INJECT_LEVEL; INJECT_LEVEL; log level for fault injection
726 //faultinjection In both cases, when a fault is injected it will be logged at
727 //faultinjection `NOBUG_INJECT_LEVEL` (default: `LOG_NOTICE`). This can be defined
728 //faultinjection before including 'nobug.h' to override it.
729 //faultinjection
731 #define NOBUG_INJECT_LOG(msg) \
732 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
733 "INJECT_FAULT", NOBUG_CONTEXT, \
734 msg)
737 #ifndef NOBUG_INJECT_LEVEL
738 #define NOBUG_INJECT_LEVEL LOG_NOTICE
739 #endif
743 Flag handling
745 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_, name)
747 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
750 #define NOBUG_DEFINE_FLAG(name) \
751 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
752 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
753 struct nobug_flag NOBUG_FLAG(name) = \
754 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
755 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
756 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
757 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
758 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
759 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
763 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
764 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
765 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
766 NOBUG_DECLARE_FLAG(parent); \
767 struct nobug_flag NOBUG_FLAG(name) = \
768 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
769 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
770 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
771 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
772 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
773 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
777 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) \
778 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
779 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
780 struct nobug_flag NOBUG_FLAG(name) = \
781 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
782 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
783 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
784 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
785 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
786 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
790 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
791 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
792 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
793 NOBUG_DECLARE_FLAG(parent); \
794 struct nobug_flag NOBUG_FLAG(name) = \
795 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
796 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
797 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
798 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
799 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
800 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
804 #define NOBUG_INIT_FLAG(name) \
805 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT, NOBUG_CONTEXT)
808 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
809 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default, NOBUG_CONTEXT)
812 #define NOBUG_CPP_DEFINE_FLAG(name) \
813 NOBUG_FLAG_IF_DECLAREONLY( \
814 NOBUG_DECLARE_FLAG(name); \
815 extern int nobug_cppflag_##name \
817 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
818 NOBUG_DEFINE_FLAG(name); \
819 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
823 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
824 NOBUG_FLAG_IF_DECLAREONLY( \
825 NOBUG_DECLARE_FLAG(name); \
826 extern int nobug_cppflag_##name \
828 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
829 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
830 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
834 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
835 NOBUG_FLAG_IF_DECLAREONLY( \
836 NOBUG_DECLARE_FLAG(name); \
837 extern int nobug_cppflag_##name \
839 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
840 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
841 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
845 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
846 NOBUG_FLAG_IF_DECLAREONLY( \
847 NOBUG_DECLARE_FLAG(name); \
848 extern int nobug_cppflag_##name \
850 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
851 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
852 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
856 #ifndef NOBUG_DECLARE_ONLY
857 #define NOBUG_DECLARE_ONLY 0
858 #endif
860 #define NOBUG_FLAG_IF_DECLAREONLY(...) \
861 NOBUG_IF(NOBUG_DECLARE_ONLY, __VA_ARGS__)
863 #define NOBUG_FLAG_IF_NOT_DECLAREONLY(...) \
864 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
866 #ifdef __cplusplus
867 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
868 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
869 #else
870 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
871 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, NOBUG_ERROR_CANT_DEFINE_AUTOINITIALIZED_CPP_FLAGS_IN_C)
872 #endif
874 #ifndef NOBUG_LOG_LIMIT_ALPHA
875 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
876 #endif
877 #ifndef NOBUG_LOG_LIMIT_BETA
878 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
879 #endif
880 #ifndef NOBUG_LOG_LIMIT_RELEASE
881 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
882 #endif
884 #ifndef NOBUG_LOG_LIMIT
885 # define NOBUG_LOG_LIMIT \
886 NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA) \
887 NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA) \
888 NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
889 #endif
891 #ifndef NOBUG_LOG_TARGET_ALPHA
892 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
893 #endif
894 #ifndef NOBUG_LOG_TARGET_BETA
895 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
896 #endif
897 #ifndef NOBUG_LOG_TARGET_RELEASE
898 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
899 #endif
901 #ifndef NOBUG_LOG_TARGET
902 # define NOBUG_LOG_TARGET \
903 NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA) \
904 NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA) \
905 NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
906 #endif
908 #define NOBUG_SET_LIMIT(flag, min) \
909 NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
913 //resourcemacros HEAD~ Resource tracking macros;;
914 //resourcemacros
915 //resourcemacros INDEX RESOURCE_LOGGING; RESOURCE_LOGGING; switch resource logging on and off
916 //resourcemacros INDEX RESOURCE_LOG_LEVEL; RESOURCE_LOG_LEVEL; select the log level for resource logging
917 //resourcemacros
918 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
919 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
920 //resourcemacros `LOG_DEBUG`.
921 //resourcemacros
923 #ifndef NOBUG_RESOURCE_LOGGING
924 #define NOBUG_RESOURCE_LOGGING 1
925 #endif
927 #ifndef NOBUG_RESOURCE_LOG_LEVEL
928 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
929 #endif
933 //resourcemacros PARA RESOURCE_HANDLE; RESOURCE_HANDLE; define resource handles
934 //resourcemacros RESOURCE_HANDLE(name)
935 //resourcemacros RESOURCE_HANDLE_INIT(name)
936 //resourcemacros RESOURCE_USER(name)
937 //resourcemacros RESOURCE_USER_INIT(name)
938 //resourcemacros
939 //resourcemacros Define and initialize handles for to track resources.
940 //resourcemacros
941 //resourcemacros `name`::
942 //resourcemacros identifer to be used for the handle
943 //resourcemacros
944 //resourcemacros There are two kinds of handles, each resource itself is abstracted with a
945 //resourcemacros `RESOURCE_HANDLE` and every access to this resources is tracked through a
946 //resourcemacros `RESOURCE_USER` handle. These macros takes care that the declaration is optimized
947 //resourcemacros out in the same manner as the rest of the resource tracker would be disabled.
948 //resourcemacros You can still instantiate handles as `struct nobug_resource_record*` or
949 //resourcemacros `struct nobug_resource_user*` in structures which must have a constant size
950 //resourcemacros unconditional of the build level. The two `*_INIT` macros can be used to initialize
951 //resourcemacros resource handles and are optimized out when the resource tracker gets disabled.
952 //resourcemacros
954 #define NOBUG_RESOURCE_HANDLE(handle) \
955 NOBUG_IF_ALPHA(struct nobug_resource_record* handle)
957 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
959 #define NOBUG_RESOURCE_USER(handle) \
960 NOBUG_IF_ALPHA(struct nobug_resource_user* handle)
962 #define NOBUG_RESOURCE_USER_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
966 //resourcemacros PARA RESOURCE_ANNOUNCE; RESOURCE_ANNOUNCE; publish new resources
967 //resourcemacros RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
968 //resourcemacros
969 //resourcemacros Publishes resources.
970 //resourcemacros
971 //resourcemacros `flag`::
972 //resourcemacros the NoBug flag which turns logging on for this macro
973 //resourcemacros `type`::
974 //resourcemacros a string which should denote the domain of the resource,
975 //resourcemacros examples are "file", "mutex", "lock", "database" and so on
976 //resourcemacros `name`::
977 //resourcemacros the actual name of a named resource this as string which
978 //resourcemacros together with type forms a unique identifier of the resource. `type` and
979 //resourcemacros `name` must be available through the entire lifetime of the resource, using
980 //resourcemacros literal strings is recommended
981 //resourcemacros `identifier`::
982 //resourcemacros a pointer which should be unique for this resource, any
983 //resourcemacros kind of pointer will suffice, it is only used for identification. In
984 //resourcemacros multithreaded applications the thread identifier becomes an additional
985 //resourcemacros identifier
986 //resourcemacros `handle`::
987 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to point to
988 //resourcemacros the newly created resource.
989 //resourcemacros
990 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
991 //resourcemacros announced more than one time.
992 //resourcemacros
994 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
995 NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(&NOBUG_FLAG(flag), type, name, ptr, handle, NOBUG_CONTEXT)
997 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
998 NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, NOBUG_CONTEXT)
1000 #define NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, context) \
1001 NOBUG_IF_ALPHA( do { \
1002 NOBUG_RESOURCE_LOCK; \
1003 NOBUG_REQUIRE_CTX(!handle, context, "Announced resource handle not initialized"); \
1004 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1005 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1006 "RESOURCE_ANNOUNCE", context, \
1007 "%s: %s@%p", type, name, ptr);) \
1008 NOBUG_RESOURCE_ASSERT_CTX(handle = nobug_resource_announce (type, name, ptr, \
1009 context), \
1010 "RESOURCE_ASSERT_ANNOUNCE", context, \
1011 "%s: %s@%p %s", type, name, ptr, nobug_resource_error); \
1012 NOBUG_RESOURCE_UNLOCK; \
1013 } while (0))
1017 //resourcemacros PARA RESOURCE_FORGET; RESOURCE_FORGET; remove resources
1018 //resourcemacros RESOURCE_FORGET(flag, handle)
1019 //resourcemacros
1020 //resourcemacros Removes resources that have become unavailable from the registry.
1021 //resourcemacros
1022 //resourcemacros `flag`::
1023 //resourcemacros the NoBug flag which turns logging on for this macro
1024 //resourcemacros `handle`::
1025 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1026 //resourcemacros
1027 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1028 //resourcemacros error is raised.
1029 //resourcemacros
1031 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1032 NOBUG_RESOURCE_FORGET_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1034 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1035 NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1037 #define NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, context) \
1038 NOBUG_IF_ALPHA( do { \
1039 NOBUG_RESOURCE_LOCK; \
1040 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1041 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1042 "RESOURCE_FORGET", context, "%s: %s@%p", \
1043 (handle)?(handle)->type:"", \
1044 (handle)?(handle)->hdr.name:"", \
1045 (handle)?(handle)->object_id:NULL);) \
1046 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_forget (handle), \
1047 "RESOURCE_ASSERT_FORGET", context, "%s: %s@%p: %s", \
1048 (handle)?(handle)->type:"", \
1049 (handle)?(handle)->hdr.name:"", \
1050 (handle)?(handle)->object_id:NULL, \
1051 nobug_resource_error); \
1052 handle = NULL; \
1053 NOBUG_RESOURCE_UNLOCK; \
1054 } while (0))
1058 //resourcemacros PARA RESOURCE_ENTER; RESOURCE_ENTER; claim a resource
1059 //resourcemacros RESOURCE_ENTER(flag, announced, user, state, handle)
1060 //resourcemacros
1061 //resourcemacros Acquire a resource.
1062 //resourcemacros
1063 //resourcemacros `flag`::
1064 //resourcemacros nobug flag which turns logging on for this macro
1065 //resourcemacros `announced`::
1066 //resourcemacros the handle set by `RESOURCE_ANNOUNCE`
1067 //resourcemacros `user`::
1068 //resourcemacros a free-form identifier
1069 //resourcemacros `state`::
1070 //resourcemacros the initial state, one of `NOBUG_RESOURCE_WAITING`,
1071 //resourcemacros `NOBUG_RESOURCE_EXCLUSIVE`, `NOBUG_RESOURCE_RECURSIVE` or `NOBUG_RESOURCE_SHARED`
1072 //resourcemacros `handle`::
1073 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to the
1074 //resourcemacros entering node
1075 //resourcemacros
1076 //resourcemacros
1078 #define NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle) \
1079 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, NOBUG_CONTEXT)
1081 #define NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, context) \
1082 NOBUG_IF_ALPHA( \
1083 do { \
1084 NOBUG_REQUIRE_CTX(resource, context, "Announced resource handle not initialized"); \
1085 NOBUG_REQUIRE_CTX(!(handle), context, "Resource handle already entered"); \
1086 NOBUG_RESOURCE_LOCK; \
1087 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1088 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, \
1089 "RESOURCE_ENTER", context, \
1090 "%s: %s@%p: %s: %s", \
1091 (resource)?(resource)->type:"", \
1092 (resource)?(resource)->hdr.name:"", \
1093 (resource)?(resource)->object_id:NULL, \
1094 user, \
1095 nobug_resource_states[state]);) \
1096 NOBUG_RESOURCE_ASSERT_CTX(handle = \
1097 nobug_resource_enter (resource, \
1098 user, state, \
1099 context), \
1100 "RESOURCE_ASSERT_ENTER", context, \
1101 "%s: %s@%p: %s: %s: %s", \
1102 (resource)?(resource)->type:"", \
1103 (resource)?(resource)->hdr.name:"", \
1104 (resource)?(resource)->object_id:NULL, \
1105 user, nobug_resource_states[state], \
1106 nobug_resource_error); \
1107 NOBUG_RESOURCE_UNLOCK; \
1108 } while(0))
1111 //resourcemacros PARA RESOURCE_WAIT; RESOURCE_WAIT; wait for a resource to become available
1112 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle)
1113 //resourcemacros
1114 //resourcemacros This is just an alias for RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1115 //resourcemacros
1116 //resourcemacros .How to use it
1117 //resourcemacros [source,c]
1118 //resourcemacros ----
1119 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle);
1120 //resourcemacros if (lock_my_resource() == ERROR)
1121 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle);
1122 //resourcemacros else
1123 //resourcemacros RESOURCE_STATE(flag, NOBUG_RESOURCE_EXCLUSIVE, handle);
1124 //resourcemacros ----
1125 //resourcemacros
1126 #define NOBUG_RESOURCE_WAIT(flag, resource, user, handle) \
1127 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1129 #define NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context) \
1130 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_WAITING, handle, context)
1133 //resourcemacros PARA RESOURCE_TRY; RESOURCE_TRY; wait for a resource to become available
1134 //resourcemacros RESOURCE_TRY(flag, resource, user, handle)
1135 //resourcemacros
1136 //resourcemacros This is just an alias for RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_TRYING, handle).
1137 //resourcemacros Trying on a resource is similar to waiting but will not trigger a deadlock check. This can be used
1138 //resourcemacros when a deadlock is expected at runtime and one handles this otherwise (by a timed wait or something like that).
1139 //resourcemacros
1140 #define NOBUG_RESOURCE_TRY(flag, resource, user, handle) \
1141 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_TRYING, handle)
1143 #define NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context) \
1144 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_TRYING, handle, context)
1148 //resourcemacros PARA RESOURCE_STATE; RESOURCE_STATE; change the state of a resource
1149 //resourcemacros RESOURCE_STATE(flag, entered, state)
1150 //resourcemacros
1151 //resourcemacros Changes resource's state.
1152 //resourcemacros
1153 //resourcemacros `flag`::
1154 //resourcemacros is nobug flag which turns logging on for this macro
1155 //resourcemacros `state`::
1156 //resourcemacros the new state Note that only certain state transitions are
1157 //resourcemacros allowed, see discussion/diagram above
1158 //resourcemacros `entered`::
1159 //resourcemacros the handle set by `RESOURCE_ENTER`
1160 //resourcemacros
1162 #define NOBUG_RESOURCE_STATE(flag, state, entered) \
1163 NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, NOBUG_CONTEXT)
1165 #define NOBUG_RESOURCE_STATE_RAW(flag, state, entered) \
1166 NOBUG_RESOURCE_STATE_RAW_CTX(flag, state, entered, NOBUG_CONTEXT)
1168 #define NOBUG_RESOURCE_STATE_RAW_CTX(flag, nstate, entered, context) \
1169 NOBUG_IF_ALPHA( \
1170 do { \
1171 NOBUG_RESOURCE_LOCK; \
1172 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1173 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1174 "RESOURCE_STATE", context, \
1175 "%s: %s@%p: %s: %s->%s", \
1176 (entered)?(entered)->current->resource->type:"", \
1177 (entered)?(entered)->current->resource->hdr.name:"", \
1178 (entered)?(entered)->current->resource->object_id:"", \
1179 (entered)?(entered)->hdr.name:"", \
1180 nobug_resource_states[(entered)?(entered)->state \
1181 :NOBUG_RESOURCE_INVALID], \
1182 nobug_resource_states[nstate]); \
1184 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_state ((entered), nstate), \
1185 "RESOURCE_ASSERT_STATE", context, \
1186 "%s: %s@%p: %s: %s->%s: %s", \
1187 (entered)?(entered)->current->resource->type:"", \
1188 (entered)?(entered)->current->resource->hdr.name:"", \
1189 (entered)?(entered)->current->resource->object_id:"", \
1190 (entered)?(entered)->hdr.name:"", \
1191 nobug_resource_states[(entered)?(entered)->state \
1192 :NOBUG_RESOURCE_INVALID], \
1193 nobug_resource_states[nstate], \
1194 nobug_resource_error); \
1195 NOBUG_RESOURCE_UNLOCK; \
1196 } while (0))
1200 //resourcemacros PARA RESOURCE_LEAVE; RESOURCE_LEAVE; relinquish a claimed resource
1201 //resourcemacros RESOURCE_LEAVE(flag, handle)
1202 //resourcemacros
1203 //resourcemacros Disconnect from a resource identified with its handle.
1204 //resourcemacros
1205 //resourcemacros `flag`::
1206 //resourcemacros nobug flag which turns logging on for this macro
1207 //resourcemacros `handle`::
1208 //resourcemacros the handle you got while entering the resource
1209 //resourcemacros
1210 //resourcemacros 'RESOURCE_LEAVE()' acts like the head of a C loop statement, it ties to the following
1211 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1212 //resourcemacros This statement must not be left by break, return or any other kind of jump. NoBug does
1213 //resourcemacros not assert this (for for Performance reasons).
1214 //resourcemacros
1215 //resourcemacros .How to use it
1216 //resourcemacros [source,c]
1217 //resourcemacros ----
1218 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle)
1219 //resourcemacros {
1220 //resourcemacros unlock_my_resource();
1221 //resourcemacros }
1222 //resourcemacros ----
1223 //resourcemacros
1225 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1226 NOBUG_RESOURCE_LEAVE_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1228 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1229 NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1231 #define NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, context) \
1232 NOBUG_IF_ALPHA( \
1233 for ( \
1234 int nobug_locked_ = (NOBUG_RESOURCE_LOCK, 1); \
1235 nobug_locked_; \
1236 ({ \
1237 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1238 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1239 "RESOURCE_LEAVE", context, \
1240 "%s: %s@%p: %s: %s", \
1241 (handle)?(handle)->current->resource->type:"", \
1242 (handle)?(handle)->current->resource->hdr.name:"", \
1243 (handle)?(handle)->current->resource->object_id:"", \
1244 (handle)?(handle)->hdr.name:"", \
1245 nobug_resource_states[(handle)?(handle)->state \
1246 :NOBUG_RESOURCE_INVALID]); \
1248 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_leave (handle), \
1249 "RESOURCE_ASSERT_LEAVE", context, \
1250 "%s: %s@%p: %s: %s: %s", \
1251 (handle)?(handle)->current->resource->type:"", \
1252 (handle)?(handle)->current->resource->hdr.name:"", \
1253 (handle)?(handle)->current->resource->object_id:"", \
1254 (handle)?(handle)->hdr.name:"", \
1255 nobug_resource_states[(handle)?(handle)->state \
1256 :NOBUG_RESOURCE_INVALID], \
1257 nobug_resource_error); \
1258 handle = NULL; \
1259 NOBUG_RESOURCE_UNLOCK; \
1260 nobug_locked_ = 0; \
1261 })))
1265 //resourcemacros PARA RESOURCE_ASSERT_STATE; RESOURCE_ASSERT_STATE; assert the state of a resource
1266 //resourcemacros RESOURCE_ASSERT_STATE(resource, state)
1267 //resourcemacros RESOURCE_ASSERT_STATE_IF(when, resource, state)
1268 //resourcemacros
1269 //resourcemacros Assert that we have a resource in a given state. For multithreaded programms the topmost
1270 //resourcemacros state of the calling thread is checked, for non threadeded programs the most recent state on
1271 //resourcemacros resource is used.
1272 //resourcemacros
1273 //resourcemacros `when`::
1274 //resourcemacros Condition which must be true for testing the assertion
1275 //resourcemacros `resource`::
1276 //resourcemacros Resource handle
1277 //resourcemacros `state`::
1278 //resourcemacros The expected state
1279 //resourcemacros
1281 #define NOBUG_RESOURCE_ASSERT_STATE(resource, state) \
1282 NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, NOBUG_CONTEXT)
1284 #define NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context) \
1285 do { \
1286 enum nobug_resource_state mystate = nobug_resource_mystate (resource); \
1287 NOBUG_RESOURCE_ASSERT_CTX(mystate == state, \
1288 "RESOURCE_ASSERT_STATE", context, \
1289 "resource %p has state %s but %s was expected", \
1290 resource, nobug_resource_states[mystate], nobug_resource_states[state]); \
1291 } while (0)
1294 #define NOBUG_RESOURCE_ASSERT_STATE_IF(when, resource, state) \
1295 NOBUG_IF_ALPHA (NOBUG_WHEN(when, NOBUG_RESOURCE_ASSERT_STATE (resource, state))
1298 /* assertion which dumps all resources */
1299 #define NOBUG_RESOURCE_ASSERT_CTX(expr, what, context, ...) \
1300 NOBUG_IF_ALPHA( \
1301 NOBUG_WHEN (!(expr), \
1302 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
1303 what, context, \
1304 ""__VA_ARGS__); \
1305 struct nobug_resource_dump_context nobug_dumpcontext = \
1307 &nobug_flag_NOBUG_ON, \
1308 LOG_EMERG, \
1309 context \
1310 }; \
1311 nobug_resource_dump_all (&nobug_dumpcontext); \
1312 NOBUG_BACKTRACE_CTX(context); \
1313 NOBUG_ABORT))
1317 //resourcemacros PARA RESOURCE_DUMP; RESOURCE_DUMP; dump the state of a single resource
1318 //resourcemacros NOBUG_RESOURCE_DUMP(flag, handle)
1319 //resourcemacros NOBUG_RESOURCE_DUMP_IF(when, flag, handle)
1320 //resourcemacros
1321 //resourcemacros Dump the state of a single resource.
1322 //resourcemacros
1323 //resourcemacros `when`::
1324 //resourcemacros Condition which must be true to dump the resource
1325 //resourcemacros `flag`::
1326 //resourcemacros Nobug flag for the log channel
1327 //resourcemacros `handle`::
1328 //resourcemacros handle of the resource to be dumped
1329 //resourcemacros
1331 #define NOBUG_RESOURCE_DUMP(flag, handle) \
1332 NOBUG_IF_ALPHA( \
1333 do { \
1334 NOBUG_RESOURCE_LOCK; \
1335 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1336 {&NOBUG_FLAG(flag), \
1337 NOBUG_RESOURCE_LOG_LEVEL, \
1338 NOBUG_CONTEXT}); \
1339 NOBUG_RESOURCE_UNLOCK; \
1340 } while (0))
1342 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle) \
1343 NOBUG_IF_ALPHA( \
1344 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1345 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1346 {&NOBUG_FLAG(flag), \
1347 NOBUG_RESOURCE_LOG_LEVEL, \
1348 NOBUG_CONTEXT}); \
1349 NOBUG_RESOURCE_UNLOCK))
1353 //resourcemacros PARA RESOURCE_DUMPALL; RESOURCE_DUMPALL; dump the state of all resources
1354 //resourcemacros NOBUG_RESOURCE_DUMPALL(flag)
1355 //resourcemacros NOBUG_RESOURCE_DUMPALL_IF(when, flag)
1356 //resourcemacros
1357 //resourcemacros Dump the state of all resources.
1358 //resourcemacros
1359 //resourcemacros `when`::
1360 //resourcemacros Condition which must be true to dump the resources
1361 //resourcemacros `flag`::
1362 //resourcemacros Nobug flag for the log channel
1363 //resourcemacros
1365 #define NOBUG_RESOURCE_DUMPALL(flag) \
1366 NOBUG_IF_ALPHA( \
1367 do { \
1368 NOBUG_RESOURCE_LOCK; \
1369 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1370 {&NOBUG_FLAG(flag), \
1371 NOBUG_RESOURCE_LOG_LEVEL, \
1372 NOBUG_CONTEXT}); \
1373 NOBUG_RESOURCE_UNLOCK; \
1374 } while (0))
1377 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag) \
1378 NOBUG_IF_ALPHA( \
1379 NOBUG_WHEN(when, \
1380 NOBUG_RESOURCE_LOCK; \
1381 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1382 {&NOBUG_FLAG(flag), \
1383 NOBUG_RESOURCE_LOG_LEVEL, \
1384 NOBUG_CONTEXT}); \
1385 NOBUG_RESOURCE_UNLOCK))
1388 //resourcemacros PARA RESOURCE_LIST; RESOURCE_LIST; enumerate all registered resources
1389 //resourcemacros NOBUG_RESOURCE_LIST(flag)
1390 //resourcemacros NOBUG_RESOURCE_LIST_IF(when, flag)
1391 //resourcemacros
1392 //resourcemacros List all registered resources.
1393 //resourcemacros
1394 //resourcemacros `when`::
1395 //resourcemacros Condition which must be true to list the resources
1396 //resourcemacros `flag`::
1397 //resourcemacros Nobug flag for the log channel
1398 //resourcemacros
1400 #define NOBUG_RESOURCE_LIST(flag) \
1401 NOBUG_IF_ALPHA( \
1402 do { \
1403 NOBUG_RESOURCE_LOCK; \
1404 nobug_resource_list (&(struct nobug_resource_dump_context) \
1405 {&NOBUG_FLAG(flag), \
1406 NOBUG_RESOURCE_LOG_LEVEL, \
1407 NOBUG_CONTEXT}); \
1408 NOBUG_RESOURCE_UNLOCK; \
1409 } while (0))
1412 #define NOBUG_RESOURCE_LIST_IF(when, flag) \
1413 NOBUG_IF_ALPHA( \
1414 NOBUG_WHEN(when, \
1415 NOBUG_RESOURCE_LOCK; \
1416 nobug_resource_list (&(struct nobug_resource_dump_context) \
1417 {&NOBUG_FLAG(flag), \
1418 NOBUG_RESOURCE_LOG_LEVEL, \
1419 NOBUG_CONTEXT}); \
1420 NOBUG_RESOURCE_UNLOCK))
1424 threading support
1426 #if NOBUG_USE_PTHREAD
1427 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1428 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1430 #else
1431 #define NOBUG_THREAD_ID_SET(name)
1432 #define NOBUG_THREAD_ID_GET ""
1433 #endif
1435 #define NOBUG_THREAD_DATA (*nobug_thread_data())
1439 Debuggers
1442 #define NOBUG_DBG_NONE 0
1443 #define NOBUG_DBG_GDB 1
1444 #define NOBUG_DBG_VALGRIND 2
1446 #define NOBUG_ACTIVE_DBG \
1447 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1448 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1451 //toolmacros HEAD- Tool Macros;;
1452 //toolmacros
1453 //toolmacros PARA NOBUG_FLAG_RAW; NOBUG_FLAG_RAW; pass direct flag pointer
1454 //toolmacros NOBUG_FLAG_RAW(ptr)
1455 //toolmacros
1456 //toolmacros Using this macro one can pass a direct pointer to a flag where a name would
1457 //toolmacros be expected. This is sometimes convinient when flag pointers are passed around
1458 //toolmacros in management strutures and one wants to tie logging to dynamic targets.
1459 //toolmacros
1460 //toolmacros [source,c]
1461 //toolmacros ----
1462 //toolmacros NOBUG_DEFINE_FLAG(myflag);
1463 //toolmacros ...
1464 //toolmacros struct nobug_flag* ptr = &NOBUG_FLAG(myflag);
1465 //toolmacros TRACE(NOBUG_FLAG_RAW(ptr), "Passed flag by pointer")
1466 //toolmacros ----
1467 //toolmacros
1469 #define nobug_flag_NOBUG_FLAG_RAW(name) *name
1472 //toolmacros PARA Backtraces; BACKTRACE; generate a backtrace
1473 //toolmacros BACKTRACE
1474 //toolmacros BACKTRACE_CTX(context)
1475 //toolmacros
1476 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1477 //toolmacros This is automatically called when NoBug finds an error and is due
1478 //toolmacros to abort. But one might call it manually too.
1479 //toolmacros
1481 #define NOBUG_BACKTRACE NOBUG_BACKTRACE_CTX(NOBUG_CONTEXT)
1483 #define NOBUG_BACKTRACE_CTX(context) \
1484 NOBUG_IF_ALPHA( \
1485 switch (NOBUG_ACTIVE_DBG) { \
1486 case NOBUG_DBG_VALGRIND: \
1487 NOBUG_BACKTRACE_VALGRIND(context); \
1488 break; \
1489 default: \
1490 NOBUG_BACKTRACE_GLIBC(context); \
1491 }) \
1492 NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC(context))
1494 #define NOBUG_BACKTRACE_GDB(context) UNIMPLEMENTED
1496 #define NOBUG_BACKTRACE_VALGRIND(context) \
1497 NOBUG_IF(NOBUG_USE_VALGRIND, \
1498 NOBUG_LOGGING_LOCK; \
1499 struct nobug_context ctx = context; \
1500 VALGRIND_PRINTF_BACKTRACE("----------: BACKTRACE: %s@%d %s", \
1501 nobug_basename(ctx.file), \
1502 ctx.line, \
1503 ctx.func); \
1504 NOBUG_LOGGING_UNLOCK)
1506 #ifndef NOBUG_BACKTRACE_DEPTH
1507 #define NOBUG_BACKTRACE_DEPTH 256
1508 #endif
1510 #define NOBUG_BACKTRACE_GLIBC(context) \
1511 NOBUG_IF_NOT_RELEASE( \
1512 NOBUG_IF(NOBUG_USE_EXECINFO, do { \
1513 nobug_backtrace_glibc (context); \
1514 } while (0)))
1517 #ifndef NOBUG_TAB
1518 #define NOBUG_TAB " "
1519 #endif
1521 //toolmacros PARA Aborting; ABORT; abort the program
1522 //toolmacros NOBUG_ABORT_
1523 //toolmacros
1524 //toolmacros This is the default implementation for aborting the program, it first syncs all ringbuffers to disk, then
1525 //toolmacros calls the abort callback if defined and then `abort()`.
1526 //toolmacros
1527 //toolmacros NOBUG_ABORT
1528 //toolmacros
1529 //toolmacros If not overridden, evaluates to `NOBUG_ABORT_`. One can override this before including
1530 //toolmacros `nobug.h` to customize abortion behaviour. This will be local to the translation unit then.
1531 //toolmacros
1532 #define NOBUG_ABORT_ \
1533 do { \
1534 nobug_ringbuffer_allsync (); \
1535 if (nobug_abort_callback) \
1536 nobug_abort_callback (nobug_callback_data); \
1537 abort(); \
1538 } while(0)
1540 #ifndef NOBUG_ABORT
1541 #define NOBUG_ABORT NOBUG_ABORT_
1542 #endif
1545 init and other function wrapers
1547 #define NOBUG_INIT nobug_init(NOBUG_CONTEXT)
1550 short macros without NOBUG_
1552 #ifndef NOBUG_DISABLE_SHORTNAMES
1553 #ifndef REQUIRE
1554 #define REQUIRE NOBUG_REQUIRE
1555 #endif
1556 #ifndef REQUIRE_IF
1557 #define REQUIRE_IF NOBUG_REQUIRE_IF
1558 #endif
1559 #ifndef ENSURE
1560 #define ENSURE NOBUG_ENSURE
1561 #endif
1562 #ifndef ENSURE_IF
1563 #define ENSURE_IF NOBUG_ENSURE_IF
1564 #endif
1565 #ifndef ASSERT
1566 #define ASSERT NOBUG_ASSERT
1567 #endif
1568 #ifndef ASSERT_IF
1569 #define ASSERT_IF NOBUG_ASSERT_IF
1570 #endif
1571 #ifndef CHECK
1572 #define CHECK NOBUG_CHECK
1573 #endif
1574 #ifndef CHECK
1575 #define CHECK NOBUG_CHECK
1576 #endif
1577 #ifndef INVARIANT
1578 #define INVARIANT NOBUG_INVARIANT
1579 #endif
1580 #ifndef INVARIANT_IF
1581 #define INVARIANT_IF NOBUG_INVARIANT_IF
1582 #endif
1583 #ifndef INVARIANT_ASSERT
1584 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
1585 #endif
1586 #ifndef DUMP
1587 #define DUMP NOBUG_DUMP
1588 #endif
1589 #ifndef DUMP_IF
1590 #define DUMP_IF NOBUG_DUMP_IF
1591 #endif
1592 #ifndef DUMP_LOG
1593 #define DUMP_LOG NOBUG_DUMP_LOG
1594 #endif
1595 #ifndef DUMP_LOG_IF
1596 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1597 #endif
1598 #ifndef LOG
1599 #define LOG NOBUG_LOG
1600 #endif
1601 #ifndef LOG_IF
1602 #define LOG_IF NOBUG_LOG_IF
1603 #endif
1604 #ifndef ECHO
1605 #define ECHO NOBUG_ECHO
1606 #endif
1607 #ifndef ALERT
1608 #define ALERT NOBUG_ALERT
1609 #endif
1610 #ifndef ALERT_IF
1611 #define ALERT_IF NOBUG_ALERT_IF
1612 #endif
1613 #ifndef CRITICAL
1614 #define CRITICAL NOBUG_CRITICAL
1615 #endif
1616 #ifndef CRITICAL_IF
1617 #define CRITICAL_IF NOBUG_CRITICAL_IF
1618 #endif
1619 #ifndef ERROR
1620 #define ERROR NOBUG_ERROR
1621 #endif
1622 #ifndef ERROR_IF
1623 #define ERROR_IF NOBUG_ERROR_IF
1624 #endif
1625 #ifndef WARN
1626 #define WARN NOBUG_WARN
1627 #endif
1628 #ifndef WARN_IF
1629 #define WARN_IF NOBUG_WARN_IF
1630 #endif
1631 #ifndef INFO
1632 #define INFO NOBUG_INFO
1633 #endif
1634 #ifndef INFO_IF
1635 #define INFO_IF NOBUG_INFO_IF
1636 #endif
1637 #ifndef NOTICE
1638 #define NOTICE NOBUG_NOTICE
1639 #endif
1640 #ifndef NOTICE_IF
1641 #define NOTICE_IF NOBUG_NOTICE_IF
1642 #endif
1643 #ifndef TRACE
1644 #define TRACE NOBUG_TRACE
1645 #endif
1646 #ifndef TRACE_IF
1647 #define TRACE_IF NOBUG_TRACE_IF
1648 #endif
1649 #ifndef BACKTRACE
1650 #define BACKTRACE NOBUG_BACKTRACE
1651 #endif
1652 #ifndef DEPRECATED
1653 #define DEPRECATED NOBUG_DEPRECATED
1654 #endif
1655 #ifndef UNIMPLEMENTED
1656 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1657 #endif
1658 #ifndef FIXME
1659 #define FIXME NOBUG_FIXME
1660 #endif
1661 #ifndef TODO
1662 #define TODO NOBUG_TODO
1663 #endif
1664 #ifndef PLANNED
1665 #define PLANNED NOBUG_PLANNED
1666 #endif
1667 #ifndef NOTREACHED
1668 #define NOTREACHED NOBUG_NOTREACHED
1669 #endif
1670 #ifndef ELSE_NOTREACHED
1671 #define ELSE_NOTREACHED NOBUG_ELSE_NOTREACHED
1672 #endif
1673 #ifndef INJECT_GOODBAD
1674 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
1675 #endif
1676 #ifndef INJECT_FAULT
1677 #define INJECT_FAULT NOBUG_INJECT_FAULT
1678 #endif
1679 #ifndef CLEANUP
1680 #define CLEANUP NOBUG_CLEANUP
1681 #endif
1682 #ifndef CHECKED
1683 #define CHECKED NOBUG_CHECKED
1684 #endif
1685 #ifndef UNCHECKED
1686 #define UNCHECKED NOBUG_UNCHECKED
1687 #endif
1688 #ifndef RESOURCE_ANNOUNCE
1689 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1690 #endif
1691 #ifndef RESOURCE_FORGET
1692 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1693 #endif
1694 #ifndef RESOURCE_ENTER
1695 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1696 #endif
1697 #ifndef RESOURCE_WAIT
1698 #define RESOURCE_WAIT NOBUG_RESOURCE_WAIT
1699 #endif
1700 #ifndef RESOURCE_TRY
1701 #define RESOURCE_TRY NOBUG_RESOURCE_TRY
1702 #endif
1703 #ifndef RESOURCE_STATE
1704 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1705 #endif
1706 #ifndef RESOURCE_LEAVE
1707 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1708 #endif
1709 #ifndef RESOURCE_LEAVE_LOOKUP
1710 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1711 #endif
1712 #ifndef RESOURCE_HANDLE
1713 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1714 #endif
1715 #ifndef RESOURCE_HANDLE_INIT
1716 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
1717 #endif
1718 #ifndef RESOURCE_USER
1719 #define RESOURCE_USER NOBUG_RESOURCE_USER
1720 #endif
1721 #ifndef RESOURCE_ASSERT_STATE
1722 #define RESOURCE_ASSERT_STATE NOBUG_RESOURCE_ASSERT_STATE
1723 #endif
1724 #ifndef RESOURCE_ASSERT_STATE_IF
1725 #define RESOURCE_ASSERT_STATE_IF NOBUG_RESOURCE_ASSERT_STATE_IF
1726 #endif
1727 #ifndef RESOURCE_USER_INIT
1728 #define RESOURCE_USER_INIT NOBUG_RESOURCE_USER_INIT
1729 #endif
1730 #ifndef RESOURCE_DUMP
1731 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
1732 #endif
1733 #ifndef RESOURCE_DUMP_IF
1734 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
1735 #endif
1736 #ifndef RESOURCE_DUMPALL
1737 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
1738 #endif
1739 #ifndef RESOURCE_DUMPALL_IF
1740 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
1741 #endif
1742 #ifndef RESOURCE_LIST
1743 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
1744 #endif
1745 #ifndef RESOURCE_LIST_IF
1746 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
1747 #endif
1748 #endif /* NOBUG_DISABLE_SHORTNAMES */
1752 Tool macros
1754 #ifdef __GNUC__
1755 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
1756 #define NOBUG_ATTR_PRINTF(fmt, ell) __attribute__ ((format (printf, fmt, ell)))
1757 #else
1758 #define NOBUG_CLEANUP(fn)
1759 #define NOBUG_ATTR_PRINTF(fmt, ell)
1760 #endif
1763 //toolmacros PARA NOBUG_ALPHA_COMMA; NOBUG_ALPHA_COMMA; append something after a comma in *ALPHA* builds
1764 //toolmacros NOBUG_ALPHA_COMMA(something)
1765 //toolmacros NOBUG_ALPHA_COMMA_NULL
1766 //toolmacros
1767 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
1768 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
1769 //toolmacros use this macros to append a comman and something else only in *ALPHA* builds as in:
1770 //toolmacros struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
1771 //toolmacros
1773 #define NOBUG_COMMA ,
1774 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
1775 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
1777 #define NOBUG_ONCE(code) \
1778 do { \
1779 static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 1; \
1780 if (NOBUG_EXPECT_FALSE(NOBUG_CAT(nobug_once_,__LINE__))) \
1782 NOBUG_CAT(nobug_once_,__LINE__) = 0; \
1783 code; \
1785 } while (0)
1787 #if __GNUC__
1788 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
1789 #else
1790 #define NOBUG_EXPECT_FALSE(x) x
1791 #endif
1793 #define NOBUG_WHEN(when, ...) \
1794 do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
1797 //toolmacros PARA NOBUG_IF_*; NOBUG_IF; include code conditionally on build level
1798 //toolmacros NOBUG_IF_ALPHA(...)
1799 //toolmacros NOBUG_IF_NOT_ALPHA(...)
1800 //toolmacros NOBUG_IF_BETA(...)
1801 //toolmacros NOBUG_IF_NOT_BETA(...)
1802 //toolmacros NOBUG_IF_RELEASE(...)
1803 //toolmacros NOBUG_IF_NOT_RELEASE(...)
1804 //toolmacros
1805 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
1806 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
1807 //toolmacros internally, but can also be used for custom things.
1808 //toolmacros
1810 #define NOBUG_IF_ALPHA(...) \
1811 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1813 #define NOBUG_IF_NOT_ALPHA(...) \
1814 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1816 #define NOBUG_IF_BETA(...) \
1817 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__) \
1819 #define NOBUG_IF_NOT_BETA(...) \
1820 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__) \
1822 #define NOBUG_IF_RELEASE(...) \
1823 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1825 #define NOBUG_IF_NOT_RELEASE(...) \
1826 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1829 preprocessor hacks/metaprogramming
1832 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
1833 #define NOBUG_IF_1(...) __VA_ARGS__
1834 #define NOBUG_IF_0(...)
1836 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
1838 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
1839 #define NOBUG_NOT_1 0
1840 #define NOBUG_NOT_0 1
1842 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
1843 #define NOBUG_AND_00 0
1844 #define NOBUG_AND_01 0
1845 #define NOBUG_AND_10 0
1846 #define NOBUG_AND_11 1
1848 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
1849 #define NOBUG_OR_00 0
1850 #define NOBUG_OR_01 1
1851 #define NOBUG_OR_10 1
1852 #define NOBUG_OR_11 1
1854 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
1855 #define NOBUG_XOR_00 0
1856 #define NOBUG_XOR_01 1
1857 #define NOBUG_XOR_10 1
1858 #define NOBUG_XOR_11 0
1860 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
1861 #define NOBUG_CAT_(a,b) a##b
1863 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
1864 #define NOBUG_CAT3_(a,b,c) a##b##c
1866 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
1867 #define NOBUG_STRINGIZE_(s) #s
1871 LIBNOBUG DECLARATIONS
1873 #ifdef __cplusplus
1874 extern "C" {
1875 #elif 0
1876 } /* fix emacs indent */
1877 #endif
1879 #ifndef LLIST_DEFINED
1880 #define LLIST_DEFINED
1881 struct llist_struct
1883 struct llist_struct *next;
1884 struct llist_struct *prev;
1886 #endif
1889 source context
1892 struct nobug_context
1894 const char* file;
1895 int line;
1896 const char* func;
1899 const char*
1900 nobug_basename (const char* const file);
1903 envvar control
1905 enum nobug_log_targets
1907 NOBUG_TARGET_RINGBUFFER,
1908 NOBUG_TARGET_CONSOLE,
1909 NOBUG_TARGET_FILE,
1910 NOBUG_TARGET_SYSLOG,
1911 NOBUG_TARGET_APPLICATION
1914 struct nobug_flag
1916 const char* name;
1917 struct nobug_flag* parent;
1918 volatile int initialized;
1919 int limits[5];
1920 struct nobug_ringbuffer* ringbuffer_target;
1921 FILE* console_target;
1922 FILE* file_target;
1926 nobug_env_parse_flag (const char* env, struct nobug_flag* flag, int default_target, int default_limit, const struct nobug_context context);
1929 nobug_env_init_flag (struct nobug_flag* flag, int default_target, int default_limit, const struct nobug_context context);
1933 ringbuffer
1935 struct nobug_ringbuffer
1937 struct llist_struct node; /* all ringbufers are chained together, needed for sync */
1938 char* pos;
1939 char* start;
1940 size_t size;
1941 size_t maxmsg;
1942 char name[256];
1945 enum nobug_ringbuffer_flags
1947 NOBUG_RINGBUFFER_DEFAULT, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
1948 NOBUG_RINGBUFFER_APPEND = 1, /* use existing backing file, append if possible */
1949 NOBUG_RINGBUFFER_TEMP = 2, /* unlink file instantly */
1950 NOBUG_RINGBUFFER_KEEP = 4 /* dont unlink the file at destroy */
1954 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
1955 with sane (but undefined) semantics.
1957 struct nobug_ringbuffer*
1958 nobug_ringbuffer_init (struct nobug_ringbuffer* self, size_t size,
1959 const char * name, int flags);
1961 struct nobug_ringbuffer*
1962 nobug_ringbuffer_new (size_t size, const char * name, int flags);
1964 struct nobug_ringbuffer*
1965 nobug_ringbuffer_destroy (struct nobug_ringbuffer* self);
1967 void
1968 nobug_ringbuffer_delete (struct nobug_ringbuffer* self);
1970 void
1971 nobug_ringbuffer_sync (struct nobug_ringbuffer* self);
1973 void
1974 nobug_ringbuffer_allsync (void);
1977 nobug_ringbuffer_vprintf (struct nobug_ringbuffer* self, const char* fmt, va_list ap);
1980 nobug_ringbuffer_printf (struct nobug_ringbuffer* self, const char* fmt, ...);
1982 char*
1983 nobug_ringbuffer_append (struct nobug_ringbuffer* self);
1985 char*
1986 nobug_ringbuffer_prev (struct nobug_ringbuffer* self, char* pos);
1988 char*
1989 nobug_ringbuffer_next (struct nobug_ringbuffer* self, char* pos);
1992 nobug_ringbuffer_save (struct nobug_ringbuffer* self, FILE* out);
1995 nobug_ringbuffer_load (struct nobug_ringbuffer* self, FILE* in);
1997 char*
1998 nobug_ringbuffer_pos (struct nobug_ringbuffer* self);
2000 void
2001 nobug_ringbuffer_pop (struct nobug_ringbuffer* self);
2005 multithreading extras
2007 #if NOBUG_USE_PTHREAD
2009 struct nobug_tls_data
2011 const char* thread_id;
2012 unsigned thread_num; /* thread counter at initialization, gives a unique thread number */
2013 unsigned thread_gen; /* incremented at each name reset, (currently unused) */
2014 void* data;
2015 struct llist_struct res_stack; /* resources of this thread */
2018 extern pthread_key_t nobug_tls_key;
2020 struct nobug_tls_data*
2021 nobug_thread_set (const char* name);
2023 struct nobug_tls_data*
2024 nobug_thread_get (void);
2026 const char*
2027 nobug_thread_id_set (const char* name);
2029 const char*
2030 nobug_thread_id_get (void);
2032 extern pthread_mutex_t nobug_logging_mutex;
2033 extern pthread_mutex_t nobug_resource_mutex;
2034 #endif
2036 void**
2037 nobug_thread_data (void);
2040 resource registry
2043 #if NOBUG_USE_PTHREAD
2044 #define NOBUG_RESOURCE_LOCK pthread_mutex_lock (&nobug_resource_mutex)
2045 #define NOBUG_RESOURCE_UNLOCK pthread_mutex_unlock (&nobug_resource_mutex)
2046 #define NOBUG_LOGGING_LOCK pthread_mutex_lock (&nobug_logging_mutex)
2047 #define NOBUG_LOGGING_UNLOCK pthread_mutex_unlock (&nobug_logging_mutex)
2048 #else
2049 #define NOBUG_RESOURCE_LOCK
2050 #define NOBUG_RESOURCE_UNLOCK
2051 #define NOBUG_LOGGING_LOCK
2052 #define NOBUG_LOGGING_UNLOCK
2053 #endif
2055 enum nobug_resource_state
2057 NOBUG_RESOURCE_INVALID,
2058 NOBUG_RESOURCE_WAITING,
2059 NOBUG_RESOURCE_TRYING,
2060 NOBUG_RESOURCE_EXCLUSIVE,
2061 NOBUG_RESOURCE_RECURSIVE,
2062 NOBUG_RESOURCE_SHARED
2066 struct nobug_resource_header
2068 struct llist_struct node; /* link node for resource registry or users */
2069 const char* name; /* name */
2070 struct nobug_context extra; /* context information */
2073 struct nobug_resource_node;
2074 struct nobug_resource_user;
2076 struct nobug_resource_record
2078 struct nobug_resource_header hdr;
2080 struct llist_struct users; /* list of users of this resource */
2081 const void* object_id; /* unique identifer, usually a this pointer or similar */
2082 const char* type; /* type */
2084 #if NOBUG_USE_PTHREAD
2085 struct llist_struct nodes;
2086 #endif
2090 struct nobug_resource_node
2092 struct llist_struct node; /* all nodes for one resource */
2094 struct nobug_resource_record* resource; /* backpointer */
2095 struct nobug_resource_node* parent; /* upwards the tree */
2097 struct llist_struct childs; /* down the tree, all nodes pointing to here (TODO make this a slist) */
2098 struct llist_struct cldnode; /* node to accumulate all childrens of a parent (TODO slist) */
2102 struct nobug_resource_user
2104 struct nobug_resource_header hdr;
2106 struct nobug_resource_node* current; /* this resource */
2107 enum nobug_resource_state state; /* state */
2109 #if NOBUG_USE_PTHREAD
2110 struct nobug_tls_data* thread; /* pointer to this theads id */
2111 struct llist_struct res_stack; /* resources of this thread */
2112 #endif
2116 extern const char* nobug_resource_error;
2118 extern const char* nobug_resource_states[];
2121 void
2122 nobug_resource_init (void);
2124 void
2125 nobug_resource_destroy (void);
2128 struct nobug_resource_record*
2129 nobug_resource_announce (const char* type, const char* name, const void* object_id, const struct nobug_context extra);
2132 nobug_resource_forget (struct nobug_resource_record* node);
2135 struct nobug_resource_user*
2136 nobug_resource_enter (struct nobug_resource_record* resource,
2137 const char* name,
2138 enum nobug_resource_state state,
2139 const struct nobug_context extra);
2142 nobug_resource_leave (struct nobug_resource_user* handle);
2145 unsigned
2146 nobug_resource_record_available (void);
2149 unsigned
2150 nobug_resource_user_available (void);
2153 #if NOBUG_USE_PTHREAD
2154 unsigned
2155 nobug_resource_node_available (void);
2156 #endif
2159 struct nobug_resource_dump_context
2161 struct nobug_flag* flag;
2162 int level;
2163 struct nobug_context ctx;
2166 enum nobug_resource_state
2167 nobug_resource_mystate (struct nobug_resource_record* res);
2169 void
2170 nobug_resource_dump (struct nobug_resource_record* resource, const struct nobug_resource_dump_context* context);
2172 void
2173 nobug_resource_dump_all (const struct nobug_resource_dump_context* context);
2176 nobug_resource_state (struct nobug_resource_user* resource,
2177 enum nobug_resource_state state);
2180 void
2181 nobug_resource_list (const struct nobug_resource_dump_context* context);
2185 global config, data and defaults
2187 void nobug_init (const struct nobug_context context);
2190 the destroy function is optional, since nobug should stay alive for the whole application lifetime
2191 (and destroying is global!) it is only provided for the nobug testsuite itself
2193 void nobug_destroy (const struct nobug_context context);
2195 void
2196 nobug_backtrace_glibc (const struct nobug_context context);
2198 void
2199 nobug_log (struct nobug_flag* flag, int lvl, const char* what,
2200 const struct nobug_context ctx,
2201 const char* fmt, ...) NOBUG_ATTR_PRINTF(5, 6);
2204 extern struct nobug_ringbuffer nobug_default_ringbuffer;
2205 extern FILE* nobug_default_file;
2206 extern struct nobug_flag nobug_flag_NOBUG_ON;
2207 extern struct nobug_flag nobug_flag_NOBUG_ANN;
2208 extern struct nobug_flag nobug_flag_nobug;
2209 extern unsigned long long nobug_counter;
2211 //callbacks HEAD- Callbacks;;
2212 //callbacks
2213 //callbacks NoBug provides callbacks, applications can use these
2214 //callbacks to present logging information in some custom way or hook some special processing in.
2215 //callbacks The callbacks are initialized to NULL and never modified by NoBug, its the solve responsibility
2216 //callbacks of the user to manage them.
2217 //callbacks
2218 //callbacks CAUTION: There are certain constraints what and what not can be done in callbacks
2219 //callbacks documented below which must be followed.
2220 //callbacks
2221 //callbacks PARA type of logging callbacks; logging_cb; type of a logging callback function
2222 typedef void (*nobug_logging_cb)(const struct nobug_flag* flag, int priority, const char *log, void* data); //callbacks VERBATIM;
2223 //callbacks
2224 //callbacks used for the logging callbacks
2225 //callbacks
2226 //callbacks `flag`::
2227 //callbacks Flag structure which defines the logging configuration for this event
2228 //callbacks `priority`::
2229 //callbacks Log level of the current event
2230 //callbacks `log`::
2231 //callbacks Pointing to the current log line in the ringbuffer or `NULL`
2232 //callbacks `data`::
2233 //callbacks Global pointer defined by the user, passed arround (see below)
2234 //callbacks
2236 //callbacks PARA type of abort callback; abort_cb; type of a abort callback function
2237 typedef void (*nobug_abort_cb)(void* data); //callbacks VERBATIM;
2238 //callbacks
2239 //callbacks used for the abort callback
2240 //callbacks
2241 //callbacks `data`::
2242 //callbacks Global data defined by the user, passed arround (see below)
2243 //callbacks
2245 //callbacks PARA passing data to callbacks; callback_data; data to be passed to callbacks
2246 extern
2247 void* nobug_callback_data; //callbacks VERBATIM;
2248 //callbacks
2249 //callbacks This global variable is initialized to `NULL` and will never be touched by NoBug. One can use it
2250 //callbacks to pass extra data to the callback functions.
2251 //callbacks
2253 //callbacks PARA callback when logging; logging_callback; hook when something get logged
2254 extern
2255 nobug_logging_cb nobug_logging_callback; //callbacks VERBATIM;
2256 //callbacks
2257 //callbacks This callback gets called when something gets logged.
2258 //callbacks NoBug will still hold its mutexes when calling this hook, calling NoBug logging or resource tracking
2259 //callbacks functions from here recursively will deadlock and must be avoided.
2260 //callbacks The `log` parameter points to the logging message in the ringbuffer.
2261 //callbacks Unlike other logging targets it is not automatically limited to the log level configured
2262 //callbacks in the flag but called unconditionally. The callback should implement its own limiting.
2263 //callbacks
2264 //callbacks When one wants to do complex calls which may include recursion into logging and resource tracking
2265 //callbacks functions, the intended way is to pass contextual information possibly including a __copy__ of the
2266 //callbacks `log` parameter in xref:THREAD_DATA[NOBUG_THREAD_DATA] to the postlogging callback (see below).
2267 //callbacks Other internal NoBug facilties, like the ringbuffer etc, are protected by the mutexes and may be accessed
2268 //callbacks from this function.
2269 //callbacks
2271 //callbacks PARA callback after logging; postlogging_callback; hook after something get logged
2272 extern
2273 nobug_logging_cb nobug_postlogging_callback; //callbacks VERBATIM;
2274 //callbacks
2275 //callbacks This callback gets called after something got logged. The `log` parameter is always NULL and all
2276 //callbacks NoBug mutexes are released. This means that this function may call any complex things, including
2277 //callbacks calling logging and resource tracking, but may not call internal NoBug facilities.
2278 //callbacks Contextual created in the `nobug_logging_callback` and stored in xref:THREAD_DATA[NOBUG_THREAD_DATA] can be
2279 //callbacks retrieved here and may need to be cleaned up here.
2280 //callbacks
2282 //callbacks PARA callback for aborting; abort_callback; hook to handle a termination
2283 extern
2284 nobug_abort_cb nobug_abort_callback; //callbacks VERBATIM;
2285 //callbacks
2286 //callbacks This callback gets called when the application shall be terminated due an error.
2287 //callbacks It can be used to hook exceptions or similar things in. When it returns, `abort()`
2288 //callbacks is called.
2289 //callbacks
2290 //callbacks IMPORTANT: Errors detected by NoBug are always fatal. If one handles and possible
2291 //callbacks throws an exception here, the application must shut down as soon as possible.
2292 //callbacks Most causes for aborts are optimitzed out in `RELEASE` builds.
2293 //callbacks
2295 #ifdef __cplusplus
2296 } /* extern "C" */
2297 #endif
2299 #ifndef NOBUG_LIBNOBUG_C
2302 tag this translation unit as unchecked in ALPHA and BETA builds
2304 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED);
2306 #endif /* NOBUG_LIBNOBUG_C */
2307 #endif