NOBUG_THREAD_DATA for thread local storage of user data
[nobug.git] / src / nobug.h
blob42e8e5a3901804e3f2801c6259ee905a3b9b406d
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
105 #if NOBUG_MODE_RELEASE==0
107 //assertions PARA assert; assert; C standard assertion
108 //assertions assert(expr)
109 //assertions
110 //assertions NoBug overrides the standard assert macro in *ALPHA* and *BETA* builds.
111 //assertions This is just a compatibility feature, its use is not suggested.
112 //assertions
114 #undef assert
115 #define assert(expr) NOBUG_ASSERT(expr)
116 #endif
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__)))
224 //assertions PARA CHECK; CHECK; unnconditional assertion for testsuites
225 //assertions CHECK(expr, ...)
226 //assertions CHECK_IF(when, expr, ...)
227 //assertions
228 //assertions This assertion is never optimized out. Its main purpose is for implementing
229 //assertions testsuites where one want to assert tests independent of the build level
230 //assertions
232 #define NOBUG_CHECK(expr, ...) \
233 NOBUG_ASSERT_(expr, "CHECK", NOBUG_LOCATION_INFO, ## __VA_ARGS__)
235 #define NOBUG_CHECK_IF(when, expr, ...) \
236 NOBUG_WHEN(when, NOBUG_CHECK(expr, ## __VA_ARGS__))
241 low level assert
243 #define NOBUG_ASSERT_(expr, what, location, ...) \
244 NOBUG_WHEN (!(expr), \
245 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
246 location, what, "(%s) " \
247 NOBUG_HEAD(__VA_ARGS__), \
248 #expr NOBUG_TAIL(__VA_ARGS__)); \
249 NOBUG_BACKTRACE; \
250 NOBUG_ABORT \
253 #define NOBUG_ASSERT_DBG_(expr, what, location, ...) \
254 NOBUG_WHEN (NOBUG_ACTIVE_DBG && !(expr), \
255 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
256 location, what, "(%s) " \
257 NOBUG_HEAD(__VA_ARGS__), \
258 #expr NOBUG_TAIL(__VA_ARGS__)); \
259 NOBUG_BACKTRACE; \
260 NOBUG_ABORT \
265 //assertions PARA INVARIANT; INVARIANT; validate invariant state
266 //assertions INVARIANT(type, pointer, depth)
267 //assertions INVARIANT_DBG(type, pointer, depth)
268 //assertions INVARIANT_IF(when,type, pointer, depth)
269 //assertions INVARIANT_IF_DBG(when, type, pointer, depth)
270 //assertions
271 //assertions Checking invariants. You can provide more complex checking functions
272 //assertions which test the validity of datastructures. Invariants are only enabled
273 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
274 //assertions otherwise optimized out.
275 //assertions
276 //assertions TODO: describe how to create invariant checks
277 //assertions
279 #define NOBUG_INVARIANT(type, pointer, depth) \
280 NOBUG_IF_ALPHA( \
281 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
282 NOBUG_CAT(type,_invariant)(pointer, depth, \
283 NOBUG_LOCATION_ARGS) \
287 #define NOBUG_INVARIANT_DBG(type, pointer, ...) \
288 NOBUG_IF_ALPHA( \
289 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED && NOBUG_ACTIVE_DBG, \
290 NOBUG_CAT(type,_invariant)(pointer, depth, \
291 NOBUG_LOCATION_ARGS) \
295 #define NOBUG_INVARIANT_IF(when, type, pointer, ...) \
296 NOBUG_IF_ALPHA (NOBUG_WHEN (when, \
297 NOBUG_INVARIANT(type, pointer, ## __VA_ARGS__)) \
300 #define NOBUG_INVARIANT_IF_DBG(when, type, pointer, ...) \
301 NOBUG_IF_ALPHA (NOBUG_WHEN (when, \
302 NOBUG_INVARIANT_DBG(type, pointer, ## __VA_ARGS__))\
305 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
306 NOBUG_ASSERT_(expr, "INVARIANT", (file, line, func), ## __VA_ARGS__)
310 checked/unchecked tagged scopes
312 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
314 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
316 #define NOBUG_UNCHECKED \
317 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
318 NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
322 /*TODO dump-level for flags instead limits[0]*/
324 //dumpmacros PARA DUMP; DUMP; dumping datastructures
325 //dumpmacros DUMP(flag, type, pointer, depth)
326 //dumpmacros DUMP_IF(when, flag, type, pointer, depth)
327 //dumpmacros
328 //dumpmacros This macros call a datastructure dump of the object (`pointer`) in question.
329 //dumpmacros `DUMP_IF` is the only enabled dumping macro for the RELEASE build level.
330 //dumpmacros
332 #define NOBUG_DUMP(flag, type, pointer, depth) \
333 NOBUG_IF_NOT_RELEASE( \
334 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
335 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
336 NOBUG_LOCATION_ARGS) \
340 #define NOBUG_DUMP_DBG(flag, type, pointer, depth) \
341 NOBUG_IF_NOT_RELEASE( \
342 NOBUG_WHEN (NOBUG_ACTIVE_DBG && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
343 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
344 NOBUG_LOCATION_ARGS) \
348 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth) \
349 NOBUG_WHEN (when && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
350 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
351 NOBUG_LOCATION_ARGS) \
354 #define NOBUG_DUMP_IF_DBG(when, flag, type, pointer, depth) \
355 NOBUG_IF_NOT_RELEASE( \
356 NOBUG_WHEN (NOBUG_ACTIVE_DBG && when && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET],\
357 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
358 NOBUG_LOCATION_ARGS) \
364 //dumpmacros PARA DUMP_LOG; DUMP_LOG; logging helper for dumping
365 //dumpmacros DUMP_LOG(fmt, ...)
366 //dumpmacros DUMP_LOG_DBG(fmt, ...)
367 //dumpmacros DUMP_LOG_IF(when, fmt, ...)
368 //dumpmacros DUMP_LOG_IF_DBG(when, fmt, ...)
369 //dumpmacros
370 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
371 //dumpmacros
372 //dumpmacros Dumping is by default done on level `LOG_DEBUG`, this can be overridden by
373 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other level.
374 //dumpmacros
376 #define NOBUG_DUMP_LOG(fmt, ...) \
377 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
378 (file, line, func), "DUMP", \
379 fmt, ## __VA_ARGS__)
382 #define NOBUG_DUMP_LOG_DBG(fmt, ...) \
383 NOBUG_WHEN (NOBUG_ACTIVE_DBG, \
384 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
385 (file, line, func), "DUMP", \
386 fmt, ## __VA_ARGS__) \
389 #define NOBUG_DUMP_LOG_IF(expr, fmt, ...) \
390 NOBUG_WHEN (expr, \
391 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
392 (file, line, func), "DUMP", \
393 fmt, ## __VA_ARGS__) \
396 #define NOBUG_DUMP_LOG_IF_DBG(expr, fmt, ...) \
397 NOBUG_WHEN (NOBUG_ACTIVE_DBG && expr, \
398 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
399 (file, line, func), "DUMP", \
400 fmt, ## __VA_ARGS__) \
404 #ifndef NOBUG_DUMP_LEVEL
405 #define NOBUG_DUMP_LEVEL LOG_DEBUG
406 #endif
409 Logging
413 //logmacros PARA ECHO; ECHO; unconditional logging for tests
414 //logmacros ECHO(...)
415 //logmacros
416 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
417 //logmacros testsuites where one want to print and log messages independent of the build level
418 //logmacros
420 #define NOBUG_ECHO(...) \
421 NOBUG_LOG_(&nobug_flag_NOBUG_ON, LOG_NOTICE, NOBUG_LOCATION_INFO, "ECHO", ## __VA_ARGS__)
424 //logmacros PARA ALERT; ALERT; about to die
425 //logmacros ALERT(flag, ...)
426 //logmacros ALERT_DBG(flag, ...)
427 //logmacros ALERT_IF(when, flag, ...)
428 //logmacros ALERT_IF_DBG(when, flag, ...)
429 //logmacros
430 //logmacros This is the most critical condition an application might log. This might be used
431 //logmacros if an error occurs which can not be handled except a safe shutdown for example.
432 //logmacros
434 #define NOBUG_ALERT(flag, ...) \
435 NOBUG_LOG(flag, LOG_ALERT, ## __VA_ARGS__)
436 #define NOBUG_ALERT_IF(expr, flag, ...) \
437 NOBUG_LOG_IF(expr, flag, LOG_ALERT, ## __VA_ARGS__)
438 #define NOBUG_ALERT_DBG(flag, ...) \
439 NOBUG_LOG_DBG(flag, LOG_ALERT, ## __VA_ARGS__)
440 #define NOBUG_ALERT_IF_DBG(expr, flag, ...) \
441 NOBUG_LOG_IF_DBG(expr, flag, LOG_ALERT, ## __VA_ARGS__)
444 //logmacros PARA CRITICAL; CRITICAL; can not continue
445 //logmacros CRITICAL(flag, ...)
446 //logmacros CRITICAL_DBG(flag, ...)
447 //logmacros CRITICAL_IF(when, flag, ...)
448 //logmacros CRITICAL_IF_DBG(when, flag, ...)
449 //logmacros
450 //logmacros An error which can not be handled occured but the application does not need to be
451 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
452 //logmacros
454 #define NOBUG_CRITICAL(flag, ...) \
455 NOBUG_LOG(flag, LOG_CRIT, ## __VA_ARGS__)
456 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
457 NOBUG_LOG_IF(expr, flag, LOG_CRIT, ## __VA_ARGS__)
458 #define NOBUG_CRITICAL_DBG(flag, ...) \
459 NOBUG_LOG_DBG(flag, LOG_CRIT, ## __VA_ARGS__)
460 #define NOBUG_CRITICAL_IF_DBG(expr, flag, ...) \
461 NOBUG_LOG_IF_DBG(expr, flag, LOG_CRIT, ## __VA_ARGS__)
464 //logmacros PARA ERROR; ERROR; something gone wrong
465 //logmacros ERROR(flag, fmt, ...)
466 //logmacros ERROR_DBG(flag, fmt, ...)
467 //logmacros ERROR_IF(when, flag, fmt, ...)
468 //logmacros ERROR_IF_DBG(when, flag, fmt, ...)
469 //logmacros
470 //logmacros Application takes a error handling brach
471 //logmacros
473 #define NOBUG_ERROR(flag, ...) \
474 NOBUG_LOG(flag, LOG_ERR, ## __VA_ARGS__)
475 #define NOBUG_ERROR_IF(expr, flag, ...) \
476 NOBUG_LOG_IF(expr, flag, LOG_ERR, ## __VA_ARGS__)
477 #define NOBUG_ERROR_DBG(flag, ...) \
478 NOBUG_LOG_DBG(flag, LOG_ERR, ## __VA_ARGS__)
479 #define NOBUG_ERROR_IF_DBG(expr, flag, ...) \
480 NOBUG_LOG_IF_DBG(expr, flag, LOG_ERR, ## __VA_ARGS__)
483 //logmacros PARA WARN; WARN; unexpected fixable error
484 //logmacros WARN(flag, fmt, ...)
485 //logmacros WARN_DBG(flag, fmt, ...)
486 //logmacros WARN_IF(when, flag, fmt, ...)
487 //logmacros WARN_IF_DBG(when, flag, fmt, ...)
488 //logmacros
489 //logmacros Rare, handled but unexpected branch
490 //logmacros
492 #define NOBUG_WARN(flag, ...) \
493 NOBUG_LOG(flag, LOG_WARNING, ## __VA_ARGS__)
494 #define NOBUG_WARN_IF(expr, flag, ...) \
495 NOBUG_LOG_IF(expr, flag, LOG_WARNING, ## __VA_ARGS__)
496 #define NOBUG_WARN_DBG(flag, ...) \
497 NOBUG_LOG_DBG(flag, LOG_WARNING, ## __VA_ARGS__)
498 #define NOBUG_WARN_IF_DBG(expr, flag, ...) \
499 NOBUG_LOG_IF_DBG(expr, flag, LOG_WARNING, ## __VA_ARGS__)
502 //logmacros PARA INFO; INFO; progress message
503 //logmacros INFO(flag, fmt, ...)
504 //logmacros INFO_DBG(flag, fmt, ...)
505 //logmacros INFO_IF(when, flag, fmt, ...)
506 //logmacros INFO_IF_DBG(when, flag, fmt, ...)
507 //logmacros
508 //logmacros Message about program progress
509 //logmacros
511 #define NOBUG_INFO(flag, ...) \
512 NOBUG_LOG(flag, LOG_INFO, ## __VA_ARGS__)
513 #define NOBUG_INFO_IF(expr, flag, ...) \
514 NOBUG_LOG_IF(expr, flag, LOG_INFO, ## __VA_ARGS__)
515 #define NOBUG_INFO_DBG(flag, ...) \
516 NOBUG_LOG_DBG(flag, LOG_INFO, ## __VA_ARGS__)
517 #define NOBUG_INFO_IF_DBG(expr, flag, ...) \
518 NOBUG_LOG_IF_DBG(expr, flag, LOG_INFO, ## __VA_ARGS__)
521 //logmacros PARA NOTICE; NOTICE; detailed progress message
522 //logmacros NOTICE(flag, fmt, ...)
523 //logmacros NOTICE_DBG(flag, fmt, ...)
524 //logmacros NOTICE_IF(when, flag, fmt, ...)
525 //logmacros NOTICE_IF_DBG(when, flag, fmt, ...)
526 //logmacros
527 //logmacros More detailed progress message
528 //logmacros
530 #define NOBUG_NOTICE(flag, ...) \
531 NOBUG_LOG(flag, LOG_NOTICE, ## __VA_ARGS__)
532 #define NOBUG_NOTICE_IF(expr, flag, ...) \
533 NOBUG_LOG_IF(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
534 #define NOBUG_NOTICE_DBG(flag, ...) \
535 NOBUG_LOG_DBG(flag, LOG_NOTICE, ## __VA_ARGS__)
536 #define NOBUG_NOTICE_IF_DBG(expr, flag, ...) \
537 NOBUG_LOG_IF_DBG(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
540 //logmacros PARA TRACE; TRACE; debugging level message
541 //logmacros TRACE(flag, fmt, ...)
542 //logmacros TRACE_DBG(flag, fmt, ...)
543 //logmacros TRACE_IF(when, flag, fmt, ...)
544 //logmacros TRACEIF_DBG(when, flag, fmt, ...)
545 //logmacros
546 //logmacros Very fine grained messages
547 //logmacros
548 //logmacros NOTE: that `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
549 //logmacros
551 #define NOBUG_TRACE(flag, ...) \
552 NOBUG_LOG(flag, LOG_DEBUG, ## __VA_ARGS__)
553 #define NOBUG_TRACE_IF(expr, flag, ...) \
554 NOBUG_LOG_IF(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
555 #define NOBUG_TRACE_DBG(flag, ...) \
556 NOBUG_LOG_DBG(flag, LOG_DEBUG, ## __VA_ARGS__)
557 #define NOBUG_TRACE_IF_DBG(expr, flag, ...) \
558 NOBUG_LOG_IF_DBG(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
562 //logmacros PARA LOG; LOG; generic logging
563 //logmacros LOG(flag, lvl, fmt, ...)
564 //logmacros LOG_DBG(flag, lvl, fmt, ...)
565 //logmacros LOG_IF(when, flag, lvl, fmt, ...)
566 //logmacros LOG_IF_DBG(when, flag, lvl, fmt, ...)
567 //logmacros
568 //logmacros Generic logging macro which takes the level explicitly,
569 //logmacros avoid this, unless you implement your own logging facilities.
570 //logmacros
572 #define NOBUG_LOG(flag, lvl, ...) \
573 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
574 NOBUG_LVL(lvl), ## __VA_ARGS__)
576 #define NOBUG_LOG_DBG(flag, lvl, ...) \
577 NOBUG_WHEN (NOBUG_ACTIVE_DBG, \
578 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
579 NOBUG_LVL(lvl), ## __VA_ARGS__) \
582 #define NOBUG_LOG_IF(expr, flag, lvl, ...) \
583 NOBUG_WHEN (expr, \
584 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
585 NOBUG_LVL(lvl), ## __VA_ARGS__) \
588 #define NOBUG_LOG_IF_DBG(expr, flag, lvl, ...) \
589 NOBUG_WHEN (NOBUG_ACTIVE_DBG && expr, \
590 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
591 NOBUG_LVL(lvl), ## __VA_ARGS__) \
596 low level logging handler
598 #define NOBUG_LOG_(flag, lvl, location, what, ...) \
599 NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER], \
600 nobug_log (flag, lvl, \
601 "%.10llu: %s: %s:%d:"NOBUG_THREAD_ID_FMT(" ",":")" %s: " \
602 NOBUG_HEAD(__VA_ARGS__), ++nobug_counter, what, \
603 NOBUG_LOCATION_FILE location, \
604 NOBUG_LOCATION_LINE location NOBUG_THREAD_ID_COMMA, \
605 NOBUG_LOCATION_FUNC location NOBUG_TAIL(__VA_ARGS__)) \
608 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
609 #define NOBUG_LVL_0 "EMERG"
610 #define NOBUG_LVL_1 "ALERT"
611 #define NOBUG_LVL_2 "CRIT"
612 #define NOBUG_LVL_3 "ERR"
613 #define NOBUG_LVL_4 "WARNING"
614 #define NOBUG_LVL_5 "NOTICE"
615 #define NOBUG_LVL_6 "INFO"
616 #define NOBUG_LVL_7 "TRACE"
619 //logmacros PARA LOG_BASELIMIT; LOG_BASELIMIT; minimum compliled-in logging limit
620 //logmacros NOBUG_LOG_BASELIMIT_ALPHA
621 //logmacros NOBUG_LOG_BASELIMIT_BETA
622 //logmacros NOBUG_LOG_BASELIMIT_RELEASE
623 //logmacros NOBUG_LOG_BASELIMIT
624 //logmacros
625 //logmacros NoBug defines some logging base limits, anything more detailed
626 //logmacros than this base limits will be optimized out. This is used to
627 //logmacros reduce the logging overhead for *RELEASE* builds.
628 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
629 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
630 //logmacros builds to log the application progress only coarsely then.
631 //logmacros
632 //logmacros This macros can be defined before including 'nobug.h' to some other
633 //logmacros log level (as defined in 'syslog.h').
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
660 alpha beta release
661 DEPRECATED log nothing wont compile
663 //annotations PARA DEPRECATED; DEPRECATED; to be discarded in future
664 //annotations DEPRECATED(...)
665 //annotations
666 //annotations Something which shouldn't be used in future
667 //annotations
669 #define NOBUG_DEPRECATED(msg) \
670 NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN, \
671 NOBUG_LOCATION_INFO, "DEPRECATED", msg) \
673 NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
677 alpha beta release
678 UNIMPLEMENTED abort abort wont compile
680 //annotations PARA UNIMPLEMENTED; UNIMPLEMENTED; not yet implemented
681 //annotations UNIMPLEMENTED(...)
682 //annotations
683 //annotations not yet finished feature
684 //annotations
686 #define NOBUG_UNIMPLEMENTED(msg) \
687 NOBUG_IF_NOT_RELEASE ( do { \
688 NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG, NOBUG_LOCATION_INFO, \
689 "UNIMPLEMENTED", msg); \
690 NOBUG_ABORT; \
691 } while (0)) \
692 NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
696 alpha beta release
697 FIXME log wont compile wont compile
699 //annotations PARA FIXME; FIXME; known bug
700 //annotations FIXME(...)
701 //annotations
702 //annotations known bug to be fixed later
703 //annotations
705 #define NOBUG_FIXME(msg) \
706 NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT, \
707 NOBUG_LOCATION_INFO, "FIXME", msg))) \
708 NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(msg)) \
709 NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
713 alpha beta release
714 TODO log log wont compile
716 //annotations PARA TODO; TODO; things to be done
717 //annotations TODO(...)
718 //annotations
719 //annotations enhancement to be done soon
720 //annotations
722 #define NOBUG_TODO(msg) \
723 NOBUG_IF_NOT_RELEASE ( \
724 NOBUG_ONCE ( \
725 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE, NOBUG_LOCATION_INFO, \
726 "TODO", msg); \
727 )) \
728 NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
732 alpha beta release
733 PLANNED log nothing nothing
735 //annotations PARA PLANNED; PLANNED; ideas for future
736 //annotations PLANNED(...)
737 //annotations
738 //annotations future enhancement
739 //annotations
741 #define NOBUG_PLANNED(msg) \
742 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO, \
743 NOBUG_LOCATION_INFO, "PLANNED", msg)))
747 alpha beta release
748 NOTREACHED abort abort nothing
750 //annotations PARA NOTREACHED; NOTREACHED; code path never taken
751 //annotations NOTREACHED
752 //annotations
753 //annotations used to tag code-path which shall be never executed (defaults in switch
754 //annotations statements, `else NOTREACHED;` after series of if's, etc.)
755 //annotations
757 #define NOBUG_NOTREACHED \
758 NOBUG_IF_NOT_RELEASE( do { \
759 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
760 NOBUG_LOCATION_INFO, "NOTREACHED"); \
761 NOBUG_ABORT; \
762 } while (0))
766 Fault injection
768 //faultinjection NoBug has some macros which can be used to simulate errorneous behaviour:
769 //faultinjection
771 //faultinjection PARA INJECT_GOODBAD; INJECT_GOODBAD; fault injection expression
772 //faultinjection INJECT_GOODBAD(expr, good, bad)
773 //faultinjection
774 //faultinjection substitutes to an expression and returns good when expr is false and
775 //faultinjection bad when expr is true. In BETA and RELEASE builds 'good' is always returned.
776 //faultinjection
778 #define NOBUG_INJECT_GOODBAD(expr, good, bad) \
779 NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);}),bad:good) \
780 NOBUG_IF_NOT_ALPHA(good)
784 //faultinjection PARA INJECT_FAULT; INJECT_FAULT; fault injection statement
785 //faultinjection INJECT_FAULT(expr, bad)
786 //faultinjection
787 //faultinjection substitutes to a statement which executes 'bad'
788 //faultinjection when expr is true. Optimitzed out in BETA and RELEASE builds.
789 //faultinjection
791 #define NOBUG_INJECT_FAULT(expr, bad) \
792 NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
796 //faultinjection PARA INJECT_LEVEL; INJECT_LEVEL; log level for fault injection
797 //faultinjection In both cases, when a fault is injected it will be logged at
798 //faultinjection `NOBUG_INJECT_LEVEL` (default: `LOG_NOTICE`). This can be defined
799 //faultinjection before including 'nobug.h' to override it.
800 //faultinjection
802 #define NOBUG_INJECT_LOG(msg) \
803 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
804 NOBUG_LOCATION_INFO, "INJECT_FAULT", \
805 msg)
808 #ifndef NOBUG_INJECT_LEVEL
809 #define NOBUG_INJECT_LEVEL LOG_NOTICE
810 #endif
814 Flag handling
816 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_, name)
819 //predefflags PARA NOBUG_FLAG_RAW; NOBUG_FLAG_RAW; pass direct flag pointer
820 //predefflags NOBUG_FLAG_RAW(ptr)
821 //predefflags
822 //predefflags Using this macro one can pass a direct pointer to a flag where a name would
823 //predefflags be expected. This is sometimes convinient when flag pointers are passed around
824 //predefflags in management strutures and one wants to tie logging to dynamic targets.
825 //predefflags
826 //predefflags [source,c]
827 //predefflags ----
828 //predefflags NOBUG_DEFINE_FLAG(myflag);
829 //predefflags ...
830 //predefflags struct nobug_flag* ptr = &NOBUG_FLAG(myflag);
831 //predefflags TRACE(NOBUG_FLAG_RAW(ptr), "Passed flag by pointer")
832 //predefflags ----
833 //predefflags
835 #define nobug_flag_NOBUG_FLAG_RAW(name) *name
837 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
840 #define NOBUG_DEFINE_FLAG(name) \
841 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
842 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
843 struct nobug_flag NOBUG_FLAG(name) = \
844 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
845 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
846 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
847 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
848 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
849 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
853 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
854 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
855 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
856 NOBUG_DECLARE_FLAG(parent); \
857 struct nobug_flag NOBUG_FLAG(name) = \
858 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
859 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
860 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
861 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
862 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
863 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
867 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) \
868 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
869 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
870 struct nobug_flag NOBUG_FLAG(name) = \
871 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
872 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
873 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
874 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
875 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
876 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
880 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
881 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
882 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
883 NOBUG_DECLARE_FLAG(parent); \
884 struct nobug_flag NOBUG_FLAG(name) = \
885 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
886 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
887 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
888 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
889 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
890 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
894 #define NOBUG_INIT_FLAG(name) \
895 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT)
898 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
899 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default)
902 #define NOBUG_CPP_DEFINE_FLAG(name) \
903 NOBUG_FLAG_IF_DECLAREONLY( \
904 NOBUG_DECLARE_FLAG(name); \
905 extern int nobug_cppflag_##name \
907 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
908 NOBUG_DEFINE_FLAG(name); \
909 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
913 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
914 NOBUG_FLAG_IF_DECLAREONLY( \
915 NOBUG_DECLARE_FLAG(name); \
916 extern int nobug_cppflag_##name \
918 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
919 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
920 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
924 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
925 NOBUG_FLAG_IF_DECLAREONLY( \
926 NOBUG_DECLARE_FLAG(name); \
927 extern int nobug_cppflag_##name \
929 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
930 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
931 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
935 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
936 NOBUG_FLAG_IF_DECLAREONLY( \
937 NOBUG_DECLARE_FLAG(name); \
938 extern int nobug_cppflag_##name \
940 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
941 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
942 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
946 #ifndef NOBUG_DECLARE_ONLY
947 #define NOBUG_DECLARE_ONLY 0
948 #endif
950 #define NOBUG_FLAG_IF_DECLAREONLY(...) \
951 NOBUG_IF(NOBUG_DECLARE_ONLY, __VA_ARGS__)
953 #define NOBUG_FLAG_IF_NOT_DECLAREONLY(...) \
954 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
956 #ifdef __cplusplus
957 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
958 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
959 #else
960 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
961 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, NOBUG_ERROR_CANT_DEFINE_AUTOINITIALIZED_CPP_FLAGS_IN_C)
962 #endif
964 #ifndef NOBUG_LOG_LIMIT_ALPHA
965 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
966 #endif
967 #ifndef NOBUG_LOG_LIMIT_BETA
968 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
969 #endif
970 #ifndef NOBUG_LOG_LIMIT_RELEASE
971 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
972 #endif
974 #ifndef NOBUG_LOG_LIMIT
975 # define NOBUG_LOG_LIMIT \
976 NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA) \
977 NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA) \
978 NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
979 #endif
981 #ifndef NOBUG_LOG_TARGET_ALPHA
982 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
983 #endif
984 #ifndef NOBUG_LOG_TARGET_BETA
985 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
986 #endif
987 #ifndef NOBUG_LOG_TARGET_RELEASE
988 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
989 #endif
991 #ifndef NOBUG_LOG_TARGET
992 # define NOBUG_LOG_TARGET \
993 NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA) \
994 NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA) \
995 NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
996 #endif
998 #define NOBUG_SET_LIMIT(flag, min) \
999 NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
1003 Resource registry macros
1007 //index.resource_logging xref:RESOURCE_LOGGING[RESOURCE_LOGGING]:: switch resource logging on and off
1008 //index.resource_log_level xref:RESOURCE_LOGGING[RESOURCE_LOG_LEVEL]:: select the log level for resource logging
1009 //resourcemacros [[RESOURCE_LOGGING]]
1010 //resourcemacros
1011 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
1012 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
1013 //resourcemacros `LOG_DEBUG`.
1014 //resourcemacros
1016 #ifndef NOBUG_RESOURCE_LOGGING
1017 #define NOBUG_RESOURCE_LOGGING 1
1018 #endif
1020 #ifndef NOBUG_RESOURCE_LOG_LEVEL
1021 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
1022 #endif
1026 //index.resource_handle xref:RESOURCE_HANDLE[RESOURCE_HANDLE]:: define an resource handle
1027 //resourcemacros [[RESOURCE_HANDLE]]
1028 //resourcemacros Resources are accessed through handles.
1029 //resourcemacros
1030 //resourcemacros .RESOURCE_HANDLE
1031 //resourcemacros RESOURCE_HANDLE(name)
1032 //resourcemacros
1033 //resourcemacros Defines handles to access resources.
1034 //resourcemacros
1035 //resourcemacros `name`::
1036 //resourcemacros identifer to be used for the handle
1037 //resourcemacros
1038 //resourcemacros This macro takes care that the declaration is optimized out in the same manner
1039 //resourcemacros the rest of the resource tracker would be disabled. You can still instantiate
1040 //resourcemacros handles as `struct nobug_resource_header*` in structures which must have a
1041 //resourcemacros constant size unconditional of the build level.
1042 //resourcemacros
1044 #define NOBUG_RESOURCE_HANDLE(handle) \
1045 NOBUG_IF_ALPHA(struct nobug_resource_header* handle)
1047 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1051 //index.resource_announce xref:RESOURCE_ANNOUNCE[RESOURCE_ANNOUNCE]:: publish new resources
1052 //resourcemacros [[RESOURCE_ANNOUNCE]]
1053 //resourcemacros
1054 //resourcemacros .RESOURCE_ANNOUNCE
1055 //resourcemacros RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
1056 //resourcemacros
1057 //resourcemacros Publishes resources.
1058 //resourcemacros
1059 //resourcemacros `flag`::
1060 //resourcemacros the NoBug flag which turns logging on for this macro
1061 //resourcemacros `type`::
1062 //resourcemacros a string which should denote the domain of the resource,
1063 //resourcemacros examples are "file", "mutex", "lock", "database" and so on
1064 //resourcemacros `name`::
1065 //resourcemacros the actual name of a named resource this as string which
1066 //resourcemacros together with type forms a unique identifier of the resource. `type` and
1067 //resourcemacros `name` must be available through the entire lifetime of the resource, using
1068 //resourcemacros literal strings is recommended
1069 //resourcemacros `identifier`::
1070 //resourcemacros a pointer which should be unique for this resource, any
1071 //resourcemacros kind of pointer will suffice, it is only used for identification. In
1072 //resourcemacros multithreaded applications the thread identifier becomes an additional
1073 //resourcemacros identifier
1074 //resourcemacros `handle`::
1075 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to point to
1076 //resourcemacros the newly created resource.
1077 //resourcemacros
1078 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
1079 //resourcemacros announced more than one time.
1080 //resourcemacros
1082 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
1083 NOBUG_RESOURCE_ANNOUNCE_RAW(&NOBUG_FLAG(flag), type, name, ptr, handle)
1085 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
1086 NOBUG_IF_ALPHA( do { \
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__)))->hdr, \
1094 "RESOURCE_ASSERT_ANNOUNCE", NOBUG_LOCATION_INFO, \
1095 "%s: %s@%p %s", type, name, ptr, nobug_resource_error); \
1096 } while (0))
1100 //index.resource_forget xref:RESOURCE_FORGET[RESOURCE_FORGET]:: remove resources
1101 //resourcemacros [[RESOURCE_FORGET]]
1102 //resourcemacros
1103 //resourcemacros .RESOURCE_FORGET
1104 //resourcemacros RESOURCE_FORGET(flag, handle)
1105 //resourcemacros
1106 //resourcemacros Removes resources that have become unavailable from the registry.
1107 //resourcemacros
1108 //resourcemacros `flag`::
1109 //resourcemacros the NoBug flag which turns logging on for this macro
1110 //resourcemacros `handle`::
1111 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1112 //resourcemacros
1113 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1114 //resourcemacros error is raised.
1115 //resourcemacros
1117 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1118 NOBUG_RESOURCE_FORGET_RAW(&NOBUG_FLAG(flag), handle)
1120 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1121 NOBUG_IF_ALPHA( do { \
1122 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1123 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1124 "RESOURCE_FORGET", "%s: %s@%p", \
1125 handle?((struct nobug_resource_record*)handle)->type:"", \
1126 handle?handle->name:"", \
1127 handle?((struct nobug_resource_record*)handle)->object_id:NULL);) \
1128 NOBUG_RESOURCE_ASSERT(nobug_resource_forget ((struct nobug_resource_record*)handle), \
1129 "RESOURCE_ASSERT_FORGET", NOBUG_LOCATION_INFO, "%s: %s@%p: %s", \
1130 handle?((struct nobug_resource_record*)handle)->type:"", \
1131 handle?handle->name:"", \
1132 handle?((struct nobug_resource_record*)handle)->object_id:NULL, \
1133 nobug_resource_error); \
1134 handle = NULL; \
1135 } while (0))
1139 //index.resource_enter xref:RESOURCE_ENTER[RESOURCE_ENTER]:: claim a resource
1140 //resourcemacros [[RESOURCE_ENTER]]
1141 //resourcemacros
1142 //resourcemacros .RESOURCE_ENTER
1143 //resourcemacros RESOURCE_ENTER(flag, announced, name, identifier, state, handle)
1144 //resourcemacros
1145 //resourcemacros Attach a resource to code.
1146 //resourcemacros
1147 //resourcemacros `flag`::
1148 //resourcemacros nobug flag which turns logging on for this macro
1149 //resourcemacros `resource`::
1150 //resourcemacros the handle set by `RESOURCE_ANNOUNCE`
1151 //resourcemacros `name`::
1152 //resourcemacros a free-form identifier
1153 //resourcemacros `identifier`::
1154 //resourcemacros some pointer which must be unique for the user of the
1155 //resourcemacros resource (see above)
1156 //resourcemacros `state`::
1157 //resourcemacros the initial state, one of `NOBUG_RESOURCE_WAITING`,
1158 //resourcemacros `NOBUG_RESOURCE_EXCLUSIVE` or `NOBUG_RESOURCE_RECURSIVE`
1159 //resourcemacros `handle`::
1160 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to the
1161 //resourcemacros entering node
1162 //resourcemacros
1164 #define NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle) \
1165 NOBUG_IF_ALPHA( do { \
1166 NOBUG_REQUIRE(resource, "Announced resource handle not initialized"); \
1167 NOBUG_REQUIRE(!handle, "Resource handle already entered"); \
1168 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1169 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, \
1170 NOBUG_LOCATION_INFO, "RESOURCE_ENTER", \
1171 "%s: %s@%p: %s: %s", \
1172 resource?((struct nobug_resource_record*)resource)->type:"", \
1173 resource?resource->name:"", \
1174 resource?((struct nobug_resource_record*)resource)->object_id:NULL, \
1175 user, \
1176 nobug_resource_states[state]);) \
1177 NOBUG_RESOURCE_ASSERT(handle = &nobug_resource_enter ((struct nobug_resource_record*)resource, \
1178 user, state, \
1179 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__)))->hdr, \
1180 "RESOURCE_ASSERT_ENTER", NOBUG_LOCATION_INFO, \
1181 "%s: %s@%p: %s: %s: %s", \
1182 resource?((struct nobug_resource_record*)resource)->type:"", \
1183 resource?resource->name:"", \
1184 resource?((struct nobug_resource_record*)resource)->object_id:NULL, \
1185 user, nobug_resource_states[state], \
1186 nobug_resource_error); \
1187 } while (0))
1191 //index.resource_state xref:RESOURCE_STATE[RESOURCE_STATE]:: change the state of a resource
1192 //resourcemacros [[RESOURCE_STATE]]
1193 //resourcemacros
1194 //resourcemacros .NOBUG_RESOURCE_STATE
1195 //resourcemacros NOBUG_RESOURCE_STATE(flag, entered, state)
1196 //resourcemacros
1197 //resourcemacros Changes resource's state.
1198 //resourcemacros
1199 //resourcemacros `flag`::
1200 //resourcemacros is nobug flag which turns logging on for this macro
1201 //resourcemacros `state`::
1202 //resourcemacros the new state Note that only certain state transitions are
1203 //resourcemacros allowed, see discussion/diagram above
1204 //resourcemacros `entered`::
1205 //resourcemacros the handle set by `RESOURCE_ENTER`
1206 //resourcemacros
1208 #define NOBUG_RESOURCE_STATE(flag, state, entered) \
1209 NOBUG_RESOURCE_STATE_RAW(&NOBUG_FLAG(flag), state, entered)
1211 #define NOBUG_RESOURCE_STATE_RAW(flag, nstate, entered) \
1212 NOBUG_IF_ALPHA( do { \
1213 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1214 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1215 "RESOURCE_STATE", "%s: %s@%p: %s: %s->%s", \
1216 entered?((struct nobug_resource_user*)entered)->current->resource->type:"", \
1217 entered?((struct nobug_resource_user*)entered)->current->resource->hdr.name:"", \
1218 entered?((struct nobug_resource_user*)entered)->current->resource->object_id:"", \
1219 entered?entered->name:"", \
1220 nobug_resource_states[entered?((struct nobug_resource_user*)entered)->state \
1221 :NOBUG_RESOURCE_INVALID], \
1222 nobug_resource_states[nstate]); \
1224 NOBUG_RESOURCE_ASSERT(nobug_resource_state ((struct nobug_resource_user*)entered, nstate), \
1225 "RESOURCE_ASSERT_STATE", NOBUG_LOCATION_INFO, \
1226 "%s: %s@%p: %s: %s->%s: %s", \
1227 entered?((struct nobug_resource_user*)entered)->current->resource->type:"", \
1228 entered?((struct nobug_resource_user*)entered)->current->resource->hdr.name:"", \
1229 entered?((struct nobug_resource_user*)entered)->current->resource->object_id:"", \
1230 entered?entered->name:"", \
1231 nobug_resource_states[entered?((struct nobug_resource_user*)entered)->state \
1232 :NOBUG_RESOURCE_INVALID], \
1233 nobug_resource_states[nstate], \
1234 nobug_resource_error); \
1235 } while (0))
1239 //index.resource_leave xref:RESOURCE_LEAVE[RESOURCE_LEAVE]:: relinquish a claimed resource
1240 //resourcemacros [[RESOURCE_LEAVE]]
1241 //resourcemacros
1242 //resourcemacros .RESOURCE_LEAVE
1243 //resourcemacros RESOURCE_LEAVE(flag, handle)
1244 //resourcemacros
1245 //resourcemacros Disconnect from a resource identified with its handle.
1246 //resourcemacros
1247 //resourcemacros `flag`::
1248 //resourcemacros nobug flag which turns logging on for this macro
1249 //resourcemacros `handle`::
1250 //resourcemacros the handle you got while entering the resource
1251 //resourcemacros
1253 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1254 NOBUG_RESOURCE_LEAVE_RAW(&NOBUG_FLAG(flag), handle)
1256 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1257 NOBUG_IF_ALPHA( do { \
1258 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1259 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1260 "RESOURCE_LEAVE", "%s: %s@%p: %s: %s", \
1261 handle?((struct nobug_resource_user*)handle)->current->resource->type:"", \
1262 handle?((struct nobug_resource_user*)handle)->current->resource->hdr.name:"", \
1263 handle?((struct nobug_resource_user*)handle)->current->resource->object_id:"", \
1264 handle?handle->name:"", \
1265 nobug_resource_states[handle?((struct nobug_resource_user*)handle)->state \
1266 :NOBUG_RESOURCE_INVALID]); \
1268 NOBUG_RESOURCE_ASSERT(nobug_resource_leave ((struct nobug_resource_user*)handle), \
1269 "RESOURCE_ASSERT_LEAVE", NOBUG_LOCATION_INFO, "%s: %s@%p: %s: %s: %s", \
1270 handle?((struct nobug_resource_user*)handle)->current->resource->type:"", \
1271 handle?((struct nobug_resource_user*)handle)->current->resource->hdr.name:"", \
1272 handle?((struct nobug_resource_user*)handle)->current->resource->object_id:"", \
1273 handle?handle->name:"", \
1274 nobug_resource_states[handle?((struct nobug_resource_user*)handle)->state \
1275 :NOBUG_RESOURCE_INVALID], \
1276 nobug_resource_error); \
1277 handle = NULL; \
1278 } while (0))
1282 /* assertion which dumps all resources */
1283 #define NOBUG_RESOURCE_ASSERT(resource, what, location, ...) \
1284 NOBUG_WHEN (!(resource), \
1285 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
1286 location, what, \
1287 ## __VA_ARGS__); \
1288 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1289 {&nobug_flag_NOBUG_ON, \
1290 LOG_EMERG, \
1291 NOBUG_LOCATION_ARGS}); \
1292 NOBUG_BACKTRACE; \
1293 NOBUG_ABORT \
1298 //index.resource_dump xref:NOBUG_RESOURCE_DUMP[NOBUG_RESOURCE_DUMP]:: dump the state of a single resource
1299 //resourcemacros [[NOBUG_RESOURCE_DUMP]]
1300 //resourcemacros
1301 //resourcemacros .NOBUG_RESOURCE_DUMP
1302 //resourcemacros NOBUG_RESOURCE_DUMP(flag, handle)
1303 //resourcemacros
1304 //resourcemacros Dump the state of a single resource.
1305 //resourcemacros
1306 //resourcemacros `flag`::
1307 //resourcemacros Nobug flag for the log channel
1308 //resourcemacros `handle`::
1309 //resourcemacros handle of the resource to be dumped
1310 //resourcemacros
1312 #define NOBUG_RESOURCE_DUMP(flag, handle) \
1313 do { NOBUG_RESOURCE_LOCK; \
1314 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1315 {&NOBUG_FLAG(flag), \
1316 NOBUG_RESOURCE_LOG_LEVEL, \
1317 NOBUG_LOCATION_ARGS}); \
1318 NOBUG_RESOURCE_UNLOCK; } while (0)
1320 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle) \
1321 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1322 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1323 {&NOBUG_FLAG(flag), \
1324 NOBUG_RESOURCE_LOG_LEVEL, \
1325 NOBUG_LOCATION_ARGS}); \
1326 NOBUG_RESOURCE_UNLOCK)
1330 //index.resource_dumpall xref:NOBUG_RESOURCE_DUMPALL[NOBUG_RESOURCE_DUMPALL]:: dump the state of all resources
1331 //resourcemacros [[NOBUG_RESOURCE_DUMPALL]]
1332 //resourcemacros
1333 //resourcemacros .NOBUG_RESOURCE_DUMPALL
1334 //resourcemacros NOBUG_RESOURCE_DUMPALL(flag)
1335 //resourcemacros
1336 //resourcemacros Dump the state of all resources.
1337 //resourcemacros
1338 //resourcemacros `flag`::
1339 //resourcemacros Nobug flag for the log channel
1340 //resourcemacros
1342 #define NOBUG_RESOURCE_DUMPALL(flag) \
1343 do { NOBUG_RESOURCE_LOCK; \
1344 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1345 {&NOBUG_FLAG(flag), \
1346 NOBUG_RESOURCE_LOG_LEVEL, \
1347 NOBUG_LOCATION_ARGS}); \
1348 NOBUG_RESOURCE_UNLOCK; } while (0)
1351 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag) \
1352 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1353 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1354 {&NOBUG_FLAG(flag), \
1355 NOBUG_RESOURCE_LOG_LEVEL, \
1356 NOBUG_LOCATION_ARGS}); \
1357 NOBUG_RESOURCE_UNLOCK)
1361 //index.resource_list xref:NOBUG_RESOURCE_LIST[NOBUG_RESOURCE_LIST]:: enumerate all registered resources
1362 //resourcemacros [[NOBUG_RESOURCE_LIST]]
1363 //resourcemacros
1364 //resourcemacros .NOBUG_RESOURCE_LIST
1365 //resourcemacros NOBUG_RESOURCE_LIST(flag)
1366 //resourcemacros
1367 //resourcemacros List all registered resources.
1368 //resourcemacros
1369 //resourcemacros `flag`::
1370 //resourcemacros Nobug flag for the log channel
1371 //resourcemacros
1373 #define NOBUG_RESOURCE_LIST(flag) \
1374 do { NOBUG_RESOURCE_LOCK; \
1375 nobug_resource_list (&(struct nobug_resource_dump_context) \
1376 {&NOBUG_FLAG(flag), \
1377 NOBUG_RESOURCE_LOG_LEVEL, \
1378 NOBUG_LOCATION_ARGS}); \
1379 NOBUG_RESOURCE_UNLOCK; } while (0)
1381 #define NOBUG_RESOURCE_LIST_IF(when, flag) \
1382 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1383 nobug_resource_list (&(struct nobug_resource_dump_context) \
1384 {&NOBUG_FLAG(flag), \
1385 NOBUG_RESOURCE_LOG_LEVEL, \
1386 NOBUG_LOCATION_ARGS}); \
1387 NOBUG_RESOURCE_UNLOCK)
1391 threading support
1393 #if NOBUG_USE_PTHREAD
1394 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1395 #define NOBUG_THREAD_ID_FMT(pre,post) pre "%s" post
1396 #define NOBUG_THREAD_ID_COMMA , NOBUG_THREAD_ID_GET
1397 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1399 #else
1400 #define NOBUG_THREAD_ID_SET(name)
1401 #define NOBUG_THREAD_ID_FMT(pre,post) ""
1402 #define NOBUG_THREAD_ID_COMMA
1403 #define NOBUG_THREAD_ID_GET ""
1404 #endif
1406 #define NOBUG_THREAD_DATA (*nobug_thread_data())
1409 Source location
1411 #define NOBUG_LOCATION_ARGS NOBUG_BASENAME(__FILE__), __LINE__, __func__
1412 #define NOBUG_LOCATION_INFO (NOBUG_LOCATION_ARGS)
1414 #define NOBUG_LOCATION_FILE(file, _1, _2) file
1415 #define NOBUG_LOCATION_LINE(_1, line, _2) line
1416 #define NOBUG_LOCATION_FUNC(_1, _2, func) func
1420 Debuggers
1423 #define NOBUG_DBG_NONE 0
1424 #define NOBUG_DBG_GDB 1
1425 #define NOBUG_DBG_VALGRIND 2
1427 #define NOBUG_ACTIVE_DBG \
1428 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1429 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1432 //toolmacros PARA BACKTRACE; BACKTRACE; generate a backtrace
1433 //toolmacros BACKTRACE
1434 //toolmacros
1435 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1436 //toolmacros This is automatically called when NoBug finds an error and is due
1437 //toolmacros to abort. But one might call it manually too.
1438 //toolmacros
1440 #define NOBUG_BACKTRACE \
1441 NOBUG_IF_ALPHA( \
1442 switch (NOBUG_ACTIVE_DBG) { \
1443 case NOBUG_DBG_VALGRIND: \
1444 NOBUG_BACKTRACE_VALGRIND; \
1445 break; \
1446 default: \
1447 NOBUG_BACKTRACE_GLIBC; \
1448 }) \
1449 NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC)
1451 #define NOBUG_BACKTRACE_DBG \
1452 NOBUG_IF_NOT_RELEASE( \
1453 switch (NOBUG_ACTIVE_DBG) { \
1454 case NOBUG_DBG_VALGRIND: \
1455 NOBUG_BACKTRACE_VALGRIND; \
1456 break; \
1459 #define NOBUG_BACKTRACE_GDB fprintf(stderr, "UNIMPLEMENTED : GDB Backtraces\n")
1461 #define NOBUG_BACKTRACE_VALGRIND \
1462 NOBUG_IF(NOBUG_USE_VALGRIND, \
1463 VALGRIND_PRINTF_BACKTRACE("BACKTRACE: %s@%d %s", \
1464 NOBUG_LOCATION_ARGS))
1467 #ifndef NOBUG_BACKTRACE_DEPTH
1468 #define NOBUG_BACKTRACE_DEPTH 256
1469 #endif
1471 #define NOBUG_BACKTRACE_GLIBC \
1472 NOBUG_IF_NOT_RELEASE( \
1473 NOBUG_IF(NOBUG_USE_EXECINFO, do { \
1474 NOBUG_LOG_(&nobug_flag_NOBUG_ON, LOG_NOTICE, NOBUG_LOCATION_INFO, "BACKTRACE"); \
1475 nobug_backtrace_glibc (); \
1476 } while (0)))
1479 #ifndef NOBUG_TAB
1480 #define NOBUG_TAB " "
1481 #endif
1484 init and other function wrapers
1486 #define NOBUG_INIT nobug_init()
1487 #define NOBUG_BASENAME(name) (strrchr((name), '/')?strrchr((name), '/') + 1 : (name))
1488 #define NOBUG_ABORT abort()
1492 short macros without NOBUG_
1494 #ifndef NOBUG_DISABLE_SHORTNAMES
1495 #ifndef REQUIRE
1496 #define REQUIRE NOBUG_REQUIRE
1497 #endif
1498 #ifndef REQUIRE_DBG
1499 #define REQUIRE_DBG NOBUG_REQUIRE_DBG
1500 #endif
1501 #ifndef REQUIRE_IF
1502 #define REQUIRE_IF NOBUG_REQUIRE_IF
1503 #endif
1504 #ifndef REQUIRE_IF_DBG
1505 #define REQUIRE_IF_DBG NOBUG_REQUIRE_IF_DBG
1506 #endif
1507 #ifndef ENSURE
1508 #define ENSURE NOBUG_ENSURE
1509 #endif
1510 #ifndef ENSURE_DBG
1511 #define ENSURE_DBG NOBUG_ENSURE_DBG
1512 #endif
1513 #ifndef ENSURE_IF
1514 #define ENSURE_IF NOBUG_ENSURE_IF
1515 #endif
1516 #ifndef ENSURE_IF_DBG
1517 #define ENSURE_IF_DBG NOBUG_ENSURE_IF_DBG
1518 #endif
1519 #ifndef ASSERT
1520 #define ASSERT NOBUG_ASSERT
1521 #endif
1522 #ifndef ASSERT_DBG
1523 #define ASSERT_DBG NOBUG_ASSERT_DBG
1524 #endif
1525 #ifndef ASSERT_IF
1526 #define ASSERT_IF NOBUG_ASSERT_IF
1527 #endif
1528 #ifndef ASSERT_IF_DBG
1529 #define ASSERT_IF_DBG NOBUG_ASSERT_IF_DBG
1530 #endif
1531 #ifndef CHECK
1532 #define CHECK NOBUG_CHECK
1533 #endif
1534 #ifndef CHECK
1535 #define CHECK NOBUG_CHECK
1536 #endif
1537 #ifndef INVARIANT
1538 #define INVARIANT NOBUG_INVARIANT
1539 #endif
1540 #ifndef INVARIANT_DBG
1541 #define INVARIANT_DBG NOBUG_INVARIANT_DBG
1542 #endif
1543 #ifndef INVARIANT_IF
1544 #define INVARIANT_IF NOBUG_INVARIANT_IF
1545 #endif
1546 #ifndef INVARIANT_IF_DBG
1547 #define INVARIANT_IF_DBG NOBUG_INVARIANT_IF_DBG
1548 #endif
1549 #ifndef INVARIANT_ASSERT
1550 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
1551 #endif
1552 #ifndef DUMP
1553 #define DUMP NOBUG_DUMP
1554 #endif
1555 #ifndef DUMP_DBG
1556 #define DUMP_DBG NOBUG_DUMP_DBG
1557 #endif
1558 #ifndef DUMP_IF
1559 #define DUMP_IF NOBUG_DUMP_IF
1560 #endif
1561 #ifndef DUMP_IF_DBG
1562 #define DUMP_IF_DBG NOBUG_DUMP_IF_DBG
1563 #endif
1564 #ifndef DUMP_LOG
1565 #define DUMP_LOG NOBUG_DUMP_LOG
1566 #endif
1567 #ifndef DUMP_LOG_DBG
1568 #define DUMP_LOG_DBG NOBUG_DUMP_LOG_DBG
1569 #endif
1570 #ifndef DUMP_LOG_IF
1571 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1572 #endif
1573 #ifndef DUMP_LOG_IF_DBG
1574 #define DUMP_LOG_IF_DBG NOBUG_DUMP_LOG_IF_DBG
1575 #endif
1576 #ifndef LOG
1577 #define LOG NOBUG_LOG
1578 #endif
1579 #ifndef LOG_DBG
1580 #define LOG_DBG NOBUG_LOG_DBG
1581 #endif
1582 #ifndef LOG_IF
1583 #define LOG_IF NOBUG_LOG_IF
1584 #endif
1585 #ifndef LOG_IF_DBG
1586 #define LOG_IF_DBG NOBUG_LOG_IF_DBG
1587 #endif
1588 #ifndef ECHO
1589 #define ECHO NOBUG_ECHO
1590 #endif
1591 #ifndef ALERT
1592 #define ALERT NOBUG_ALERT
1593 #endif
1594 #ifndef ALERT_DBG
1595 #define ALERT_DBG NOBUG_ALERT_DBG
1596 #endif
1597 #ifndef ALERT_IF
1598 #define ALERT_IF NOBUG_ALERT_IF
1599 #endif
1600 #ifndef ALERT_IF_DBG
1601 #define ALERT_IF_DBG NOBUG_ALERT_IF_DBG
1602 #endif
1603 #ifndef CRITICAL
1604 #define CRITICAL NOBUG_CRITICAL
1605 #endif
1606 #ifndef CRITICAL_DBG
1607 #define CRITICAL_DBG NOBUG_CRITICAL_DBG
1608 #endif
1609 #ifndef CRITICAL_IF
1610 #define CRITICAL_IF NOBUG_CRITICAL_IF
1611 #endif
1612 #ifndef CRITICAL_IF_DBG
1613 #define CRITICAL_IF_DBG NOBUG_CRITICAL_IF_DBG
1614 #endif
1615 #ifndef ERROR
1616 #define ERROR NOBUG_ERROR
1617 #endif
1618 #ifndef ERROR_DBG
1619 #define ERROR_DBG NOBUG_ERROR_DBG
1620 #endif
1621 #ifndef ERROR_IF
1622 #define ERROR_IF NOBUG_ERROR_IF
1623 #endif
1624 #ifndef ERROR_IF_DBG
1625 #define ERROR_IF_DBG NOBUG_ERROR_IF_DBG
1626 #endif
1627 #ifndef WARN
1628 #define WARN NOBUG_WARN
1629 #endif
1630 #ifndef WARN_DBG
1631 #define WARN_DBG NOBUG_WARN_DBG
1632 #endif
1633 #ifndef WARN_IF
1634 #define WARN_IF NOBUG_WARN_IF
1635 #endif
1636 #ifndef WARN_IF_DBG
1637 #define WARN_IF_DBG NOBUG_WARN_IF_DBG
1638 #endif
1639 #ifndef INFO
1640 #define INFO NOBUG_INFO
1641 #endif
1642 #ifndef INFO_DBG
1643 #define INFO_DBG NOBUG_INFO_DBG
1644 #endif
1645 #ifndef INFO_IF
1646 #define INFO_IF NOBUG_INFO_IF
1647 #endif
1648 #ifndef INFO_IF_DBG
1649 #define INFO_IF_DBG NOBUG_INFO_IF_DBG
1650 #endif
1651 #ifndef NOTICE
1652 #define NOTICE NOBUG_NOTICE
1653 #endif
1654 #ifndef NOTICE_DBG
1655 #define NOTICE_DBG NOBUG_NOTICE_DBG
1656 #endif
1657 #ifndef NOTICE_IF
1658 #define NOTICE_IF NOBUG_NOTICE_IF
1659 #endif
1660 #ifndef NOTICE_IF_DBG
1661 #define NOTICE_IF_DBG NOBUG_NOTICE_IF_DBG
1662 #endif
1663 #ifndef TRACE
1664 #define TRACE NOBUG_TRACE
1665 #endif
1666 #ifndef TRACE_DBG
1667 #define TRACE_DBG NOBUG_TRACE_DBG
1668 #endif
1669 #ifndef TRACE_IF
1670 #define TRACE_IF NOBUG_TRACE_IF
1671 #endif
1672 #ifndef TRACE_IF_DBG
1673 #define TRACE_IF_DBG NOBUG_TRACE_IF_DBG
1674 #endif
1675 #ifndef BACKTRACE
1676 #define BACKTRACE NOBUG_BACKTRACE
1677 #endif
1678 #ifndef BACKTRACE_DBG
1679 #define BACKTRACE_DBG NOBUG_BACKTRACE_DBG
1680 #endif
1681 #ifndef DEPRECATED
1682 #define DEPRECATED NOBUG_DEPRECATED
1683 #endif
1684 #ifndef UNIMPLEMENTED
1685 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1686 #endif
1687 #ifndef FIXME
1688 #define FIXME NOBUG_FIXME
1689 #endif
1690 #ifndef TODO
1691 #define TODO NOBUG_TODO
1692 #endif
1693 #ifndef PLANNED
1694 #define PLANNED NOBUG_PLANNED
1695 #endif
1696 #ifndef NOTREACHED
1697 #define NOTREACHED NOBUG_NOTREACHED
1698 #endif
1699 #ifndef INJECT_GOODBAD
1700 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
1701 #endif
1702 #ifndef INJECT_FAULT
1703 #define INJECT_FAULT NOBUG_INJECT_FAULT
1704 #endif
1705 #ifndef CLEANUP
1706 #define CLEANUP NOBUG_CLEANUP
1707 #endif
1708 #ifndef CHECKED
1709 #define CHECKED NOBUG_CHECKED
1710 #endif
1711 #ifndef UNCHECKED
1712 #define UNCHECKED NOBUG_UNCHECKED
1713 #endif
1714 #ifndef RESOURCE_ANNOUNCE
1715 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1716 #endif
1717 #ifndef RESOURCE_FORGET
1718 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1719 #endif
1720 #ifndef RESOURCE_ENTER
1721 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1722 #endif
1723 #ifndef RESOURCE_STATE
1724 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1725 #endif
1726 #ifndef RESOURCE_LEAVE
1727 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1728 #endif
1729 #ifndef RESOURCE_LEAVE_LOOKUP
1730 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1731 #endif
1732 #ifndef RESOURCE_HANDLE
1733 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1734 #endif
1735 #ifndef RESOURCE_HANDLE_INIT
1736 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
1737 #endif
1738 #ifndef RESOURCE_DUMP
1739 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
1740 #endif
1741 #ifndef RESOURCE_DUMP_IF
1742 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
1743 #endif
1744 #ifndef RESOURCE_DUMPALL
1745 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
1746 #endif
1747 #ifndef RESOURCE_DUMPALL_IF
1748 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
1749 #endif
1750 #ifndef RESOURCE_LIST
1751 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
1752 #endif
1753 #ifndef RESOURCE_LIST_IF
1754 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
1755 #endif
1756 #endif /* NOBUG_DISABLE_SHORTNAMES */
1760 Tool macros
1762 #ifdef __GNUC__
1763 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
1764 #define NOBUG_ATTR_PRINTF(fmt, ell) __attribute__ ((format (printf, fmt, ell)))
1765 #else
1766 #define NOBUG_CLEANUP(fn)
1767 #define NOBUG_ATTR_PRINTF(fmt, ell)
1768 #endif
1771 //toolmacros PARA NOBUG_ALPHA_COMMA; NOBUG_ALPHA_COMMA; append something after a comma in *ALPHA* builds
1772 //toolmacros NOBUG_ALPHA_COMMA(something)
1773 //toolmacros NOBUG_ALPHA_COMMA_NULL
1774 //toolmacros
1775 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
1776 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
1777 //toolmacros use this macros to append a comman and something else only in *ALPHA* builds as in:
1778 //toolmacros struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
1779 //toolmacros
1781 #define NOBUG_COMMA ,
1782 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
1783 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
1785 #define NOBUG_ONCE(code) \
1786 do { \
1787 static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 0; \
1788 if (NOBUG_EXPECT_FALSE(!NOBUG_CAT(nobug_once_,__LINE__))) \
1790 NOBUG_CAT(nobug_once_,__LINE__) = 1; \
1791 code; \
1793 } while (0)
1795 #if __GNUC__
1796 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
1797 #else
1798 #define NOBUG_EXPECT_FALSE(x) x
1799 #endif
1801 #define NOBUG_WHEN(when, ...) \
1802 do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
1805 //toolmacros PARA NOBUG_IF_*; NOBUG_IF; include code conditionally on build level
1806 //toolmacros NOBUG_IF_ALPHA(...)
1807 //toolmacros NOBUG_IF_NOT_ALPHA(...)
1808 //toolmacros NOBUG_IF_BETA(...)
1809 //toolmacros NOBUG_IF_NOT_BETA(...)
1810 //toolmacros NOBUG_IF_RELEASE(...)
1811 //toolmacros NOBUG_IF_NOT_RELEASE(...)
1812 //toolmacros
1813 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
1814 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
1815 //toolmacros internally, but can also be used for custom things.
1816 //toolmacros
1818 #define NOBUG_IF_ALPHA(...) \
1819 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1821 #define NOBUG_IF_NOT_ALPHA(...) \
1822 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1824 #define NOBUG_IF_BETA(...) \
1825 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__) \
1827 #define NOBUG_IF_NOT_BETA(...) \
1828 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__) \
1830 #define NOBUG_IF_RELEASE(...) \
1831 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1833 #define NOBUG_IF_NOT_RELEASE(...) \
1834 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1837 preprocessor hacks/metaprogramming
1840 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
1841 #define NOBUG_IF_1(...) __VA_ARGS__
1842 #define NOBUG_IF_0(...)
1844 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
1846 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
1847 #define NOBUG_NOT_1 0
1848 #define NOBUG_NOT_0 1
1850 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
1851 #define NOBUG_AND_00 0
1852 #define NOBUG_AND_01 0
1853 #define NOBUG_AND_10 0
1854 #define NOBUG_AND_11 1
1856 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
1857 #define NOBUG_OR_00 0
1858 #define NOBUG_OR_01 1
1859 #define NOBUG_OR_10 1
1860 #define NOBUG_OR_11 1
1862 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
1863 #define NOBUG_XOR_00 0
1864 #define NOBUG_XOR_01 1
1865 #define NOBUG_XOR_10 1
1866 #define NOBUG_XOR_11 0
1868 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
1869 #define NOBUG_CAT_(a,b) a##b
1871 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
1872 #define NOBUG_CAT3_(a,b,c) a##b##c
1874 #define NOBUG_HEAD(head, ...) head
1875 #define NOBUG_TAIL(_, ...) , ## __VA_ARGS__
1877 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
1878 #define NOBUG_STRINGIZE_(s) #s
1882 LIBNOBUG DECLARATIONS
1884 #ifdef __cplusplus
1885 extern "C" {
1886 #elif 0
1887 } /* fix emacs indent */
1888 #endif
1891 envvar control
1893 enum nobug_log_targets
1895 NOBUG_TARGET_RINGBUFFER,
1896 NOBUG_TARGET_CONSOLE,
1897 NOBUG_TARGET_FILE,
1898 NOBUG_TARGET_SYSLOG,
1899 NOBUG_TARGET_APPLICATION
1902 struct nobug_flag
1904 const char* name;
1905 struct nobug_flag* parent;
1906 volatile int initialized;
1907 int limits[5];
1908 struct nobug_ringbuffer* ringbuffer_target;
1909 FILE* console_target;
1910 FILE* file_target;
1914 nobug_env_parse_flag (const char* env, struct nobug_flag* flag, int default_target, int default_limit);
1917 nobug_env_init_flag (struct nobug_flag* flag, int default_target, int default_limit);
1921 ringbuffer
1923 struct nobug_ringbuffer
1925 char* pos;
1926 char* start;
1927 size_t size;
1928 size_t maxmsg;
1929 char name[256];
1932 enum nobug_ringbuffer_flags
1934 NOBUG_RINGBUFFER_DEFAULT, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
1935 NOBUG_RINGBUFFER_APPEND = 1, /* use existing backing file, append if possible */
1936 NOBUG_RINGBUFFER_TEMP = 2, /* unlink file instantly */
1937 NOBUG_RINGBUFFER_KEEP = 4 /* dont unlink the file at destroy */
1941 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
1942 with sane (but undefined) semantics.
1944 struct nobug_ringbuffer*
1945 nobug_ringbuffer_init (struct nobug_ringbuffer* self, size_t size,
1946 const char * name, int flags);
1948 struct nobug_ringbuffer*
1949 nobug_ringbuffer_new (size_t size, const char * name, int flags);
1951 struct nobug_ringbuffer*
1952 nobug_ringbuffer_destroy (struct nobug_ringbuffer* self);
1954 void
1955 nobug_ringbuffer_delete (struct nobug_ringbuffer* self);
1958 nobug_ringbuffer_vprintf (struct nobug_ringbuffer* self, const char* fmt, va_list ap);
1961 nobug_ringbuffer_printf (struct nobug_ringbuffer* self, const char* fmt, ...);
1963 char*
1964 nobug_ringbuffer_prev (struct nobug_ringbuffer* self, char* pos);
1966 char*
1967 nobug_ringbuffer_next (struct nobug_ringbuffer* self, char* pos);
1970 nobug_ringbuffer_save (struct nobug_ringbuffer* self, FILE* out);
1973 nobug_ringbuffer_load (struct nobug_ringbuffer* self, FILE* in);
1975 char*
1976 nobug_ringbuffer_pos (struct nobug_ringbuffer* self);
1978 void
1979 nobug_ringbuffer_pop (struct nobug_ringbuffer* self);
1983 multithreading extras
1986 #ifndef LLIST_DEFINED
1987 #define LLIST_DEFINED
1988 struct llist_struct
1990 struct llist_struct *next;
1991 struct llist_struct *prev;
1993 #endif
1995 #if NOBUG_USE_PTHREAD
1997 struct nobug_tls_data
1999 const char* thread_id;
2000 void* data;
2001 struct llist_struct res_stack; /* resources of this thread */
2004 extern pthread_key_t nobug_tls_key;
2006 struct nobug_tls_data*
2007 nobug_thread_set (const char* name);
2009 struct nobug_tls_data*
2010 nobug_thread_get (void);
2012 const char*
2013 nobug_thread_id_set (const char* name);
2015 const char*
2016 nobug_thread_id_get (void);
2018 extern pthread_mutex_t nobug_logging_mutex;
2019 extern pthread_mutex_t nobug_resource_mutex;
2020 #endif
2022 void**
2023 nobug_thread_data (void);
2026 resource registry
2028 #if NOBUG_USE_PTHREAD
2029 #define NOBUG_RESOURCE_LOCK pthread_mutex_lock (&nobug_resource_mutex)
2030 #define NOBUG_RESOURCE_UNLOCK pthread_mutex_unlock (&nobug_resource_mutex)
2032 Note: errors are all fatal, we dont unlock the mutex when returning an error,
2033 this should be handled better in future but does not hurt
2035 #else
2036 #define NOBUG_RESOURCE_LOCK
2037 #define NOBUG_RESOURCE_UNLOCK
2038 #endif
2040 enum nobug_resource_state
2042 NOBUG_RESOURCE_INVALID,
2043 NOBUG_RESOURCE_WAITING,
2044 NOBUG_RESOURCE_EXCLUSIVE,
2045 NOBUG_RESOURCE_RECURSIVE,
2046 NOBUG_RESOURCE_SHARED
2050 struct nobug_resource_header
2052 struct llist_struct node; /* link node for resource registry or users */
2053 const char* name; /* name */
2054 const char* extra; /* extra information, file/line usually */
2057 struct nobug_resource_node;
2058 struct nobug_resource_user;
2060 struct nobug_resource_record
2062 struct nobug_resource_header hdr;
2064 struct llist_struct users; /* list of users of this resource */
2065 const void* object_id; /* unique identifer, usually a this pointer or similar */
2066 const char* type; /* type */
2068 #if NOBUG_USE_PTHREAD
2069 struct llist_struct nodes;
2070 #endif
2074 struct nobug_resource_node
2076 struct llist_struct node; /* all nodes for one resource */
2078 struct nobug_resource_record* resource; /* backpointer */
2079 struct nobug_resource_node* parent; /* upwards the tree */
2081 struct llist_struct childs; /* down the tree, all nodes pointing to here (TODO make this a slist) */
2082 struct llist_struct cldnode; /* node to accumulate all childrens of a parent (TODO slist) */
2086 struct nobug_resource_user
2088 struct nobug_resource_header hdr;
2090 struct nobug_resource_node* current; /* this resource */
2091 enum nobug_resource_state state; /* state */
2093 #if NOBUG_USE_PTHREAD
2094 struct nobug_tls_data* thread; /* pointer to this theads id */
2095 struct llist_struct res_stack; /* resources of this thread */
2096 #endif
2100 extern const char* nobug_resource_error;
2102 extern const char* nobug_resource_states[];
2105 void
2106 nobug_resource_init (void);
2108 void
2109 nobug_resource_destroy (void);
2112 struct nobug_resource_record*
2113 nobug_resource_announce (const char* type, const char* name, const void* object_id, const char* extra);
2116 nobug_resource_forget (struct nobug_resource_record* node);
2119 struct nobug_resource_user*
2120 nobug_resource_enter (struct nobug_resource_record* resource,
2121 const char* name,
2122 enum nobug_resource_state state,
2123 const char* extra);
2126 nobug_resource_leave (struct nobug_resource_user* handle);
2129 unsigned
2130 nobug_resource_record_available (void);
2133 unsigned
2134 nobug_resource_user_available (void);
2137 #if NOBUG_USE_PTHREAD
2138 unsigned
2139 nobug_resource_node_available (void);
2140 #endif
2143 struct nobug_resource_dump_context
2145 struct nobug_flag* flag;
2146 int level;
2147 const char* file;
2148 int line;
2149 const char* func;
2153 void
2154 nobug_resource_dump (struct nobug_resource_record* resource, struct nobug_resource_dump_context* context);
2156 void
2157 nobug_resource_dump_all (struct nobug_resource_dump_context* context);
2160 nobug_resource_state (struct nobug_resource_user* resource,
2161 enum nobug_resource_state state);
2164 void
2165 nobug_resource_list (struct nobug_resource_dump_context* context);
2169 global config, data and defaults
2171 void nobug_init (void);
2174 the destroy function is optional, since nobug should stay alive for the whole application lifetime
2175 (and destroying is global!) it is only provided for the nobug testsuite itself
2177 void nobug_destroy (void);
2179 void
2180 nobug_backtrace_glibc (void);
2182 void
2183 nobug_log (struct nobug_flag* flag, int lvl, const char* fmt, ...) NOBUG_ATTR_PRINTF(3, 4);
2185 typedef void (*nobug_application_cb)(struct nobug_flag* flag, int priority, const char *log, void* data);
2187 extern struct nobug_ringbuffer nobug_default_ringbuffer;
2188 extern FILE* nobug_default_file;
2189 extern struct nobug_flag nobug_flag_NOBUG_ON;
2190 extern struct nobug_flag nobug_flag_NOBUG_ANN;
2191 extern struct nobug_flag nobug_flag_nobug;
2192 extern unsigned long long nobug_counter;
2193 extern nobug_application_cb nobug_callback;
2194 extern void* nobug_callback_data;
2196 #ifdef __cplusplus
2197 } /* extern "C" */
2198 #endif
2200 #ifndef NOBUG_LIBNOBUG_C
2203 tag this translation unit as unchecked in ALPHA and BETA builds
2205 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED);
2207 #endif /* NOBUG_LIBNOBUG_C */
2208 #endif