diff --git a/base/base.pro b/base/base.pro index 06587971b3..3925a464d6 100644 --- a/base/base.pro +++ b/base/base.pro @@ -29,6 +29,7 @@ SOURCES += \ strings_bundle.cpp \ string_format.cpp \ object_tracker.cpp \ + scheduled_task.cpp \ HEADERS += \ SRC_FIRST.hpp \ @@ -79,4 +80,5 @@ HEADERS += \ strings_bundle.hpp \ string_format.hpp \ object_tracker.hpp \ - regexp.hpp + regexp.hpp \ + scheduled_task.hpp \ diff --git a/base/base_tests/base_tests.pro b/base/base_tests/base_tests.pro index 0cb91f591d..09fcf9972d 100644 --- a/base/base_tests/base_tests.pro +++ b/base/base_tests/base_tests.pro @@ -35,7 +35,8 @@ SOURCES += \ containers_test.cpp \ fence_manager_test.cpp \ string_format_test.cpp \ - regexp_test.cpp + regexp_test.cpp \ + scheduled_task_test.cpp \ HEADERS += diff --git a/base/base_tests/scheduled_task_test.cpp b/base/base_tests/scheduled_task_test.cpp new file mode 100644 index 0000000000..934ae1e074 --- /dev/null +++ b/base/base_tests/scheduled_task_test.cpp @@ -0,0 +1,48 @@ +#include "../scheduled_task.hpp" +#include "../thread.hpp" +#include "../../testing/testing.hpp" +#include "../../std/bind.hpp" + +namespace +{ + void add_int(int & val, int a) + { + val += a; + } + + void mul_int(int & val, int b) + { + val *= b; + } +} + + +UNIT_TEST(ScheduledTask_Smoke) +{ + int val = 0; + + ScheduledTask t(bind(&add_int, ref(val), 10), 1000); + + CHECK(val == 0, ()); + + threads::Sleep(1100); + + CHECK(val == 10, ()); +} + +UNIT_TEST(ScheduledTask_Cancel) +{ + int val = 2; + + ScheduledTask t0(bind(&add_int, ref(val), 10), 500); + ScheduledTask t1(bind(&mul_int, ref(val), 2), 1000); + + CHECK(val == 2, ()); + + t0.Cancel(); + + threads::Sleep(1100); + + CHECK(val == 4, ()); +} + diff --git a/base/scheduled_task.cpp b/base/scheduled_task.cpp new file mode 100644 index 0000000000..da2ea3ad73 --- /dev/null +++ b/base/scheduled_task.cpp @@ -0,0 +1,24 @@ +#include "scheduled_task.hpp" + +ScheduledTask::Routine::Routine(fn_t const & fn, size_t ms) + : m_Fn(fn), m_Interval(ms) +{} + +void ScheduledTask::Routine::Do() +{ + m_Cond.Lock(); + m_Cond.Wait(m_Interval); + if (!IsCancelled()) + m_Fn(); + m_Cond.Unlock(); +} + +ScheduledTask::ScheduledTask(fn_t const & fn, size_t ms) +{ + m_Thread.Create(new Routine(fn, ms)); +} + +void ScheduledTask::Cancel() +{ + m_Thread.Cancel(); +} diff --git a/base/scheduled_task.hpp b/base/scheduled_task.hpp new file mode 100644 index 0000000000..92f9bd3e06 --- /dev/null +++ b/base/scheduled_task.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "../std/function.hpp" +#include "thread.hpp" +#include "condition.hpp" + +/// Class, which performs any function when the specified +/// amount of time is elapsed. +class ScheduledTask +{ +public: + + typedef function fn_t; + + class Routine : public threads::IRoutine + { + private: + fn_t m_Fn; + size_t m_Interval; + threads::Condition m_Cond; + public: + + Routine(fn_t const & fn, size_t ms); + + void Do(); + }; + +private: + + threads::Thread m_Thread; + +public: + + /// Constructor by function and time in miliseconds. + ScheduledTask(fn_t const& fn, size_t ms); + /// Task could be cancelled before time elapses. + void Cancel(); +};