Review: std.logger

Jakob Ovrum via Digitalmars-d digitalmars-d at puremagic.com
Thu Jul 24 16:40:54 PDT 2014


On Thursday, 24 July 2014 at 23:01:56 UTC, Robert burner Schadek 
wrote:
> I do this lazily in a function, because having it global froze 
> std.concurrency and std.process unittest. I couldn't figure out 
> why.

It could still be initialized lazily, using `emplace`, ala

---
private static __gshared Logger _defaultLogger;

Logger defaultLogger() @safe @nogc
{
     static __gshared ubyte[__traits(classInstanceSize, 
StdoutLogger)] buffer;

     if(!_defaultLogger) // TODO: thread safety
         _defaultLogger = () @trusted { return 
emplace!StdoutLogger(buffer); }();

     return _defaultLogger;
}

void defaultLogger(Logger newDefaultLogger) @safe @nogc
{
     _defaultLogger = newDefaultLogger;
}
---

> As said earlier, I think GC and Logger is a none issue. I mean 
> how often has anyone seen a Logger created in a loop over and 
> over again.

Some programs want to forego having a GC-heap entirely. That 
means any GC allocation is a no-go.

Class instances don't have to be GC-allocated, so it's not an 
issue to use classes.

> nothrow will be hard as std.logger uses format, same for nogc

How often have you seen a formatted log message logged in a loop? 
I'd wager that happens quite often. Using `format` is a no-go as 
it completely thrashes the GC, it needs to use `formattedWrite` 
to write directly to the underlying buffer (such as a file).

Even using `formattedWrite` though, `nothrow` is still a problem, 
and since exceptions are still GC-allocated, it doesn't help with 
@nogc either. The latter is something we can fix in the future 
though.

> So you're thinking of a stack array?

No, MultiLogger could manage a non-GC yet still heap-allocated 
array using std.container.array.Array. It uses the C heap 
internally, i.e. malloc, realloc and free. Sortedness can be used 
for searching by name in logarithmic time if desired.

> What about the log functions and there implementation as well 
> as the Logger specific LogLevel and name?

The log functions don't need to be virtual, only the 
`writeLogMsg` function does, so these implementations can either 
be final member functions of the interface, or UFCS functions as 
I suggested in the corresponding line comment.

The Logger-specific LogLevel and the name do not have to be 
implemented by Logger. Leave it to concrete classes to implement 
those. As an internal aid, an abstract GenericLogger base class 
that manages these properties as member variables (as Logger 
currently does) can help.


More information about the Digitalmars-d mailing list