Exemple #1
0
//[asio_rr_suspend_until
    void suspend_until( std::chrono::steady_clock::time_point const& abs_time) noexcept {
        // Set a timer so at least one handler will eventually fire, causing
        // run_one() to eventually return. Set a timer even if abs_time ==
        // time_point::max() so the timer can be canceled by our notify()
        // method -- which calls the handler.
        if ( suspend_timer_.expires_at() != abs_time) {
            // Each expires_at(time_point) call cancels any previous pending
            // call. We could inadvertently spin like this:
            // dispatcher calls suspend_until() with earliest wake time
            // suspend_until() sets suspend_timer_
            // lambda loop calls run_one()
            // some other asio handler runs before timer expires
            // run_one() returns to lambda loop
            // lambda loop yields to dispatcher
            // dispatcher finds no ready fibers
            // dispatcher calls suspend_until() with SAME wake time
            // suspend_until() sets suspend_timer_ to same time, canceling
            // previous async_wait()
            // lambda loop calls run_one()
            // asio calls suspend_timer_ handler with operation_aborted
            // run_one() returns to lambda loop... etc. etc.
            // So only actually set the timer when we're passed a DIFFERENT
            // abs_time value.
            suspend_timer_.expires_at( abs_time);
            // It really doesn't matter what the suspend_timer_ handler does,
            // or even whether it's called because the timer ran out or was
            // canceled. The whole point is to cause the run_one() call to
            // return. So just pass a no-op lambda with proper signature.
            suspend_timer_.async_wait([](boost::system::error_code const&){});
        }
    }
Exemple #2
0
  void ScheduleExpire() {
    expire_timer.expires_from_now(std::chrono::minutes(5));
    expire_timer.async_wait([this](const boost::system::error_code &ec){
        if (ec)
          return;

        clients.Expire(expire_timer.expires_at() - std::chrono::minutes(10));
        if (!clients.empty())
          ScheduleExpire();
      });
  }
Exemple #3
0
//[asio_rr_notify
    void notify() noexcept {
        // Something has happened that should wake one or more fibers BEFORE
        // suspend_timer_ expires. Reset the timer to cause it to fire
        // immediately, causing the run_one() call to return. In theory we
        // could use cancel() because we don't care whether suspend_timer_'s
        // handler is called with operation_aborted or success. However --
        // cancel() doesn't change the expiration time, and we use
        // suspend_timer_'s expiration time to decide whether it's already
        // set. If suspend_until() set some specific wake time, then notify()
        // canceled it, then suspend_until() was called again with the same
        // wake time, it would match suspend_timer_'s expiration time and we'd
        // refrain from setting the timer. So instead of simply calling
        // cancel(), reset the timer, which cancels the pending sleep AND sets
        // a new expiration time. This will cause us to spin the loop twice --
        // once for the operation_aborted handler, once for timer expiration
        // -- but that shouldn't be a big problem.
        suspend_timer_.expires_at( std::chrono::steady_clock::now() );
    }
    // Only call on io_service
    void ResetTimer()
    {
        const auto now = std::chrono::steady_clock::now();

        UniqueLock unique_lock(mutex_);

        while (running_ && !data_.empty())
        {
            auto map_front_it = data_.begin();
            const auto timeout = map_front_it->first;
            if ( timeout <= now )
            {
                // Effeciently extract the value so we can move it.
                auto event = std::move( map_front_it->second );
                data_.erase(map_front_it);

                // Unlock incase callback calls a TimedActions method.
                unique_lock.unlock();
                event_processor_(std::move(event), std::error_code());
                unique_lock.lock();
            }
            else
            {
                timeout_timer_.expires_at(timeout);

                timeout_timer_.async_wait(
                    boost::bind(
                        &TimedEvents<Event>::HandleTimeout,
                        this->shared_from_this(),
                        boost::asio::placeholders::error
                    )
                );
                break;
            }
        }
    }