Esempio n. 1
0
  Object* Fiber::s_yield(STATE, Arguments& args) {
    Fiber* fiber = state->vm()->fiber();
    OnStack<1> os(state, fiber);

    {
      std::lock_guard<std::mutex> guard(state->vm()->thread()->fiber_mutex());

      if(fiber->root_p()) {
        Exception::raise_fiber_error(state, "can't yield from root fiber");
      } else if(fiber->status() == eTransfer) {
        Exception::raise_fiber_error(state, "can't yield from transferred fiber");
      }

      fiber->unpack_arguments(state, args);
      fiber->status(eYielding);
    }

    // Being cooperative...
    fiber->invoke_context()->fiber()->restart(state);

    // Through the worm hole...
    fiber->suspend_and_continue(state);

    // We're back...
    return fiber->return_value(state);
  }
Esempio n. 2
0
 Object* Thread::locals_remove(STATE, Symbol* key) {
   if(state->vm() != vm()) {
     return locals()->remove(state, key);
   }
   Fiber* fib = state->vm()->current_fiber.get();
   if(fib->nil_p() || fib->root_p()) {
     return locals()->remove(state, key);
   }
   if(fib->locals()->nil_p()) {
     return cNil;
   }
   return fib->locals()->remove(state, key);
 }
Esempio n. 3
0
 Object* Thread::locals_has_key(STATE, Symbol* key) {
   /*
    * If we're not trying to set values on the current thread,
    * we will set thread locals anyway and not use fiber locals.
    */
   if(state->vm() != vm()) {
     return locals()->has_key(state, key);
   }
   Fiber* fib = state->vm()->current_fiber.get();
   if(fib->nil_p() || fib->root_p()) {
     return locals()->has_key(state, key);
   }
   if(try_as<LookupTable>(fib->locals())) {
     return fib->locals()->has_key(state, key);
   }
   return cFalse;
 }
Esempio n. 4
0
 Array* Thread::locals_keys(STATE) {
   /*
    * If we're not trying to set values on the current thread,
    * we will set thread locals anyway and not use fiber locals.
    */
   if(state->vm() != vm()) {
     return locals()->all_keys(state);
   }
   Fiber* fib = state->vm()->current_fiber.get();
   if(fib->nil_p() || fib->root_p()) {
     return locals()->all_keys(state);
   }
   if(try_as<LookupTable>(fib->locals())) {
     return fib->locals()->all_keys(state);
   }
   return Array::create(state, 0);
 }
Esempio n. 5
0
 Object* Thread::locals_store(STATE, Symbol* key, Object* value) {
   /*
    * If we're not trying to set values on the current thread,
    * we will set thread locals anyway and not use fiber locals.
    */
   if(state->vm() != vm()) {
     return locals()->store(state, key, value);
   }
   Fiber* fib = state->vm()->current_fiber.get();
   if(fib->nil_p() || fib->root_p()) {
     return locals()->store(state, key, value);
   }
   if(fib->locals()->nil_p()) {
     fib->locals(state, LookupTable::create(state));
   }
   return fib->locals()->store(state, key, value);
 }
Esempio n. 6
0
  bool VM::check_thread_raise_or_kill(STATE) {
    Exception* exc = interrupted_exception();

    if(!exc->nil_p()) {
      clear_interrupted_exception();

      // Only write the locations if there are none.
      if(exc->locations()->nil_p() || exc->locations()->size() == 0) {
        exc->locations(this, Location::from_call_stack(state));
      }

      thread_state_.raise_exception(exc);

      return true;
    }

    if(interrupt_by_kill()) {
      Fiber* fib = current_fiber.get();

      if(fib->nil_p() || fib->root_p()) {
        clear_interrupt_by_kill();
      } else {
        set_check_local_interrupts();
      }

      thread_state_.raise_thread_kill();

      return true;
    }

    // If the current thread is trying to step, debugger wise, then assist!
    if(thread_step()) {
      clear_thread_step();
      if(!Helpers::yield_debugger(state, cNil)) return true;
    }

    return false;
  }