pike.git / lib / modules / Concurrent.pmod

version» Context lines:

pike.git/lib/modules/Concurrent.pmod:15:   //! Value that will be provided asynchronously   //! sometime in the future.   //!   //! @seealso   //! @[Promise]   class Future   {    mixed result = UNDEFINED;    State state;    -  protected function(mixed:void) success_cb; -  protected array(mixed) success_ctx; -  protected function(mixed:void) failure_cb; -  protected array(mixed) failure_ctx; +  protected array(array(function(mixed, mixed ...: void)|array(mixed))) +  success_cbs = ({}); +  protected array(array(function(mixed, mixed ...: void)|array(mixed))) +  failure_cbs = ({});       //! Wait for fullfillment and return the value.    //!    //! @throws    //! Throws on rejection.    mixed get()    {    State s = state;    mixed res = result;    if (!s) {
pike.git/lib/modules/Concurrent.pmod:46:    key = 0;    }       if (s == STATE_REJECTED) {    throw(res);    }    return res;    }       //! Register a callback that is to be called on fulfillment. +  //! +  //! @param cb +  //! Function to be called. The first argument will be the +  //! result of the @[Future]. +  //! +  //! @param extra +  //! Any extra context needed for @[cb]. They will be provided +  //! as arguments two and onwards when @[cb] is called. +  //! +  //! @note +  //! @[cb] will always be called from the main backend. +  //! +  //! @seealso +  //! @[on_failure()]    this_program on_success(function(mixed, mixed ... : void) cb, mixed ... extra)    {    object key = mux->lock(); -  success_cb = cb; -  success_ctx = extra; -  State s = state; -  mixed res = result; +  +  if (state == STATE_FULFILLED) { +  call_out(cb, 0, result, @extra);    key = 0; -  if (s == STATE_FULFILLED) { -  call_out(cb, 0, res, @extra); +  return this;    }    -  +  success_cbs += ({ ({ cb, extra }) }); +  key = 0; +     return 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 +  //! Any extra context needed for @[cb]. They will be provided +  //! as arguments two and onwards when @[cb] is called. +  //! +  //! @note +  //! @[cb] will always be called from the main backend. +  //! +  //! @seealso +  //! @[on_success()]    this_program on_failure(function(mixed, mixed ... : void) cb, mixed ... extra)    {    object key = mux->lock(); -  failure_cb = cb; -  failure_ctx = extra; -  State s = state; -  mixed res = result; +  +  if (state == STATE_REJECTED) { +  call_out(cb, 0, result, @extra);    key = 0; -  if (s == STATE_REJECTED) { -  call_out(cb, 0, res, @extra); +  return this;    } -  +  +  failure_cbs += ({ ({ cb, extra }) }); +  key = 0; +     return 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:238:    //! by the fulfilled results of @[others].    //!    //! @seealso    //! @[results()]    this_program zip(this_program ... others)    {    if (!sizeof(others)) return this_program::this;    return results(({ this_program::this }) + others);    }    -  //! Return a @[Future] that will be failed when @[seconds] seconds has -  //! passed unless it has already been fullfilled. +  //! Return a @[Future] that will either be fulfilled with the fulfilled +  //! result of this @[Future], or be failed after @[seconds] have expired.    this_program timeout(int|float seconds)    {    Promise p = Promise();    on_failure(p->failure);    on_success(p->success);    call_out(p->maybe_failure, seconds, ({ "Timeout.\n", backtrace() }));    return p->future();    }   }   
pike.git/lib/modules/Concurrent.pmod:274:    Future future()    {    return Future::this;    }       protected void unlocked_success(mixed value)    {    if (state < STATE_REJECTED) {    result = value;    state = STATE_FULFILLED; -  function cb = success_cb; -  array(mixed) extra = success_ctx; +     cond->broadcast(); -  +  foreach(success_cbs, +  [function(mixed, mixed ...: void) cb, +  array(mixed) extra]) {    if (cb) {    call_out(cb, 0, value, @extra);    }    }    } -  +  }    -  //! Fulfill the @[Future] value. +  //! Fulfill the @[Future]. +  //! +  //! @param value +  //! Result of the @[Future]. +  //! +  //! Mark the @[Future] as fulfilled if it hasn't already been failed, +  //! and schedule the @[on_success()] callbacks to be called as soon +  //! as possible. +  //! +  //! @seealso +  //! @[maybe_failure()], @[failure()], @[on_success()]    void success(mixed value)    {    object key = mux->lock();    unlocked_success(value);    key = 0;    }       protected void unlocked_failure(mixed value)    {    state = STATE_REJECTED;    result = value; -  function cb = failure_cb; -  array(mixed) extra = failure_ctx; +     cond->broadcast(); -  +  foreach(failure_cbs, +  [function(mixed, mixed ...: void) cb, +  array(mixed) extra]) {    if (cb) {    call_out(cb, 0, value, @extra);    }    } -  +  }       //! Reject the @[Future] value. -  +  //! +  //! @param value +  //! Failure result of the @[Future]. +  //! +  //! Mark the @[Future] as failed, and schedule the @[on_failure()] +  //! callbacks to be called as soon as possible. +  //! +  //! @seealso +  //! @[maybe_failure()], @[success()], @[on_failure()]    void failure(mixed value)    {    object key = mux->lock();    unlocked_failure(value);    key = 0;    }    -  //! Reject the @[Future] value unless it has already been fulfilled. +  //! 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 schedule the @[on_failure()] callbacks to be called as soon +  //! as possible. +  //! +  //! @seealso +  //! @[failure()], @[success()], @[on_failure()]    void maybe_failure(mixed value)    {    object key = mux->lock();    if (state) return;    unlocked_failure(value);    }       protected void destroy()    {    if (!state) {