2014-02-13 44 views
1

我試圖在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)

什麼是提供共享訪問在多個線程文件的正確方法是:我從DMD以下錯誤招呼?一些初步的想法:

  1. 在Alexandrescu的的的d編程語言,他提到,writelnstout是原子與問候到輸出流,但我似乎無法找到在在線文檔任何地方。

  2. 即使點1爲真,我不希望Logger類爲了輸出屬性而同步化嗎?

回答

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, ")"); 
     } 
    } 
} 
+0

好的,但如何將一個通行證'File *'(即你的例子中的'to')登錄?鑑於我的選擇是使文件線程本地或不可變(這將禁止寫入),是不可能在線程之間共享文件?如果我想使用stdout作爲我的文件怎麼辦?我當然希望能夠從記錄器和其他來源進行打印。 –

+0

這通常是在一些記錄器配置文件中完成的...... – DejanLekic

+0

@DejanLekic除此之外,同樣,如果我想使用stdout作爲我的文件呢?我當然希望能夠從我的程序的其餘部分打印到它,而不僅僅是記錄器,這意味着我希望有多種方式讓多個線程共享一個'File'句柄。 –