On Dec 17, 2015, at 11:39 AM, Thomas Stüfe <thomas.stu...@gmail.com> wrote: > > When we print it, we precede the multiline message with the decorators in the > first line and indent the rest of the lines to the same position: > > [time][pid][tid] hallo1 > hallo2 > hallo3 > > This approach has served us quite well. We decided against locking done by > the caller because users to minimize the danger of deadlocks.
I agree that buffering is a better approach than locking. In the old logging system, large amounts of logging are produced by the compiler threads, and is buffered separately per thread. Smaller amounts are dumped into a common "tty" stream, which is available only to one thread at a time. The effect of the ttyLocker is to ensure unbroken multi-line output. It doesn't intrinsically need to block other writers. Buffering is a great way to keep integrity without blocking. This could be introduced into the new UL framework like this: LogHandle(logging) log0; if (log0.is_debug()) { LogBuffer log(log0); int result = compute_debug_result(); log.debug("result = %d", result).trace(" tracing info"); obj->print_on(log.debug_stream()); } Or just: { LogBuffer(logging) log; if (log.is_debug()) { int result = compute_debug_result(); log.debug("result = %d", result).trace(" tracing info"); obj->print_on(log.debug_stream()); } } The "log" is a separate object from "log0" which has the same API, and buffers all output before flushing to the underlying "log0". (The RAII destructor flushes. Maybe it also has explicit flush.) Note that "log" has true object state, whereas "log0" is just a bundle of static methods. Perhaps LogBuffer could be economically used inside the Log methods themselves; currently they do buffering equivalent to what LogBuffer does, but using random logic (see uses of constant LogBufferSize). Basically, wherever a "printf" format is used with Log API points, there is already a hidden buffer (it resizes at most once, since there is just one printf call). Optional parameters to LogBuffer would control behavior related to (possibly) splitting very large outputs (like PrintAssembly), or buffering to files (using the rotating archive mechanism). This would provide a road to replacing the existing LogCompilation implementation, which has thread-local logs buffered to temp files. I.e., a long-lived, thread-local, file-backed LogBuffer would allow a compiler thread to produce gigabytes of output, all properly sequenced, with no interruptions and no blocking of other logs. Having a separate layer "LogBuffer" for keeping lines together will not penalize users of the underlying line-at-time facility. — John