我正在尝试在D中实现一个简单的全局记录器,它接收消息并将其写入某些File
。我想让所有线程都可以访问它,因为我计划最初有一个简单的日志,所以我创建了类synchronized
。
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
不同意同步。我遇到了DMD的以下错误:
log.d(32):错误:模板std.stdio.File.writeln与任何函数模板声明都不匹配。候选人是:
/usr/include/dlang/dmd/std/stdio.d(781):std.stdio.File.writeln(S ...)(S args)
跨多个线程提供对文件的共享访问的正确方法是什么?一些初步想法:
在Alexandrescu的 D编程语言中,他提到writeln
stout
对输出流来说是原子的,但我似乎无法在在线文档的任何地方找到它。
即使第1点为真,我仍然不希望Logger
类为了输出属性而同步吗?
答案 0 :(得分:3)
更容易生成另一个线程并在您想要记录时将消息传递给它
void log(LogLevel l)(string message, string file = __FILE__, int line = __LINE__){
locate("logger").send(l,message,file,line);
}
然后线程将是:
void loggerLoop(){
//setup file and such
register(thisTid, "logger");
scope(exit)unregister("logger");
while(true){
receive( (LogLevel l,string message, string file, int line){
if(l < level)
return;
to.writeln(l.to!string, ": ", message, "(", file, ":", line.to!string, ")");
}
}
}