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?
Fire away :).
import std.stdio;
import core.thread : Thread;
import core.sync.mutex : Mutex;
import core.time;
void main() {
auto ch = chan!int(1);
go!({
foreach (i; 22..44) {
ch._ = i;
} });
foreach (i; 0..10) {
writeln("pop: ", ch._);
}
}
// Implementation
void go(alias F)() {
auto t = new Thread(F);
t.isDaemon(true); // we don't care if this thread dies.
t.start();
}
/**
* chan allows messaging between threads without having to deal with locks, similar to how chan works in golang
*/
class chan_(T) {
shared Mutex lock;
struct Container(T) {
T value;
Container!T* next;
}
shared Container!T* buf;
shared Container!T* last;
shared size_t length;
shared void insert(shared T v) {
shared Container!T* newItem = new shared Container!T();
newItem.value = v;
if (buf is null) {
buf = newItem;
last = newItem;
} else {
last.next = newItem;
last = newItem;
}
length++;
}
shared T popFront() {
T ret;
synchronized (lock) {
ret = buf.value;
buf = buf.next;
length--;
}
return ret;
}
size_t maxItems;
bool blockOnFull = false;
this(int maxItems = 1024, bool blockOnFull = true) {
lock = cast(shared)new Mutex;
length = 0;
this.maxItems = maxItems;
this.blockOnFull = blockOnFull;
}
@property
shared void _(T value) {
bool done;
while(true) {
synchronized(lock) {
if (!done && length < maxItems) {
insert(value);
done = true;
} else if (!blockOnFull) {
throw new ChannelFull("Channel Full");
}
if (length <= maxItems-1) {
break;
}
}
Thread.sleep(dur!"msecs"(5));
}
}
@property
shared T _() {
while(true) {
size_t len;
synchronized(lock) {
len = length;
}
if (len > 0) {
break;
}
Thread.sleep(dur!"msecs"(5));
};
auto r = popFront();
return r;
}
}
auto chan(T)(int n, bool blockOnFull = true) {
return cast(shared)new chan_!T(n, blockOnFull);
}
class ChannelFull : Exception {
this(string msg, string file = __FILE__, ulong line = cast(ulong)__LINE__, Throwable next = null) {
super(msg,file,line,next);
}
}