@@ -78,49 +78,53 @@ namespace rubinius {
7878 std::lock_guard<std::mutex> guard (state->vm ()->thread ()->fiber_mutex ());
7979
8080 if (!vm ()->suspended_p ()) {
81- Exception::raise_fiber_error (state, " attempt to restart non-suspended fiber" );
82- }
83-
84- while (vm ()->suspended_p ()) {
85- std::lock_guard<std::mutex> guard (vm ()->wait_mutex ());
86- vm ()->wait_condition ().notify_one ();
81+ std::ostringstream msg;
82+ msg << " attempt to restart non-suspended (" << vm ()->transition_flag () << " ) fiber" ;
83+ Exception::raise_fiber_error (state, msg.str ().c_str ());
8784 }
8885
8986 state->vm ()->set_suspending ();
87+
88+ restart_context (state->vm ());
89+ wakeup ();
90+
91+ {
92+ UnmanagedPhase unmanaged (state);
93+
94+ while (vm ()->suspended_p ()) {
95+ std::lock_guard<std::mutex> guard (vm ()->wait_mutex ());
96+ vm ()->wait_condition ().notify_one ();
97+ }
98+ }
9099 }
91100
92101 while (!vm ()->running_p ()) {
93102 ; // spin wait
94103 }
95-
96- {
97- std::lock_guard<std::mutex> guard (state->vm ()->thread ()->fiber_mutex ());
98- state->vm ()->thread ()->current_fiber (state, this );
99- }
100104 }
101105
102- void Fiber::suspend (STATE) {
106+ void Fiber::suspend_and_continue (STATE) {
103107 {
104108 std::unique_lock<std::mutex> lk (vm ()->wait_mutex ());
105- vm ()->set_suspended ();
106109
110+ vm ()->set_suspended ();
107111 {
108112 UnmanagedPhase unmanaged (state);
109- vm ()->wait_condition ().wait (lk);
110- }
111113
114+ while (!wakeup_p ()) {
115+ vm ()->wait_condition ().wait (lk);
116+ }
117+ }
118+ clear_wakeup ();
112119 vm ()->set_resuming ();
113120 }
114121
115- while (invoke_context ()->running_p ()) {
116- ; // spin wait
117- }
118-
119122 {
120123 std::lock_guard<std::mutex> guard (state->vm ()->thread ()->fiber_mutex ());
124+
121125 vm ()->set_running ();
122126
123- while (invoke_context ()->suspending_p ()) {
127+ while (! restart_context ()->suspended_p ()) {
124128 ; // spin wait
125129 }
126130
@@ -159,7 +163,7 @@ namespace rubinius {
159163
160164 NativeMethod::init_thread (state);
161165
162- vm->fiber ()->suspend (state);
166+ vm->fiber ()->suspend_and_continue (state);
163167
164168 Object* value = vm->fiber ()->block ()->send (state, G (sym_call),
165169 as<Array>(vm->thread ()->fiber_value ()), vm->fiber ()->block ());
@@ -179,8 +183,12 @@ namespace rubinius {
179183 vm->fiber ()->invoke_context ()->fiber ()->restart (state);
180184 }
181185
182- vm->fiber ()->status (eDead);
183- vm->fiber ()->vm ()->set_finished ();
186+ {
187+ std::lock_guard<std::mutex> guard (vm->wait_mutex ());
188+
189+ vm->fiber ()->status (eDead);
190+ vm->set_suspended ();
191+ }
184192
185193 vm->unmanaged_phase ();
186194
@@ -295,60 +303,69 @@ namespace rubinius {
295303 }
296304
297305 Object* Fiber::resume (STATE, Arguments& args) {
298- if (state->vm ()->thread () != thread ()) {
299- Exception::raise_fiber_error (state, " attempt to resume fiber across threads" );
300- }
306+ {
307+ std::lock_guard<std::mutex> guard (state->vm ()->thread ()->fiber_mutex ());
301308
302- unpack_arguments (state, args);
303-
304- if (status () == eCreated) {
305- start (state, args);
306- } else if (status () == eTransfer) {
307- Exception::raise_fiber_error (state, " attempt to resume transfered fiber" );
308- } else if (status () == eRunning) {
309- Exception::raise_fiber_error (state, " attempt to resume running fiber" );
310- } else if (status () == eDead) {
311- Exception::raise_fiber_error (state, " attempt to resume dead fiber" );
312- } else if (root_p ()) {
313- Exception::raise_fiber_error (state, " attempt to resume root fiber" );
314- }
309+ if (state->vm ()->thread () != thread ()) {
310+ Exception::raise_fiber_error (state, " attempt to resume fiber across threads" );
311+ } else if (status () == eTransfer) {
312+ Exception::raise_fiber_error (state, " attempt to resume transfered fiber" );
313+ } else if (status () == eRunning) {
314+ Exception::raise_fiber_error (state, " attempt to resume running fiber" );
315+ } else if (status () == eDead) {
316+ Exception::raise_fiber_error (state, " attempt to resume dead fiber" );
317+ } else if (root_p ()) {
318+ Exception::raise_fiber_error (state, " attempt to resume root fiber" );
319+ }
320+
321+ unpack_arguments (state, args);
322+ invoke_context (state->vm ());
315323
316- status (eRunning);
317- invoke_context (state->vm ());
324+ if (status () == eCreated) {
325+ start (state, args);
326+ }
327+
328+ status (eRunning);
329+ }
318330
319331 // Being cooperative...
320332 restart (state);
321333
322334 // Through the worm hole...
323- state->vm ()->fiber ()->suspend (state);
335+ state->vm ()->fiber ()->suspend_and_continue (state);
324336
325337 // We're back...
326338 return return_value (state);
327339 }
328340
329341 Object* Fiber::transfer (STATE, Arguments& args) {
330- if (state->vm ()->thread () != thread ()) {
331- Exception::raise_fiber_error (state, " attempt to transfer fiber across threads" );
332- }
342+ {
343+ std::lock_guard<std::mutex> guard (state->vm ()->thread ()->fiber_mutex ());
333344
334- unpack_arguments (state, args);
345+ if (state->vm ()->thread () != thread ()) {
346+ Exception::raise_fiber_error (state, " attempt to transfer fiber across threads" );
347+ } else if (status () == eDead) {
348+ Exception::raise_fiber_error (state, " attempt to transfer to dead fiber" );
349+ } else if (state->vm ()->fiber () == this ) {
350+ // This should arguably be a FiberError
351+ return args.as_array (state);
352+ }
335353
336- if (status () == eCreated) {
337- start (state, args);
338- } else if (state->vm ()->fiber () == this ) {
339- return args.as_array (state);
340- } else if (status () == eDead) {
341- Exception::raise_fiber_error (state, " attempt to transfer to dead fiber" );
342- }
354+ unpack_arguments (state, args);
355+ invoke_context (state->vm ());
356+
357+ if (status () == eCreated) {
358+ start (state, args);
359+ }
343360
344- status (eTransfer);
345- invoke_context (state-> vm ());
361+ status (eTransfer);
362+ }
346363
347364 // Being cooperative...
348365 restart (state);
349366
350367 // Through the worm hole...
351- state->vm ()->fiber ()->suspend (state);
368+ state->vm ()->fiber ()->suspend_and_continue (state);
352369
353370 // We're back...
354371 return return_value (state);
@@ -358,20 +375,24 @@ namespace rubinius {
358375 Fiber* fiber = state->vm ()->fiber ();
359376 OnStack<1 > os (state, fiber);
360377
361- if (fiber->root_p ()) {
362- Exception::raise_fiber_error (state, " can't yield from root fiber" );
363- } else if (fiber->status () == eTransfer) {
364- Exception::raise_fiber_error (state, " can't yield from transferred fiber" );
365- }
378+ {
379+ std::lock_guard<std::mutex> guard (state->vm ()->thread ()->fiber_mutex ());
366380
367- fiber->unpack_arguments (state, args);
368- fiber->status (eYielding);
381+ if (fiber->root_p ()) {
382+ Exception::raise_fiber_error (state, " can't yield from root fiber" );
383+ } else if (fiber->status () == eTransfer) {
384+ Exception::raise_fiber_error (state, " can't yield from transferred fiber" );
385+ }
386+
387+ fiber->unpack_arguments (state, args);
388+ fiber->status (eYielding);
389+ }
369390
370391 // Being cooperative...
371392 fiber->invoke_context ()->fiber ()->restart (state);
372393
373394 // Through the worm hole...
374- fiber->suspend (state);
395+ fiber->suspend_and_continue (state);
375396
376397 // We're back...
377398 return fiber->return_value (state);
0 commit comments