pike.git / lib / modules / Concurrent.pmod

version» Context lines:

pike.git/lib/modules/Concurrent.pmod:26:   //! Value that will be provided asynchronously   //! sometime in the future.   //!   //! @seealso   //! @[Promise]   class Future   {    mixed result = UNDEFINED;    State state;    -  protected array(array(function(mixed, mixed ...: void)|array(mixed))) +  protected array(array(function(mixed, mixed ...: void)|mixed))    success_cbs = ({}); -  protected array(array(function(mixed, mixed ...: void)|array(mixed))) +  protected array(array(function(mixed, mixed ...: void)|mixed))    failure_cbs = ({});       //! Wait for fulfillment and return the value.    //!    //! @throws    //! Throws on rejection.    mixed get()    {    State s = state;    mixed res = result;
pike.git/lib/modules/Concurrent.pmod:76:    //! @note    //! @[cb] will always be called from the main backend.    //!    //! @seealso    //! @[on_failure()]    this_program on_success(function(mixed, mixed ... : void) cb, mixed ... extra)    {    Thread.MutexKey key = mux->lock();       if (state == STATE_FULFILLED) { +  key = 0;    call_out(cb, 0, result, @extra); -  +  } else { +  success_cbs += ({ ({ cb, @extra }) });    key = 0; -  return this_program::this; +     }    -  success_cbs += ({ ({ cb, extra }) }); -  key = 0; -  +     return this_program::this;    }       //! Register a callback that is to be called on failure.    //!    //! @param cb    //! Function to be called. The first argument will be the    //! failure result of the @[Future].    //!    //! @param extra
pike.git/lib/modules/Concurrent.pmod:107:    //! @note    //! @[cb] will always be called from the main backend.    //!    //! @seealso    //! @[on_success()]    this_program on_failure(function(mixed, mixed ... : void) cb, mixed ... extra)    {    Thread.MutexKey key = mux->lock();       if (state == STATE_REJECTED) { +  key = 0;    call_out(cb, 0, result, @extra); -  +  } else { +  failure_cbs += ({ ({ cb, @extra }) });    key = 0; -  return this_program::this; +     }    -  failure_cbs += ({ ({ cb, extra }) }); -  key = 0; -  +     return this_program::this;    }       //! Apply @[fun] with @[val] followed by the contents of @[ctx],    //! and update @[p] with the result.    protected void apply(mixed val, Promise p,    function(mixed, mixed ... : mixed) fun,    array(mixed) ctx)    {    mixed err = catch {
pike.git/lib/modules/Concurrent.pmod:594:    if (_astate) catch(_astate->materialise()); // catches race for _astate == 0    return ::get();    }       //! The future value that we promise.    Future future()    {    return Future::this;    }    -  protected void unlocked_success(mixed value) -  { -  if (state < STATE_REJECTED) { +  protected this_program finalise(State newstate, mixed value, int try, +  array(array(function(mixed, mixed ...: void)|array(mixed))) cbs, +  void|function(mixed : void) globalfailure) { +  Thread.MutexKey key = mux->lock(); +  if (!state) { +  state = newstate;    result = value; -  state = STATE_FULFILLED; +  key = 0;    cond->broadcast(); -  foreach(success_cbs, -  [function(mixed, mixed ...: void) cb, -  array(mixed) extra]) { -  if (cb) { -  call_out(cb, 0, value, @extra); +  if (sizeof(cbs)) { +  foreach(cbs; ; array cb) +  if (cb) +  call_out(cb[0], 0, value, @cb[1..]); +  } else if (globalfailure) +  call_out(globalfailure, 0, value); +  } else { +  key = 0; +  if (!try) +  error("Promise has already been finalised.\n");    } -  +  return this_program::this;    } -  } -  } +     -  +  //! @decl this_program success(mixed value) +  //!    //! Fulfill the @[Future].    //!    //! @param value    //! Result of the @[Future].    //!    //! @throws    //! Throws an error if the @[Future] already has been fulfilled    //! or failed.    //!    //! Mark the @[Future] as fulfilled, and schedule the @[on_success()]    //! callbacks to be called as soon as possible.    //!    //! @seealso    //! @[try_success()], @[try_failure()], @[failure()], @[on_success()] -  void success(mixed value) +  this_program success(mixed value, void|int try)    { -  if (state) error("Promise has already been finalised.\n"); -  Thread.MutexKey key = mux->lock(); -  if (state) error("Promise has already been finalised.\n"); -  unlocked_success(value); -  key = 0; +  return finalise(STATE_FULFILLED, value, try, success_cbs);    }       //! Fulfill the @[Future] if it hasn't been fulfilled or failed already.    //!    //! @param value    //! Result of the @[Future].    //!    //! Mark the @[Future] as fulfilled if it hasn't already been fulfilled    //! or failed, and in that case schedule the @[on_success()] callbacks    //! to be called as soon as possible.    //!    //! @seealso    //! @[success()], @[try_failure()], @[failure()], @[on_success()] -  void try_success(mixed value) +  inline this_program try_success(mixed value)    { -  if (state) return; -  Thread.MutexKey key = mux->lock(); -  if (state) return; -  unlocked_success(value); -  key = 0; +  return state ? this_program::this : success(value, 1);    }    -  protected void unlocked_failure(mixed value) -  { -  state = STATE_REJECTED; -  result = value; -  cond->broadcast(); -  if( !sizeof(failure_cbs) && global_on_failure ) -  call_out(global_on_failure, 0, value); -  foreach(failure_cbs, -  [function(mixed, mixed ...: void) cb, -  array(mixed) extra]) { -  if (cb) { -  call_out(cb, 0, value, @extra); -  } -  } -  } -  +  //! @decl this_program failure(mixed value) +  //!    //! Reject the @[Future] value.    //!    //! @param value    //! Failure result of the @[Future].    //!    //! @throws    //! Throws an error if the @[Future] already has been fulfilled    //! or failed.    //!    //! Mark the @[Future] as failed, and schedule the @[on_failure()]    //! callbacks to be called as soon as possible.    //!    //! @seealso    //! @[try_failure()], @[success()], @[on_failure()] -  void failure(mixed value) +  this_program failure(mixed value, void|int try)    { -  if (state) error("Promise has already been finalised.\n"); -  Thread.MutexKey key = mux->lock(); -  if (state) error("Promise has already been finalised.\n"); -  unlocked_failure(value); -  key = 0; +  return +  finalise(STATE_REJECTED, value, try, failure_cbs, global_on_failure);    }       //! Maybe reject the @[Future] value.    //!    //! @param value    //! Failure result of the @[Future].    //!    //! Mark the @[Future] as failed if it hasn't already been fulfilled,    //! and in that case schedule the @[on_failure()] callbacks to be    //! called as soon as possible.    //!    //! @seealso    //! @[failure()], @[success()], @[on_failure()] -  void try_failure(mixed value) +  inline this_program try_failure(mixed value)    { -  if (state) return; -  Thread.MutexKey key = mux->lock(); -  if (state) return; -  unlocked_failure(value); +  return state ? this_program::this : failure(value, 1);    }       inline private void fill_astate() {    if (!_astate)    _astate = aggregate_state(this);    }       //! Add futures to the list of futures which the current object depends upon.    //!    //! If called without arguments it will produce a new @[Future]
pike.git/lib/modules/Concurrent.pmod:866:    //!    //! @seealso    //! @[depend()], @[max_failures()]    this_program any_results()    {    return max_failures(-1);    }       protected void _destruct()    { -  if (!state) { -  unlocked_failure(({ "Promise broken.\n", backtrace() })); +  if (!state) +  try_failure(({ "Promise broken.\n", backtrace() }));    }   } - } +       //! @returns   //! A @[Future] that represents the first   //! of the @expr{futures@} that completes.   //!   //! @seealso   //! @[race()], @[Promise.first_completed()]   variant Future first_completed(array(Future) futures)   {    return Promise()->depend(futures)->first_completed()->future();