Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading D中的并发文件访问_Multithreading_Logging_Synchronization_D - Fatal编程技术网

Multithreading D中的并发文件访问

Multithreading D中的并发文件访问,multithreading,logging,synchronization,d,Multithreading,Logging,Synchronization,D,我正在尝试在D中实现一个简单的全局记录器,它将消息写入一些文件。我想让所有线程都能访问它,因为我计划最初只使用一个简单的日志,所以我让类同步化了 import std.stdio; import std.exception; import std.conv; @trusted: enum LogLevel { NONE, ERROR, WARN, INFO, DEBUG, } synchronized class Logger { LogL

我正在尝试在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;
}
导入标准stdio;
进口标准例外;
进口标准conv;
@信任的:
枚举日志级别{
没有一个
错误,
警告,,
信息,
调试,
}
同步类记录器{
LogLevel level=LogLevel.WARN;
//文件*必须共享,因为这是一个同步类
@属性共享(文件*)输出(){return to;}
@属性无效输出(共享(文件*)f)
{
强制执行(f!=null);
to=f;
}
无效日志(日志级别l)(字符串消息,字符串文件=\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
{
如果(l
但是,似乎
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编程语言中,他提到
    stout
    上的
    writeln
    对于输出流来说是原子的,但我似乎在在线文档的任何地方都找不到

  • 即使第1点为真,为了输出属性的缘故,我是否仍然希望对
    记录器
    类进行同步化


  • 更简单的方法是在需要登录时生成另一个线程并向其传递消息

    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, ")");
            }
        }
    }
    
    void loggerLoop(){
    //安装文件等
    登记册(thisTid,“记录器”);
    范围(退出)注销(“记录器”);
    while(true){
    接收((日志级别l,字符串消息,字符串文件,int行){
    如果(l
    好的,但是如何传递哪个
    文件*
    (即,在您的示例中,
    )来登录?考虑到我的选项是将文件线程设置为本地线程或不可变线程(这将禁止对其进行写入),是否无法在线程之间共享文件?如果我想使用stdout作为我的文件怎么办?我当然希望能够从记录器和其他来源打印。@DejanLekic这不是重点。同样,如果我想使用stdout作为我的文件怎么办?我当然希望能够从程序的其余部分打印到它,而不仅仅是记录器,这意味着我想让多个线程共享一个
    文件
    句柄。如果你看一下stdio.d代码,你会发现stdin、stdout和stderr都是共享对象。这些对象都是文件对象,但棘手的是它们在运行时由静态构造函数初始化。谢谢你的支持这些信息来自C++/C#/Java世界,我需要一些时间来重新配置我的大脑,使之适应信息传递范式。