blob: 4a49d55bc66b5e6d21131150a893c0bcb35cff1c [file] [log] [blame]
/*
* 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