D中的并发文件访问

时间:2014-02-13 19:20:05

标签: multithreading logging synchronization d

我正在尝试在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)

跨多个线程提供对文件的共享访问的正确方法是什么?一些初步想法:

  1. 在Alexandrescu的 D编程语言中,他提到writeln stout对输出流来说是原子的,但我似乎无法在在线文档的任何地方找到它。

  2. 即使第1点为真,我仍然不希望Logger类为了输出属性而同步吗?

1 个答案:

答案 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, ")");
        }
    }
}