diff --git a/.gitignore b/.gitignore index b6b54904e..a95175283 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ memgraph *.pyc *.breakpoint *.session.yaml +tags diff --git a/cypher/common.hpp b/cypher/common.hpp index c66fff3a6..7b9e905d4 100644 --- a/cypher/common.hpp +++ b/cypher/common.hpp @@ -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); diff --git a/test/unit/timer/main.cpp b/test/unit/timer/main.cpp new file mode 100644 index 000000000..244c9b91e --- /dev/null +++ b/test/unit/timer/main.cpp @@ -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; +} diff --git a/utils/timer/timer.hpp b/utils/timer/timer.hpp new file mode 100644 index 000000000..1e56cf8f2 --- /dev/null +++ b/utils/timer/timer.hpp @@ -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; +};