`
qiezi
  • 浏览: 492681 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

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

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

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

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

并不会等待调用的结果,只有使用a这个变量时--例如b := a+1, a println--它才会等待调用结果。

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

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

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
	))
)

可以看出它把调用塞到队列里,然后返回一个Proxy对象,所以我们的list里实际上都是FutureProxy对象,把结果类型打印一下就知道了:

result at(0) type println


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

原因在于FutureProxy:

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)
	)
)


它定义了forward方法,这个方法和Ruby的method_missing相似,由于它没有其它方法,所以使用它(给它发消息)时都会自然调用到这个方法。它在这里完成的功能是等待结果,然后取得结果。这个功能也可以用Ruby来完成,Io这一整套东西其实可以用Ruby 1.9来完成,很可能比现在的Io效率高很多。
0
0
分享到:
评论
1 楼 simohayha 2008-01-31  
这里有个基于ruby1.9的actor模型的实现

http://revactor.org/

相关推荐

Global site tag (gtag.js) - Google Analytics