https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112014-10-09T02:58:57ZRuby Issue Tracking SystemRuby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=493092014-10-09T02:58:57Zko1 (Koichi Sasada)
<ul></ul><p>Do you have good example to use it?</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=493182014-10-09T10:16:59Zfunny_falcon (Yura Sokolov)funny.falcon@gmail.com
<ul></ul><p>Yes: it is missing piece to make "greenlet" port, in other words - green threads that mimics real threads.<br>
To accomplish that there is a need to raise exception in a fiber waiting on event if event fails.<br>
As Knut said it could be implemented in a Ruby, but it feels to be dirty way. If implemented in C it will lead to cleaner implementation.</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=493552014-10-11T16:28:50Znome (Knut Franke)Knut.Franke@gmx.de
<ul></ul><p>For some more sophisticated examples, see <a href="https://github.com/nome/coroutines" class="external">https://github.com/nome/coroutines</a>. The library does work with vanilla Ruby, but the patch improves performance.</p>
<p>Also, similar code can be simplified by using Fiber#raise. Compare e.g. the two implementation of Consumer::Yielder#await at<br>
<a href="https://github.com/nome/coroutines/blob/master/lib/coroutines/base.rb" class="external">https://github.com/nome/coroutines/blob/master/lib/coroutines/base.rb</a></p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=494832014-10-16T04:41:30Zko1 (Koichi Sasada)
<ul></ul><p>On 2014/10/12 1:28, <a href="mailto:Knut.Franke@gmx.de" class="email">Knut.Franke@gmx.de</a> wrote:</p>
<blockquote>
<p>For some more sophisticated examples, see <a href="https://github.com/nome/coroutines" class="external">https://github.com/nome/coroutines</a>. The library does work with vanilla Ruby, but the patch improves performance.</p>
<p>Also, similar code can be simplified by using Fiber#raise. Compare e.g. the two implementation of Consumer::Yielder#await at<br>
<a href="https://github.com/nome/coroutines/blob/master/lib/coroutines/base.rb" class="external">https://github.com/nome/coroutines/blob/master/lib/coroutines/base.rb</a></p>
</blockquote>
<p>I understand this feature helps some libraries. But I can't understand<br>
why it is important.</p>
<p>I'm afraid that introducing such feature increases complexity of Fiber.<br>
Basically, I want to recommend strongly that using Fiber as<br>
semi-croutine, ristricted feature.</p>
<p>At least, such feature should be located at ext/fiber.</p>
<p>--<br>
// SASADA Koichi at atdot dot net</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=495172014-10-18T12:11:28Zfunny_falcon (Yura Sokolov)funny.falcon@gmail.com
<ul></ul><blockquote>
<p>At least, such feature should be located at ext/fiber.</p>
</blockquote>
<p>even if ext/fiber it is still should be implemented in C .</p>
<blockquote>
<p>I'm afraid that introducing such feature increases complexity of Fiber.</p>
</blockquote>
<p>Not too much. Look at the patch: it uses same hook as <code>rb_fiber_terminate</code>.</p>
<p>By the way, why Thread has this feature?<br>
<a href="http://www.ruby-doc.org/core-2.1.3/Thread.html#method-i-raise" class="external">http://www.ruby-doc.org/core-2.1.3/Thread.html#method-i-raise</a><br>
And why Fiber hasn't? In fact, it is strange that this feature still not<br>
presented, cause it is expected to exists.</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=495182014-10-18T13:55:51Znome (Knut Franke)Knut.Franke@gmx.de
<ul><li><strong>File</strong> <a href="/attachments/4785">0001-Implement-Fiber-raise.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/4785/0001-Implement-Fiber-raise.patch">0001-Implement-Fiber-raise.patch</a> added</li><li><strong>File</strong> <a href="/attachments/4786">0001-Implement-Fiber-raise-in-ext-fiber.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/4786/0001-Implement-Fiber-raise-in-ext-fiber.patch">0001-Implement-Fiber-raise-in-ext-fiber.patch</a> added</li></ul><blockquote>
<p>I understand this feature helps some libraries. But I can't understand why it is important.</p>
</blockquote>
<p>Without Fiber#raise, libraries need to use some rather inelegant and inefficient workarounds (wrapping or tagging exceptions, wrapping Fiber.yield etc). Also, having Thread#raise arguably leads one to expect the same functionality in Fiber. I'm not sure whether the feature qualifies as "important", but I still think it is worth including.</p>
<blockquote>
<p>Basically, I want to recommend strongly that using Fiber as semi-croutine, ristricted feature.</p>
</blockquote>
<p>I think <a href="http://nome.github.io/coroutines/Consumer.html" class="external">Consumer</a> is an example of a semi-coroutine (in the sense that it uses Fiber.yield, not Fiber#transfer) that benefits from having Fiber#raise.</p>
<blockquote>
<p>At least, such feature should be located at ext/fiber.</p>
</blockquote>
<p>I disagree, because the feature is applicable to the restricted (semi-coroutine) fibers available without requiring 'fiber', and indeed implementable on top of them. Nevertheless, I've attached a variant of the patch which adds the method only in ext/fiber (as a compromise solution).</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=495972014-10-23T01:05:15Zko1 (Koichi Sasada)
<ul></ul><p>Yura Sokolov wrote:</p>
<blockquote>
<blockquote>
<p>At least, such feature should be located at ext/fiber.</p>
</blockquote>
<p>even if ext/fiber it is still should be implemented in C .</p>
</blockquote>
<p>I agree.</p>
<blockquote>
<blockquote>
<p>I'm afraid that introducing such feature increases complexity of Fiber.</p>
</blockquote>
<p>Not too much. Look at the patch: it uses same hook as <code>rb_fiber_terminate</code>.</p>
</blockquote>
<p>I don't mention about implementation, but specification.</p>
<blockquote>
<p>By the way, why Thread has this feature?<br>
<a href="http://www.ruby-doc.org/core-2.1.3/Thread.html#method-i-raise" class="external">http://www.ruby-doc.org/core-2.1.3/Thread.html#method-i-raise</a><br>
And why Fiber hasn't? In fact, it is strange that this feature still not<br>
presented, cause it is expected to exists.</p>
</blockquote>
<p>Thread#raise is one of inter communication method (but asynchronouse, difficult, unrecommended way).</p>
<p>Fibers can be under control without such communication.</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=495982014-10-23T01:08:28Zko1 (Koichi Sasada)
<ul></ul><p>Knut Franke wrote:</p>
<blockquote>
<blockquote>
<p>I understand this feature helps some libraries. But I can't understand why it is important.</p>
</blockquote>
<p>Without Fiber#raise, libraries need to use some rather inelegant and inefficient workarounds (wrapping or tagging exceptions, wrapping Fiber.yield etc).</p>
</blockquote>
<p>I understand.</p>
<blockquote>
<p>Also, having Thread#raise arguably leads one to expect the same functionality in Fiber. I'm not sure whether the feature qualifies as "important", but I still think it is worth including.</p>
</blockquote>
<p>I don't expect there is Fiber#raise. Fiber and Thread are different.</p>
<blockquote>
<blockquote>
<p>Basically, I want to recommend strongly that using Fiber as semi-croutine, ristricted feature.</p>
</blockquote>
<p>I think <a href="http://nome.github.io/coroutines/Consumer.html" class="external">Consumer</a> is an example of a semi-coroutine (in the sense that it uses Fiber.yield, not Fiber#transfer) that benefits from having Fiber#raise.</p>
</blockquote>
<p>Interesting. I don't know details of this library. Could you explain why it is important in this library?</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=496342014-10-24T16:16:34Znome (Knut Franke)Knut.Franke@gmx.de
<ul></ul><p>Koichi Sasada wrote:</p>
<blockquote>
<blockquote>
<p>I think <a href="http://nome.github.io/coroutines/Consumer.html" class="external">Consumer</a> is an example of a semi-coroutine (in the sense that it uses Fiber.yield, not Fiber#transfer) that benefits from having Fiber#raise.</p>
</blockquote>
<p>Interesting. I don't know details of this library. Could you explain why it is important in this library?</p>
</blockquote>
<p>Consumer provides an abstraction for (semi-)coroutines that accept (consume) values; analogous to an Enumerator, which produces (enumerates) values. Since a consumer may need to do resource cleanup and/or produce a final result, we need some way to signal end of values. I think the most natural way to do this is to raise StopIteration in the consumer: The situation is analogous to calling Enumerator#next when no more values are available, and StopIteration terminates Kernel#loop, which often allows writing consumers very concisely.</p>
<p>In general, I think Fiber is a powerful primitive that can be used by libraries to build abstractions like Enumerator, Consumer and others. While Enumerator does not require the #raise feature, other abstractions can very well benefit from it.</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=667702017-09-19T09:07:06Zyugui (Yuki Sonoda)yugui@yugui.jp
<ul><li><strong>Assignee</strong> set to <i>ko1 (Koichi Sasada)</i></li><li><strong>Target version</strong> set to <i>2.5</i></li></ul><p>Let me add another use case which I discussed with naruse and akr in RubyKaigi.</p>
<p><code>Fiber#raise</code> is helpful to improve compatibility of methods with blocks (internal iterators) and <code>Enumerator</code> (external iterators).<br>
This happened for me when I tried to write an adapter between two independently-developed APIs.</p>
<p>Here's a simplified example below. You can also find the real example in <a href="https://github.com/supership-jp/activerecord-spanner-adapter/blob/master/lib/active_record/connection_adapters/spanner/client.rb" class="external">https://github.com/supership-jp/activerecord-spanner-adapter/blob/master/lib/active_record/connection_adapters/spanner/client.rb</a>.</p>
<a name="Example"></a>
<h1 >Example<a href="#Example" class="wiki-anchor">¶</a></h1>
<p>Suppose that we have a third-paty API, which we cannot control.</p>
<pre><code>def with_transaction
tx = Transaction.new
begin
yield tx
rescue
tx.rollback
else
tx.commit
end
end
</code></pre>
<p>And now I need to begin a transaction in a method and then need to commit or rollback the transaction in other methods.</p>
<pre><code>class TransactionManager
def begin_transaction
@iter = Transaction.enum_for(:begin_transaction)
@tx = @iter.next # skip error handlings for simplicity
end
def commit_transaction
loop { @iter.next }
ensure
@tx = nil
end
def abort_transaction(reason = RuntimeError.new)
# ??? How can I let the iterator know the error raised
@iter.raise(reason)
end
attr_reader :tx
end
</code></pre>
<p>In other words, internal iterators in Ruby can manage resources in it but external iterators can't even if the user tried to take responsibility of calling cleanup mechanism.<br>
In the real usecase, <code>with_transaction</code> was an API given by <code>google-cloud-spanner</code> gem and the interface of the <code>TransactionManager</code> was the one I had to implement for ActiveRecord.</p>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>Although I could certainly implement the adapter without the native <code>Fiber#raise</code>, it would be still helpful if internal iterators and external iterators in Ruby were more consistent.</p>
<p>Can we have <code>Fiber#raise</code> and <code>Enumerator#raise</code> on top of it to improve the consistency? ko1?</p>
<p>FYI: I've confirmed that the patch by nome still works fine for ruby-trunk. <a href="https://github.com/yugui/ruby/commit/5a04a8b49b5086686fd75c6635c95c12ccc6caa8" class="external">https://github.com/yugui/ruby/commit/5a04a8b49b5086686fd75c6635c95c12ccc6caa8</a></p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=681222017-12-01T16:46:41Znaruse (Yui NARUSE)naruse@airemix.jp
<ul><li><strong>Target version</strong> deleted (<del><i>2.5</i></del>)</li></ul> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=755852018-12-12T01:51:19Zioquatix (Samuel Williams)samuel@oriontransfer.net
<ul></ul><p>I think this is a good idea. I already ended up implementing it by hand, but it's messy.</p>
<p><a href="https://github.com/socketry/async/blob/e169aac7bc47f251ae7c6ebe94820b41bc2d063f/lib/async/task.rb#L43-L55" class="external">https://github.com/socketry/async/blob/e169aac7bc47f251ae7c6ebe94820b41bc2d063f/lib/async/task.rb#L43-L55</a></p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=755862018-12-12T01:51:58Zioquatix (Samuel Williams)samuel@oriontransfer.net
<ul></ul><p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/17">@ko1 (Koichi Sasada)</a> do you think we can aim for 2.6? I don't mind reviewing this patch and merging it if you are happy with it.</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=757892018-12-20T01:11:19Zioquatix (Samuel Williams)samuel@oriontransfer.net
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> changed from <i>ko1 (Koichi Sasada)</i> to <i>ioquatix (Samuel Williams)</i></li><li><strong>Target version</strong> set to <i>2.7</i></li></ul><p>We will experiment and aim to merge this into 2.7</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=757912018-12-20T01:11:52Zioquatix (Samuel Williams)samuel@oriontransfer.net
<ul><li><strong>Related to</strong> <i><a class="issue tracker-1 status-5 priority-4 priority-default closed" href="/issues/595">Bug #595</a>: Fiber ignores ensure clause</i> added</li></ul> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=759462018-12-28T13:03:13ZAnonymous
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li></ul><p>Applied in changeset trunk|r66610.</p>
<hr>
<p>Implement Fiber#raise. Fixes <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: [PATCH] Implement Fiber#raise (Closed)" href="https://redmine.ruby-lang.org/issues/10344">#10344</a>.</p>
<p>This allows raising exceptions in another fiber, similarly to<br>
Thread#raise.</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=759472018-12-28T13:04:49Zioquatix (Samuel Williams)samuel@oriontransfer.net
<ul></ul><p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/8645">@nome (Knut Franke)</a> can you review the relevant commits and give me feedback?</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=760092018-12-30T15:48:16Znaruse (Yui NARUSE)naruse@airemix.jp
<ul></ul><p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/3344">@ioquatix (Samuel Williams)</a> Is this feature accepted by matz?<br>
A change which is visible from Ruby and non trivial bugs requires matz's approval.</p>
<p>And also you need to add description to NEWS if you add new feature.</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=760102018-12-30T17:44:06Zko1 (Koichi Sasada)
<ul></ul><p>naruse (Yui NARUSE) wrote:</p>
<blockquote>
<p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/3344">@ioquatix (Samuel Williams)</a> Is this feature accepted by matz?<br>
A change which is visible from Ruby and non trivial bugs requires matz's approval.</p>
</blockquote>
<p>this is a support comment.</p>
<p>Matz agreed this feature several years ago (maybe I'm only person against, and I also agree to introduce this feature now, except naming issue. but nobody except me has no objection :p)<br>
I'm not sure about naming issue, but he doesn't say anything last time.</p>
<p>Anyway, it is safe to discuss at next dev meeting (I will speak for Samuel).</p>
<p>Thanks,<br>
Koichi</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=760152018-12-30T21:56:53Zioquatix (Samuel Williams)samuel@oriontransfer.net
<ul></ul><p>Thanks I didn’t know approval procedure.</p>
<p>I will update NEWS one I’m sure the feature has stabilised.</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=760172018-12-31T05:00:45Znaruse (Yui NARUSE)naruse@airemix.jp
<ul></ul><p>ko1 (Koichi Sasada) wrote:</p>
<blockquote>
<p>naruse (Yui NARUSE) wrote:</p>
<blockquote>
<p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/3344">@ioquatix (Samuel Williams)</a> Is this feature accepted by matz?<br>
A change which is visible from Ruby and non trivial bugs requires matz's approval.</p>
</blockquote>
<p>this is a support comment.</p>
<p>Matz agreed this feature several years ago (maybe I'm only person against, and I also agree to introduce this feature now, except naming issue. but nobody except me has no objection :p)<br>
I'm not sure about naming issue, but he doesn't say anything last time.</p>
<p>Anyway, it is safe to discuss at next dev meeting (I will speak for Samuel).</p>
</blockquote>
<p>Sure, thank you for comment.</p>
<p>ioquatix (Samuel Williams) wrote:</p>
<blockquote>
<p>Thanks I didn’t know approval procedure.</p>
<p>I will update NEWS one I’m sure the feature has stabilised.</p>
</blockquote>
<p>Anyway please update NEWS now to avoid forgetting adding the description.</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=782542019-05-28T11:26:16Zdecuplet (Nikita Shilnikov)fg@flashgordon.ru
<ul></ul><p>Shortly after I started to work on a library implementing algebraic effects (<a href="https://github.com/dry-rb/dry-effects" class="external">https://github.com/dry-rb/dry-effects</a>) I stumbled upon lack of <code>Fiber#raise</code>. From the user POV it is important to signal improper use of effects with a meaningful stacktrace so they can quickly detect what's wrong. It's possible to emulate <code>#raise</code> with checks but it's quite inefficient and seems redundant. Thank you all folks for discussing and working on this, I hope it'll land in 2.7. If you're interested I can show a clear example but the task is almost identical to @ioquatix's one.</p> Ruby master - Feature #10344: [PATCH] Implement Fiber#raisehttps://redmine.ruby-lang.org/issues/10344?journal_id=815542019-09-14T21:49:22Zioquatix (Samuel Williams)samuel@oriontransfer.net
<ul></ul><p>NEWS is updated.</p>