<div dir="ltr"><div>So I'm porting so #golang code to #dlang and there is all these blasted "go" statements.So I thought I'd give implmenting it in D a shot. What do you guys think?<br>Fire away :).<br><br>
import std.stdio;<br>import core.thread : Thread;<br>import core.sync.mutex : Mutex;<br>import core.time;<br><br>void main() {<br>    auto ch = chan!int(1);<br>    go!({<br>        foreach (i; 22..44) {<br>            ch._ = i;<br>
        } });<br><br>    foreach (i; 0..10) {<br>        writeln("pop: ", ch._);<br>    }<br>}<br><br></div>// Implementation<br><br>void go(alias F)() {<br>    auto t = new Thread(F);<br>    t.isDaemon(true); // we don't care if this thread dies.<br>
    t.start();<br>}<br><br>/**<br> * chan allows messaging between threads without having to deal with locks, similar to how chan works in golang<br> */<br>class chan_(T) {<br>    shared Mutex lock;<br>    struct Container(T) {<br>
        T value;<br>        Container!T* next;<br>    }<br>    shared Container!T* buf;<br>    shared Container!T* last;<br>    shared size_t length;<br>    shared void insert(shared T v) {<br>        shared Container!T* newItem = new shared Container!T();<br>
        newItem.value = v;<br>        if (buf is null) {<br>            buf = newItem;<br>            last = newItem;<br>        } else {<br>            last.next = newItem;<br>            last = newItem;<br>        }<br>
        length++;<br>    }<br>    shared T popFront() {<br>        T ret;<br>        synchronized (lock) {<br>            ret = buf.value;<br>            buf = buf.next;<br>            length--;<br>        }<br>        return ret;<br>
    }<br>    size_t maxItems;<br>    bool blockOnFull = false;<br>    this(int maxItems = 1024, bool blockOnFull = true) {<br>        lock = cast(shared)new Mutex;<br>        length = 0;<br><br>        this.maxItems = maxItems;<br>
        this.blockOnFull = blockOnFull;<br>    }<br><br>    @property<br>    shared void _(T value) {<br>        bool done;<br>        while(true) {<br>            synchronized(lock) {<br>                if (!done && length < maxItems) {<br>
                    insert(value);<br>                    done = true;<br>                } else if (!blockOnFull) {<br>                    throw new ChannelFull("Channel Full");<br>                }<br>                if (length <= maxItems-1) {<br>
                    break;<br>                }<br>            }<br>            Thread.sleep(dur!"msecs"(5));<br>        }<br>    }<br>    @property<br>    shared T _() {<br>        while(true) {<br>            size_t len;<br>
            synchronized(lock) {<br>                len = length;<br>            }<br>            if (len > 0) {<br>                break;<br>            }<br>            Thread.sleep(dur!"msecs"(5));<br>        };<br>
        auto r = popFront();<br>        return r;<br>    }<br>}<br>auto chan(T)(int n, bool blockOnFull = true) {<br>    return cast(shared)new chan_!T(n, blockOnFull);<br>}<br><br>class ChannelFull : Exception {<br>    this(string msg, string file = __FILE__, ulong line = cast(ulong)__LINE__, Throwable next = null) {<br>
        super(msg,file,line,next);<br>    }<br>}<br><br></div>