Basic timer implementation; TODO: implement timer wheel

This commit is contained in:
Marko Budiselic 2016-04-23 20:45:01 +02:00
parent 4bf5636d24
commit b794187027
4 changed files with 163 additions and 2 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ memgraph
*.pyc
*.breakpoint
*.session.yaml
tags

View File

@ -3,9 +3,9 @@
#include "utils/command_line/arguments.hpp"
#include "utils/string/file.hpp"
std::string extract_query(const vector_str& arguments)
std::string extract_query(const std::vector<std::string>& arguments)
{
if (contain_argument(arguments, "-q"))
if (contains_argument(arguments, "-q"))
return get_argument(arguments, "-q", "CREATE (n) RETURN n");
auto default_file = "query.cypher";
auto file = get_argument(arguments, "-f", default_file);

29
test/unit/timer/main.cpp Normal file
View File

@ -0,0 +1,29 @@
#include <iostream>
#include <chrono>
// #define NOT_LOG_INFO
// compile this with: c++ -std=c++1y -o a.out -I../../../ -pthread main.cpp
#include "utils/log/logger.hpp"
#include "utils/timer/timer.hpp"
using namespace std::chrono_literals;
Timer::sptr create_test_timer(int64_t counter)
{
return std::make_shared<Timer>(
counter, [](){ LOG_INFO("Timer timeout"); }
);
}
int main(void)
{
TimerScheduler<TimerSet, std::chrono::seconds> timer_scheduler;
timer_scheduler.run();
for (int64_t i = 1; i <= 3; ++i) {
timer_scheduler.add(create_test_timer(i));
}
std::this_thread::sleep_for(10s);
timer_scheduler.add(create_test_timer(1));
return 0;
}

131
utils/timer/timer.hpp Normal file
View File

@ -0,0 +1,131 @@
#pragma once
#include <set>
#include <memory>
#include <chrono>
#include <thread>
#include "utils/log/logger.hpp"
/** @class Timer
* @brief The timer contains counter and handler.
*
* With every clock interval the counter should be decresed for
* delta count. Delta count is one for now but it should be a variable in the
* near future. The handler is function that will be called when counter
* becomes zero or smaller than zero.
*/
struct Timer
{
using sptr = std::shared_ptr<Timer>;
using handler_t = std::function<void(void)>;
Timer(int64_t counter, handler_t handler):
counter(counter), handler(handler)
{
}
bool operator--()
{
if (--counter <= 0)
return true;
else
return false;
}
int64_t counter;
handler_t handler;
};
/**
* Timer container knows how to add a new timer and remove the
* existing container from itself. Also, time container object
* has the process method whose responsibility is to iterate
* over existing timers and call the appropriate handler function.
* The handler method could be called on the same thread, on a
* separate thread or on a thread pool, that is implementation detail of
* the process method.
*/
/** @class TimerSet
* @brief Trivial timer container implementation.
*
* Internal data stucture for storage of timers is std::set. So, the
* related timer complexities are:
* insertion: O(log(n))
* deletion: O(log(n))
* process: O(n)
*/
class TimerSet
{
public:
void add(Timer::sptr timer)
{
timers.insert(timer);
}
void remove(Timer::sptr timer)
{
timers.erase(timer);
}
void process()
{
for (auto it = timers.begin(); it != timers.end(); ) {
auto timer = *it;
if (--*timer) {
timer->handler();
it = timers.erase(it);
continue;
}
++it;
}
}
private:
std::set<std::shared_ptr<Timer>> timers;
};
/** @class TimerScheduler
* @brief TimerScheduler is a manager class and its responsibility is to
* take care of the time and call the timer_container process method in the
* appropriate time.
*/
template <
typename timer_container_type,
typename delta_time_type,
uint64_t delta_time = 1
> class TimerScheduler
{
public:
void add(Timer::sptr timer)
{
timer_container.add(timer);
}
void remove(Timer::sptr timer)
{
timer_container.remove(timer);
}
void run()
{
run_thread = std::thread([this]() {
while (true) {
std::this_thread::sleep_for(delta_time_type(delta_time));
timer_container.process();
LOG_INFO("timer_container.process()");
}
});
}
~TimerScheduler()
{
run_thread.join();
}
private:
timer_container_type timer_container;
std::thread run_thread;
};