Io Language学习:并行map的运行原理

前面给了个Io异步编程的例子,最后说“和Erlang比一比“,我指的是Erlang做类似的功能需要pmap。

为什么Io的List#map可以适应这种并行调用?本文简单分析一下。

通过阅读源码,首先可以确定的是map本身没有作任何特殊处理,所以重点放在"@"这个操作符上,它完成异步操作。

经过测试发现,方法如果是异步调用(应该说消息是异步发送,说方法调用感觉自然一些),如果不“使用”调用结果,是不会等待结果返回的。这里的“使用”并不是简单地赋给一个变量,而是真正使用这个变量,比如返回一个整数,简单地:
[code]
a := foo @bar
[/code]
并不会等待调用的结果,只有使用a这个变量时--例如b := a+1, a println--它才会等待调用结果。

前面的并行map正是使用了这个特性,你可以觉得奇怪,结果放到一个list里面难道不算是使用吗?其实不然,它放入的是一个Proxy对象,并非真正的结果,只有你取用list成员时,它才会取结果。有一点细节是,就算你不取结果,但调用也是真的发生了,只是这边不用等待。

它是如何完成这个过程的?简单看一下Actor.io这个文件,"@"的实现就在这里:

[code]
Object do(
setSlot("@", method(
//writeln("@ ", call argAt(0))
m := call argAt(0) asMessageWithEvaluatedArgs(call sender)
f := Future clone setRunTarget(self) setRunMessage(m)
self actorRun
self actorQueue append(f)
f futureProxy
))
)
[/code]
可以看出它把调用塞到队列里,然后返回一个Proxy对象,所以我们的list里实际上都是FutureProxy对象,把结果类型打印一下就知道了:

[code]
result at(0) type println
[/code]

但为什么result println打印的是包含几个整数的list?

原因在于FutureProxy:

[code]
FutureProxy := Object clone do(
with := method(future,
p := self clone
p _future := future
p forward := self getSlot("_forward")
p _become := self getSlot("become")
//p xyz := method(_future writeln("XYZ!"))
p type := "FutureProxy"
p removeAllProtos
p
)

_forward := method(
//_future writeln("FutureProxy forward ", call message)
_future waitOnResult
self doMessage(call message, call sender)
)
)
[/code]

它定义了forward方法,这个方法和Ruby的method_missing相似,由于它没有其它方法,所以使用它(给它发消息)时都会自然调用到这个方法。它在这里完成的功能是等待结果,然后取得结果。这个功能也可以用Ruby来完成,Io这一整套东西其实可以用Ruby 1.9来完成,很可能比现在的Io效率高很多。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值