像Erlang一样写D程序

琢磨了好久,一直没时间来做它。在讨论[url=http://www.iteye.com/topic/76007?page=5]这个问题[/url]的时候就已经有这想法了,后来发现tango里已经有Fiber的实现,昨天终于抽了点时间做了个简单的小玩意,离真实应用还差得很远。

测试代码:

import light_process;
import tango.io.Stdout;

void test() {
Stdout("test").newline;
receive(
(Process pid, float f) {
Stdout("test: receive float: ", f).newline;
pid.send(f);
},
(Process pid, int i) {
Stdout("test: receive int: ", i).newline;
pid.send(i * 2);
},
(NotMatched) {
Stdout("test: not matched").newline;
}
).timeout(3000, {
Stdout("test: timeout").newline;
}).end;

test();
}

void test1(Process pid){
Stdout("test1").newline;
//sleep(1);
pid.send(self(), 7.7f);
pid.send(self(), cast(int)3);

test1_loop();
}

void test1_loop() {
receive(
(float f) {
Stdout("test1: received result: ", f).newline;
},
(int value) {
Stdout("test1: received result: ", value).newline;
}
).timeout(3000, {
Stdout("test1: timeout").newline;
}).end;

test1_loop();
}

void sleep(size_t usecs) {
receive(

).timeout(usecs, {

}).end;
}

void de_start() {
auto pid = spawn(&test);
spawn(&test1, pid);
//sleep(3);
}

void main(){
de_start();
Process.run();
}


实现:

module light_process;

import tango.core.Thread;
import tango.core.Traits;

class NotMatched{
}

class Message {
TypeInfo typeInfo__;
public this(TypeInfo typeInfo__) {
this.typeInfo__ = typeInfo__;
}
}

class MessageT(Types...) : public Message{
Types values;

public this(Types values_){
super(typeid(typeof(Types)));
foreach(i, e; values_) {
values[i] = values_[i];
}
}
}

class Delegate {
abstract void call(Message msg);

abstract bool matchType(TypeInfo typeInfo__);
}

class DelegateT(Types...) : public Delegate{
void delegate(Types) dg;
void function(Types) func;

this(void delegate(Types) dg){
this.dg = dg;
}

this(void function(Types) func){
this.func = func;
}

override void call(Message msg) {
auto message = cast(MessageT!(Types))msg;
if (dg)
dg(message.values);
else
func(message.values);
}

override bool matchType(TypeInfo typeInfo__) {
if (typeid(Types) is typeid(NotMatched) || typeInfo__ is typeid(Types))
return true;
return false;
}
}

class Process : public Fiber{
// static members
public static Process getThis() {
return cast(Process)Fiber.getThis();
}

private static Process[] processes;

// instance members
private Message[] messages;

private Delegate[] handlers;

public this() {
super(&exec);
}

public void clearMessageHandlers() {
handlers.length = 0;
}

public void addMessageHandler(Delegate dg){
handlers ~= dg;
}

public Process timeout(int timeout, void delegate() dg) {
return this;
}

public void end() {
Fiber.yield();
domsg();
}

public Process send(Args ...)(Args args) {
messages ~= new MessageT!(Args)(args);
return this;
}

public void domsg() {
while (!messages.length) {
Fiber.yield();
}
Message msg = messages[0];
foreach(dg; handlers) {
if (dg.matchType(msg.typeInfo__)) {
dg.call(msg);
messages = messages[1..$];
break;
}
}
}

public static void run() {
while(true) {
foreach(process; Process.processes) {
if (process.state != Fiber.State.TERM) {
process.call();
}
}
}
}

protected abstract void exec();
}

class ProcessT(Ret, Args...) : public Process {
Ret delegate(Args) dg;
Ret function(Args) func;
Args args;

public this(Ret delegate(Args) dg, Args args) {
this.dg = dg;
foreach(i, e; args) {
this.args[i] = e;
}
}

public this(Ret function(Args) func, Args args) {
this.func = func;
foreach(i, e; args) {
this.args[i] = e;
}
}

public void exec() {
if (dg)
dg(args);
else
func(args);
}
}

Process spawn(Ret, Args...)(Ret delegate(Args) dg, Args args) {
Process p = new ProcessT!(Ret, Args)(dg, args);
Process.processes ~= p;
return p;
}

Process spawn(Ret, Args...)(Ret function(Args) func, Args args) {
Process p = new ProcessT!(Ret, Args)(func, args);
Process.processes ~= p;
return p;
}

Process receive(Dgs ...)(Dgs dgs) {
Process self = Process.getThis();
self.clearMessageHandlers();
foreach(i, dg; dgs) {
Delegate handler = new DelegateT!(ParameterTupleOf!(typeof(dgs[i])))
(dgs[i]);
self.addMessageHandler(handler);
}
return self;
}

Process self() {
return Process.getThis();
}


依赖tango。

目前只实现了基本的消息发送接收,为了简单目前使用内置数组来保存数据。整个驱动过程是对所有进程顺序进行调度,没有过优化是否有需要调度,只是快速做了个原型。timeout功能也没有实现,这个有时间可以重写调度部分来完成,因为这个部分就是随意写了一个,测试是否有可能实现类似erlang的高度过程。所以这个驱动过程实际上是个死循环,测试几秒就强行结束程序吧,CPU被烧本人概不负责。

递归是比较麻烦的,不知道D有没有优化尾递归,我想应该还是有的吧,不然上面那个程序应该早就溢出了。receive的各个委托参数里是没办法优化成尾递归的,解决办法当然有,就是麻烦点,谁叫咱不是FP语言呢。。(这年头,不是FP你都感觉抬不起头。。。)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值