pike.git / lib / modules / Concurrent.pmod

version» Context lines:

pike.git/lib/modules/Concurrent.pmod:3:   //! Module for handling multiple concurrent events.   //!   //! The @[Future] and @[Promise] API was inspired by   //! @url{https://github.com/couchdeveloper/FutureLib@}.      local protected enum State {    STATE_NO_FUTURE = -1,    STATE_PENDING = 0,    STATE_FULFILLED,    STATE_REJECTED, +  STATE_REJECTION_REPORTED,   };      protected Thread.Mutex mux = Thread.Mutex();   protected Thread.Condition cond = Thread.Condition();      //! Global failure callback, called when a promise without failure   //! callback fails. This is useful to log exceptions, so they are not   //! just silently caught and ignored.   void on_failure(function(mixed : void) f)   {
pike.git/lib/modules/Concurrent.pmod:185:    if (!s) {    Thread.MutexKey key = mux->lock();    while (state <= STATE_PENDING) {    cond->wait(key);    }       s = state;    res = result;    }    -  if (s == STATE_REJECTED) { +  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].
pike.git/lib/modules/Concurrent.pmod:240:    //!    //! @note    //! @[cb] will always be called from the main backend.    //!    //! @seealso    //! @[on_success()]    this_program on_failure(function(mixed, mixed ... : void) cb, mixed ... extra)    {    switch (state) {    case STATE_REJECTED: +  state = STATE_REJECTION_REPORTED; +  // FALL_THROUGH +  case STATE_REJECTION_REPORTED:    call_callback(cb, result, @extra);    break;    case STATE_NO_FUTURE:    case STATE_PENDING:    // Rely on interpreter lock to add to failure_cbs before state changes    // again    failure_cbs += ({ ({ cb, @extra }) });    }    return this_program::this;    }
pike.git/lib/modules/Concurrent.pmod:670:    (p->try_failure, seconds, ({ "Timeout.\n", backtrace() }));    return p->future();    }       protected string _sprintf(int t)    {    return t=='O' && sprintf("%O(%s,%O)", this_program,    ([ STATE_NO_FUTURE : "no future",    STATE_PENDING : "pending",    STATE_REJECTED : "rejected", +  STATE_REJECTION_REPORTED : "rejection_reported",    STATE_FULFILLED : "fulfilled" ])[state],    result);    }   }      protected class AggregateState   {    private Promise promise;    private int(0..) promises;    private int(0..) succeeded, failed;
pike.git/lib/modules/Concurrent.pmod:854:    }       //! The future value that we promise.    Future future()    {    if (state == STATE_NO_FUTURE) state = STATE_PENDING;    return Future::this;    }       protected this_program finalise(State newstate, mixed value, int try, -  array(array(function(mixed, mixed ...: void)|array(mixed))) cbs, -  void|function(mixed : void) globalfailure) +  array(array(function(mixed, mixed ...: void)|array(mixed))) cbs)    {    Thread.MutexKey key = mux->lock();    if (state <= STATE_PENDING)    {    state = newstate;    result = value;    key = 0;    cond->broadcast();    if (sizeof(cbs))    {    foreach(cbs; ; array cb)    if (cb)    call_callback(cb[0], value, @cb[1..]); -  +  if (newstate == STATE_REJECTED) { +  state = STATE_REJECTION_REPORTED;    } -  else if (globalfailure) -  call_callback(globalfailure, value); +  }    failure_cbs = success_cbs = 0; // Free memory and references    }    else    {    key = 0;    if (!try)    error("Promise has already been finalised.\n");    }    return this_program::this;    }
pike.git/lib/modules/Concurrent.pmod:939:    //! 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()]    this_program failure(mixed value, void|int try)    {    return -  finalise(STATE_REJECTED, value, try, failure_cbs, global_on_failure); +  finalise(STATE_REJECTED, value, try, failure_cbs);    }       //! 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.
pike.git/lib/modules/Concurrent.pmod:1119:    this_program any_results()    {    return max_failures(-1);    }       protected void _destruct()    {    // NB: Don't complain about dropping STATE_NO_FUTURE on the floor.    if (state == STATE_PENDING)    try_failure(({ "Promise broken.\n", backtrace() })); +  if ((state == STATE_REJECTED) && global_on_failure) +  call_callback(global_on_failure, result); +  result = UNDEFINED;    }   }      //! @returns   //! A @[Future] that represents the first   //! of the @expr{futures@} that completes.   //!   //! @note   //! The returned @[Future] does NOT have any state (eg backend)   //! propagated from the @[futures]. This must be done by hand.