Skip to content

Sinks and Threading

Hugo edited this page Sep 30, 2026 · 2 revisions

Sinks and Threading

Sinks

A sink receives the formatted output:

using SinkFn = void (*)(const char *data, size_t size);

By default, output goes to stderr. On POSIX, writes are retried on EINTR and on partial writes. set_sink(fn) redirects it, and reset_sink() or set_sink(nullptr) restores stderr.

SinkFn is a plain function pointer, so a lambda passed to it cannot capture anything. Keep sink state in variables with static storage duration:

static FILE *log_file = std::fopen("app.log", "w");

coretrace::set_sink([](const char *data, size_t size) {
  std::fwrite(data, 1, size, log_file);
});
// ...
coretrace::reset_sink();
std::fclose(log_file); // Safe: see "Changing the sink" below.

Each log() line reaches the sink in one call containing the whole line: prefix, message and your trailing \n. The sink is chosen once per line, so a line never ends up split between two sinks.

Thread-safe mode

Thread-safe mode is on by default (set_thread_safe(true)). In this mode:

  • Lines are serialized: the sink is never called for two lines at once, so a sink can append to a std::string or a FILE* without its own lock.
  • The format-error fallback (coretrace: log format error) is serialized like any other line.
  • The output mutex is recursive. A sink may call log(), for example to report its own error, and may call set_sink(); the new sink applies to the next line.

set_thread_safe(false) removes the lock, for single-threaded hot paths. The sink can then be called from several threads at once, and the guarantees below no longer hold.

Changing the sink

With thread safety enabled, set_sink() and reset_sink() wait for a line that is still being written. Once they return, log() no longer calls the previous sink, so its resources (file, socket, buffer) can be released.

Low-level writes

write_raw(), write_str(), write_dec(), write_hex() and write_prefix() write straight to the current sink. Unlike log(), they are not serialized with other lines, even in thread-safe mode. Use them from one thread, or accept that their output may interleave with other lines.

Colors and custom sinks

Whether lines include ANSI colors depends on stderr, not on the sink (see Configuration). A program started from a terminal therefore writes escape sequences into a file sink. Set NO_COLOR to avoid that.

Clone this wiki locally