Я пытаюсь реализовать простой глобальный регистратор в D, который принимает сообщения и записывает их в File
. Я хотел бы сделать его доступным для всех потоков, так как я планирую сначала иметь простой простой журнал, поэтому я сделал класс .Параллельный доступ к файлам в D
import std.stdio;
import std.exception;
import std.conv;
@trusted:
enum LogLevel {
NONE,
ERROR,
WARN,
INFO,
DEBUG,
}
synchronized class Logger {
LogLevel level = LogLevel.WARN;
// The File* must be shared since this is a synchronized class
@property shared(File*) output() { return to; }
@property void output(shared(File*) f)
{
enforce(f != null);
to = f;
}
void log(LogLevel l)(string message, string file = __FILE__, int line = __LINE__)
{
if(l < level)
return;
to.writeln(l.to!string, ": ", message, "(", file, ":", line.to!string, ")");
}
alias log!(LogLevel.ERROR) logError;
alias log!(LogLevel.WARN) logWarn;
alias log!(LogLevel.INFO) logInfo;
alias log!(LogLevel.DEBUG) logDebug;
private:
File* to = &stdout;
}
Однако, по-видимому File.writeln
не очень приятно быть синхронизированы. Я поздоровался со следующей ошибкой из ДМД:
log.d(32): Error: template std.stdio.File.writeln does not match any function template declaration. Candidates are:
/usr/include/dlang/dmd/std/stdio.d(781): std.stdio.File.writeln(S...)(S args)
Что такое правильный способ обеспечить общий доступ к файлу через несколько потоков? Некоторые первоначальные мысли:
В Alexandrescu-х Д Язык программирования, он упоминает, что
writeln
наstout
атомарно по отношению к выходному потоку, но я не могу найти, что где-нибудь в онлайн-документации.Даже если точка 1 истинна, не хочу ли я, чтобы класс
Logger
был синхронизирован ради свойства вывода?
Хорошо, но как бы один проход, который 'File *' (т.е. 'to' в вашем примере) для входа? Учитывая, что мои параметры состоят в том, чтобы сделать поток файлов локальным или неизменным (что запрещало бы писать ему), невозможно ли делиться файлом между потоками? Что делать, если я хочу использовать stdout в качестве файла? Я, конечно, хочу иметь возможность печатать как из логгера, так и из других источников. –
Обычно это делается в файле конфигурации logger ... – DejanLekic
@DejanLekic Это, кроме того, точка. Опять же, что, если я хочу использовать stdout в качестве файла? Я, конечно, хочу иметь возможность печатать на нем от остальной части моей программы, а не только от журнала, что подразумевает, что я хотел бы, чтобы какой-то способ для нескольких потоков делил один дескриптор «Файл». –