What have you found for these years?

2012-12-14

與 ko1 的一些聊天內容 (2)

延續上篇:
2223. 12-13 與 ko1 的一些聊天內容



忘記提關於 fibers 的事。很明顯我的信寫太長了,他懶得看 XD 我有貼出來:
2222. 12-09 Regarding Fibers
因此他直接問我內容。可惜的是時間不夠,結果只稍微講了前面,後面沒講到。

簡單地說,他後來終於懂了這個用法的意思。我說在 nodejs 裡面,有無數解決
這個問題的東西被發明,而在 ruby 中,這是其中一個。不過他仍然覺得這是一個
不好的寫法。我不確定理由是什麼,不過他表面上的意思是 fibers 是被設計來寫
generator, 不是做這種事。另外我也提到有時候我會需要 double resume
intentionally, 他提到可以用 Fiber#transfer.

我是知道這個東西,但想不出來有什麼場合會需要這樣用。ko1 回答,這只有
computer scientists 才會有興趣 XD

但後來跟 fumin 試了好一會。fumin 寫了一個 future 的實作,玩弄了一會,
我發現我原本對 Fiber#transfer 的理解並不是很完整。同時 ko1 說的沒錯,
在我需要 double resume 時,用 transfer 就對了。

這樣其實讓我更困惑,因為感覺上 transfer 就只是比較強的 resume 而已。
那麼是因為有實作效能的差異,所以才區分 resume 跟 transfer 嗎?
可惜來不及問了 :P

總之 transfer 有點像是 resume + yield, 因此可以亂轉一通。但是 resume
並不會 yield, current fiber 仍然會是在 resumed 狀態,因此不能寫:

f1 = nil
f0 = Fiber.new{ f1.resume }
f1 = Fiber.new{ f0.resume }
f1.resume # double resume

但是可以寫:
require 'fiber'
f1 = nil
f0 = Fiber.new{ f1.transfer }
f1 = Fiber.new{ f0.transfer }
f1.transfer # ok

另一個差別是 resume 並不會使得 current fiber yield, 像是:
f1 = nil
f0 = Fiber.new{ true }
f1 = Fiber.new{ f0.resume; false }
f1.resume # false
f1.alive? # false

但是如果是 transfer, 則 current fiber 會 yield:
require 'fiber'
f1 = nil
f0 = Fiber.new{ true }
f1 = Fiber.new{ f0.transfer; false }
f1.transfer # true
f1.alive?   # true

0 retries:

Post a Comment

All texts are licensed under CC Attribution 3.0