使用队列在D中的线程之间进行通信

时间:2017-10-07 01:12:26

标签: multithreading d

在D中使用std.container.dlist创建队列类型非常容易。

我想拥有多个线程,但让它们与队列通信,而不是与消息传递(https://tour.dlang.org/tour/en/multithreading/message-passing)。据我所知,消息旨在始终在代码中的特定点接收数据;接收线程将阻塞,直到收到预期的数据。

(编辑:我被告知有关receiveTimeout但没有超时,只是检查在这种情况下更合适(可能是0的超时?)。另外我不确定如果有多条消息,消息API会做什么在任何收到之前发送。我将不得不玩。)

void main() {
    spawn(&worker, thisTid);

    // This line will block until the expected message is received.
    receive (
        (string message) {
            writeln("Received the message: ", text);
        },
    )
}

我需要的是仅在有数据时才接收数据。像这样:

void main() {
    Queue!string queue// custom `Queue` type based on DList

    spawn(&worker, queue);

    while (true) {
        // Go through any messages (while consuming `queue`)
        for (string message; queue) {
            writeln("Received a message: ", text);
        }
        // Do other stuff
    }
}

我尝试使用shared变量(https://tour.dlang.org/tour/en/multithreading/synchronization-sharing),但DMD抱怨"别名是不允许的可变线程本地数据。"或其他一些错误,取决于。

如何在D中完成?或者,有没有办法使用消息来进行这种通信?

3 个答案:

答案 0 :(得分:1)

这并没有回答具体问题,但是我确实清楚了解我对传递消息的消息的误解......

只需拨打receiveTimeout而不是普通receive

http://dpldocs.info/experimental-docs/std.concurrency.receiveTimeout.html

答案 1 :(得分:0)

我用这个:

shared class Queue(T) {

    private T[] queue;

    synchronized void opOpAssign(string op)(T object) if(op == "~") {
        queue ~= object;
    }

    synchronized size_t length(){
        return queue.length;
    }

    synchronized T pop(){
        assert(queue.length, "Please check queue length, is 0");
        auto first = queue[0];
        queue = queue[1..$];
        return first;
    }

    synchronized shared(T[]) consume(){
        auto copy = queue;
        queue = [];
        return copy;
    }

}

答案 2 :(得分:0)

我得到了我需要的答案。

简单地说,使用core.thread而不是std.concurrencystd.concurrency为您管理邮件,不允许您自行管理。 core.threadstd.concurrency内部使用的内容。

答案越长,这就是我完全实现它的方式。

我创建了一个基于Singly Linked ListQueue类型,但保留了最后一个元素的指针。根据Walter Brights愿景(https://www.youtube.com/watch?v=cQkBOCo8UrE),Queue也使用标准组件inputRange和outputRange(或者至少我认为它)。 Queue也是为了允许一个线程写入而另一个线程在内部进行非常少的静音读取而构建的,因此它应该很快。
我在这里分享的队列https://pastebin.com/ddyPpLrp

一个简单的实现,让第二个线程读取输入:

Queue!string inputQueue = new Queue!string;
ThreadInput threadInput = new ThreadInput(inputQueue);
threadInput.start;

while (true) {
    foreach (string value; inputQueue) {
        writeln(value);
    }
}

ThreadInput被定义为:

class ThreadInput : Thread {
    private Queue!string queue;

    this(Queue!string queue) {
        super(&run);
        this.queue = queue;
    }

    private void run() {
        while (true) {
            queue.put(readln);
        }
    }
}

代码https://pastebin.com/w5jwRVrL
Queue再次https://pastebin.com/ddyPpLrp