2014-02-13 2 views
1

나는 메시지를 취하여 일부 File에 기록하는 D의 간단한 전역 로거를 구현하려고합니다. 처음에는 단일 로그를 계획하고 있으므로 모든 스레드에서 액세스 가능하게 만들고 싶습니다. 그래서 클래스를 만들었습니다. synchronized.D에서 동시 파일 액세스 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은 동기화하는 데별로 동의하지 않습니다. DMD에서 다음과 같은 오류로 반갑습니다 :

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의의 는 D 프로그래밍 언어에서

  1. , 그는 stoutwriteln이 출력 스트림에 관련하여 원자 것을 언급,하지만 난 그 어디에서나 온라인 문서에서 찾을 수 없습니다.

  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을 파일로 사용하려면 어떻게해야합니까? 필자는 로거뿐만 아니라 나머지 프로그램에서도 인쇄 할 수 있기를 원합니다. 이는 다중 스레드가 단일 '파일'핸들을 공유 할 수있는 방법을 원한다는 것을 의미합니다. –