| /* |
| * Copyright 2015 Nest Labs, Inc. All Rights Reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <folly/futures/detail/TimerMap.h> |
| #include <iterator> |
| #include <vector> |
| |
| using std::make_tuple; |
| using std::forward_as_tuple; |
| |
| namespace folly { namespace detail { |
| |
| /** |
| * Constructs a TimerMap with a predefined tick |
| * |
| * Creates an empty TimerMap with a specific tick. The tick is the |
| * minimum amount of time between timestamps returned by |
| * nextTimeout(). The intention is that the caller will only call |
| * invokeTimers() at these times. |
| */ |
| TimerMap::TimerMap(TimerMap::duration_type tick) : |
| tick_(tick), |
| next_tick_(TimerMap::clock_type::now()), |
| db_() |
| { |
| } |
| |
| /** |
| * Add a callback that should fire after a delay |
| * |
| * @param timeout The amount of time to delay before executing the |
| * callback. |
| * |
| * @param cb The callback/closure to execute. |
| * |
| * Note: this is a convenience function for |
| * scheduleAlarm(clock_type::now() + timeout, cb) |
| */ |
| void TimerMap::scheduleTimeout(TimerMap::duration_type timeout, |
| TimerMap::callback_type cb) |
| { |
| auto t0 = clock_type::now(); |
| auto t1 = t0 + timeout; |
| scheduleAlarm(t1, std::move(cb)); |
| } |
| |
| /** |
| * Add a callback that should fire at a specific time |
| * |
| * @param timeout The exact time when the callback should fire. |
| * |
| * @param cb The callback/closure to execute |
| */ |
| void TimerMap::scheduleAlarm(TimerMap::time_point_type timeout, |
| TimerMap::callback_type cb) |
| { |
| db_.emplace(std::piecewise_construct_t(), |
| make_tuple(timeout), |
| forward_as_tuple(std::move(cb))); |
| } |
| |
| /** |
| * Return the absolute time point when the next batch of callbacks should fire |
| * |
| * In the interest of efficiency, it's usually better to group the |
| * callback by 'tick'. Most timers do not need extremely high |
| * precision. Therefore, the nextTimeout() returns the timepoint when |
| * the next 'tick' expires (and thus you should call invokeTimers()). |
| * |
| * @return The absolute time when the invokeTimers() should next be |
| * called. The time returned may be in the past (meaning you should |
| * call it ASAP). |
| */ |
| TimerMap::time_point_type TimerMap::nextTimeout() const |
| { |
| return next_tick_; |
| } |
| |
| /** |
| * Execute all callbacks that have expired and remove them. |
| * |
| * This is a convenience function for SINGLE-THREADED applications |
| * (like unit tests). Do not use this if you are protecting TimerMap |
| * with any kind of lock. |
| * |
| * Usually you will be using this in a multithreaded environment, and |
| * you will have a mutex that protects this TimerMap instance. You |
| * will need to hold the lock when you call this function. However, |
| * you will want that lock to be RELEASED when the callbacks execute. |
| * This function gives you no way to do that. Instead, you should call |
| * popExpiredTimers() and invokeTimers(beg, end). |
| */ |
| void TimerMap::invokeTimers() |
| { |
| std::vector<data_type> vec; |
| |
| popExpiredTimers(std::inserter(vec, vec.begin())); |
| invokeTimers(vec.begin(), vec.end()); |
| } |
| |
| } // namespace detail |
| } // namespace folly |