Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial work towards a parallel dub building by supporting deferred logging #2717

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 87 additions & 34 deletions source/dub/internal/logging.d
Original file line number Diff line number Diff line change
Expand Up @@ -333,40 +333,7 @@ void log(T...)(
lazy T args
) nothrow
{
if (level < _minLevel)
return;

auto hasTag = true;
if (level <= LogLevel.diagnostic)
hasTag = false;
if (disableTag)
hasTag = false;

auto boldTag = false;
if (level >= LogLevel.warn)
boldTag = true;

try
{
string result = format(fmt, args);

if (hasTag)
result = tag.rightJustify(tagWidth.get, ' ').color(tagColor, boldTag ? Mode.bold : Mode.init) ~ " " ~ result;

import dub.internal.colorize : cwrite;

File output = (level <= LogLevel.info) ? stdout : stderr;

if (output.isOpen)
{
output.cwrite(result, "\n");
output.flush();
}
}
catch (Exception e)
{
debug assert(false, e.msg);
}
DereferredLogState().log(level, disableTag, tag, tagColor, fmt, args);
}

/**
Expand Down Expand Up @@ -414,3 +381,89 @@ string color(const string str, const Mode m = Mode.init)
else
return str;
}

/**
Deferrement of logging so each logger state may be parallelized without cross messages.
*/
struct DereferredLogState
{
import std.array : Appender;

bool enabled;

@disable this(this);

~this() nothrow
{
foreach (li; output.data)
{
writeOut(li.text, li.isError);
}
}

///
void log(T...)(LogLevel level, bool disableTag, string tag, Color tagColor,
string fmt, lazy T args) nothrow
{
if (level < _minLevel)
return;

auto hasTag = true;
if (level <= LogLevel.diagnostic)
hasTag = false;
if (disableTag)
hasTag = false;

auto boldTag = false;
if (level >= LogLevel.warn)
boldTag = true;

try
{
string result = format(fmt, args);
string prefix = hasTag ? (tag.rightJustify(tagWidth.get, ' ')
.color(tagColor, boldTag ? Mode.bold : Mode.init) ~ " ") : null;

const useErr = level > LogLevel.info;
string text = prefix ~ result ~ "\n";

if (enabled)
output ~= LogItem(text, useErr);
else
writeOut(text, useErr);
}
catch (Exception e)
{
debug assert(false, e.msg);
}
}

private:
Appender!(LogItem[]) output;

void writeOut(string text, bool useStdErr) nothrow
{
import dub.internal.colorize : cwrite;

try
{
File output = useStdErr ? stderr : stdout;

if (output.isOpen)
{
output.cwrite(text);
output.flush();
}
}
catch (Exception e)
{
debug assert(false, e.msg);
}
}

struct LogItem
{
string text;
bool isError;
}
}
Loading