mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-26 18:42:41 +01:00
improved Lambda support
This commit is contained in:
@@ -154,12 +154,19 @@ public:
|
|||||||
/// Starts the thread with the given target and parameter.
|
/// Starts the thread with the given target and parameter.
|
||||||
|
|
||||||
template <class Functor>
|
template <class Functor>
|
||||||
void startFunc(Functor fn)
|
void startFunc(const Functor& fn)
|
||||||
/// Starts the thread with the given functor object or lambda.
|
/// Starts the thread with the given functor object or lambda.
|
||||||
{
|
{
|
||||||
startImpl(new FunctorRunnable<Functor>(fn));
|
startImpl(new FunctorRunnable<Functor>(fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Functor>
|
||||||
|
void startFunc(Functor&& fn)
|
||||||
|
/// Starts the thread with the given functor object or lambda.
|
||||||
|
{
|
||||||
|
startImpl(new FunctorRunnable<Functor>(std::move(fn)));
|
||||||
|
}
|
||||||
|
|
||||||
void join();
|
void join();
|
||||||
/// Waits until the thread completes execution.
|
/// Waits until the thread completes execution.
|
||||||
/// If multiple threads try to join the same
|
/// If multiple threads try to join the same
|
||||||
@@ -242,6 +249,11 @@ protected:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FunctorRunnable(Functor&& functor):
|
||||||
|
_functor(std::move(functor))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~FunctorRunnable()
|
~FunctorRunnable()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
MyRunnable(): _ran(false)
|
MyRunnable(): _ran(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
Thread* pThread = Thread::current();
|
Thread* pThread = Thread::current();
|
||||||
@@ -45,22 +45,22 @@ public:
|
|||||||
_ran = true;
|
_ran = true;
|
||||||
_event.wait();
|
_event.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ran() const
|
bool ran() const
|
||||||
{
|
{
|
||||||
return _ran;
|
return _ran;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& threadName() const
|
const std::string& threadName() const
|
||||||
{
|
{
|
||||||
return _threadName;
|
return _threadName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify()
|
void notify()
|
||||||
{
|
{
|
||||||
_event.set();
|
_event.set();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void staticFunc()
|
static void staticFunc()
|
||||||
{
|
{
|
||||||
++_staticVar;
|
++_staticVar;
|
||||||
@@ -96,17 +96,17 @@ public:
|
|||||||
NonJoinRunnable() : _finished(false)
|
NonJoinRunnable() : _finished(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
_finished = true;
|
_finished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool finished() const
|
bool finished() const
|
||||||
{
|
{
|
||||||
return _finished;
|
return _finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _finished;
|
bool _finished;
|
||||||
};
|
};
|
||||||
@@ -264,12 +264,12 @@ void ThreadTest::testNotJoin()
|
|||||||
Thread thread;
|
Thread thread;
|
||||||
NonJoinRunnable r;
|
NonJoinRunnable r;
|
||||||
thread.start(r);
|
thread.start(r);
|
||||||
|
|
||||||
while (!r.finished())
|
while (!r.finished())
|
||||||
{
|
{
|
||||||
Thread::sleep(10);
|
Thread::sleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::sleep(100);
|
Thread::sleep(100);
|
||||||
assertTrue (!thread.isRunning());
|
assertTrue (!thread.isRunning());
|
||||||
}
|
}
|
||||||
@@ -383,20 +383,19 @@ void ThreadTest::testThreadFunctor()
|
|||||||
|
|
||||||
assertTrue (!thread.isRunning());
|
assertTrue (!thread.isRunning());
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
|
||||||
|
|
||||||
Thread thread2;
|
Thread thread2;
|
||||||
|
|
||||||
assertTrue (!thread2.isRunning());
|
assertTrue (!thread2.isRunning());
|
||||||
|
|
||||||
MyRunnable::_staticVar = 0;
|
MyRunnable::_staticVar = 0;
|
||||||
thread.startFunc([] () {MyRunnable::_staticVar++;});
|
thread.startFunc([] ()
|
||||||
|
{
|
||||||
|
MyRunnable::_staticVar++;
|
||||||
|
});
|
||||||
thread.join();
|
thread.join();
|
||||||
assertTrue (1 == MyRunnable::_staticVar);
|
assertTrue (1 == MyRunnable::_staticVar);
|
||||||
|
|
||||||
assertTrue (!thread2.isRunning());
|
assertTrue (!thread2.isRunning());
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ namespace Util {
|
|||||||
|
|
||||||
|
|
||||||
class Util_API Timer: protected Poco::Runnable
|
class Util_API Timer: protected Poco::Runnable
|
||||||
/// A Timer allows to schedule tasks (TimerTask objects) for future execution
|
/// A Timer allows to schedule tasks (TimerTask objects) for future execution
|
||||||
/// in a background thread. Tasks may be scheduled for one-time execution,
|
/// in a background thread. Tasks may be scheduled for one-time execution,
|
||||||
/// or for repeated execution at regular intervals.
|
/// or for repeated execution at regular intervals.
|
||||||
///
|
///
|
||||||
/// The Timer object creates a thread that executes all scheduled tasks
|
/// The Timer object creates a thread that executes all scheduled tasks
|
||||||
/// sequentially. Therefore, tasks should complete their work as quickly
|
/// sequentially. Therefore, tasks should complete their work as quickly
|
||||||
@@ -41,20 +41,29 @@ class Util_API Timer: protected Poco::Runnable
|
|||||||
/// Timer is safe for multithreaded use - multiple threads can schedule
|
/// Timer is safe for multithreaded use - multiple threads can schedule
|
||||||
/// new tasks simultaneously.
|
/// new tasks simultaneously.
|
||||||
///
|
///
|
||||||
|
/// Via the func() helper function template, a functor or
|
||||||
|
/// lambda can be used as timer task:
|
||||||
|
///
|
||||||
|
/// timer.schedule(Timer::func([]()
|
||||||
|
/// {
|
||||||
|
/// std::cout << "Timer!\n";
|
||||||
|
/// }),
|
||||||
|
/// Poco::Clock());
|
||||||
|
///
|
||||||
/// Acknowledgement: The interface of this class has been inspired by
|
/// Acknowledgement: The interface of this class has been inspired by
|
||||||
/// the java.util.Timer class from Java 1.3.
|
/// the java.util.Timer class from Java 1.3.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Timer();
|
Timer();
|
||||||
/// Creates the Timer.
|
/// Creates the Timer.
|
||||||
|
|
||||||
explicit Timer(Poco::Thread::Priority priority);
|
explicit Timer(Poco::Thread::Priority priority);
|
||||||
/// Creates the Timer, using a timer thread with
|
/// Creates the Timer, using a timer thread with
|
||||||
/// the given priority.
|
/// the given priority.
|
||||||
|
|
||||||
~Timer();
|
~Timer();
|
||||||
/// Destroys the Timer, cancelling all pending tasks.
|
/// Destroys the Timer, cancelling all pending tasks.
|
||||||
|
|
||||||
void cancel(bool wait = false);
|
void cancel(bool wait = false);
|
||||||
/// Cancels all pending tasks.
|
/// Cancels all pending tasks.
|
||||||
///
|
///
|
||||||
@@ -65,7 +74,7 @@ public:
|
|||||||
/// task queue will be purged as soon as the currently
|
/// task queue will be purged as soon as the currently
|
||||||
/// running task finishes. If wait is true, waits
|
/// running task finishes. If wait is true, waits
|
||||||
/// until the queue has been purged.
|
/// until the queue has been purged.
|
||||||
|
|
||||||
void schedule(TimerTask::Ptr pTask, Poco::Timestamp time);
|
void schedule(TimerTask::Ptr pTask, Poco::Timestamp time);
|
||||||
/// Schedules a task for execution at the specified time.
|
/// Schedules a task for execution at the specified time.
|
||||||
///
|
///
|
||||||
@@ -84,7 +93,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// If the time lies in the past, the task is executed
|
/// If the time lies in the past, the task is executed
|
||||||
/// immediately.
|
/// immediately.
|
||||||
|
|
||||||
void schedule(TimerTask::Ptr pTask, long delay, long interval);
|
void schedule(TimerTask::Ptr pTask, long delay, long interval);
|
||||||
/// Schedules a task for periodic execution.
|
/// Schedules a task for periodic execution.
|
||||||
///
|
///
|
||||||
@@ -112,12 +121,12 @@ public:
|
|||||||
/// The task is first executed at the given time.
|
/// The task is first executed at the given time.
|
||||||
/// Subsequently, the task is executed periodically with
|
/// Subsequently, the task is executed periodically with
|
||||||
/// the given interval in milliseconds between invocations.
|
/// the given interval in milliseconds between invocations.
|
||||||
|
|
||||||
void scheduleAtFixedRate(TimerTask::Ptr pTask, long delay, long interval);
|
void scheduleAtFixedRate(TimerTask::Ptr pTask, long delay, long interval);
|
||||||
/// Schedules a task for periodic execution at a fixed rate.
|
/// Schedules a task for periodic execution at a fixed rate.
|
||||||
///
|
///
|
||||||
/// The task is first executed after the given delay.
|
/// The task is first executed after the given delay.
|
||||||
/// Subsequently, the task is executed periodically
|
/// Subsequently, the task is executed periodically
|
||||||
/// every number of milliseconds specified by interval.
|
/// every number of milliseconds specified by interval.
|
||||||
///
|
///
|
||||||
/// If task execution takes longer than the given interval,
|
/// If task execution takes longer than the given interval,
|
||||||
@@ -127,7 +136,7 @@ public:
|
|||||||
/// Schedules a task for periodic execution at a fixed rate.
|
/// Schedules a task for periodic execution at a fixed rate.
|
||||||
///
|
///
|
||||||
/// The task is first executed at the given time.
|
/// The task is first executed at the given time.
|
||||||
/// Subsequently, the task is executed periodically
|
/// Subsequently, the task is executed periodically
|
||||||
/// every number of milliseconds specified by interval.
|
/// every number of milliseconds specified by interval.
|
||||||
///
|
///
|
||||||
/// If task execution takes longer than the given interval,
|
/// If task execution takes longer than the given interval,
|
||||||
@@ -144,20 +153,36 @@ public:
|
|||||||
/// Schedules a task for periodic execution at a fixed rate.
|
/// Schedules a task for periodic execution at a fixed rate.
|
||||||
///
|
///
|
||||||
/// The task is first executed at the given time.
|
/// The task is first executed at the given time.
|
||||||
/// Subsequently, the task is executed periodically
|
/// Subsequently, the task is executed periodically
|
||||||
/// every number of milliseconds specified by interval.
|
/// every number of milliseconds specified by interval.
|
||||||
///
|
///
|
||||||
/// If task execution takes longer than the given interval,
|
/// If task execution takes longer than the given interval,
|
||||||
/// further executions are delayed.
|
/// further executions are delayed.
|
||||||
|
|
||||||
|
template <typename Fn>
|
||||||
|
static TimerTask::Ptr func(const Fn& fn)
|
||||||
|
/// Helper function template to use a functor or lambda
|
||||||
|
/// with Timer::schedule() and Timer::scheduleAtFixedRate().
|
||||||
|
{
|
||||||
|
return new TimerFunc<Fn>(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Fn>
|
||||||
|
static TimerTask::Ptr func(Fn&& fn)
|
||||||
|
/// Helper function template to use a functor or lambda
|
||||||
|
/// with Timer::schedule() and Timer::scheduleAtFixedRate().
|
||||||
|
{
|
||||||
|
return new TimerFunc<Fn>(std::move(fn));
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void run();
|
void run();
|
||||||
static void validateTask(const TimerTask::Ptr& pTask);
|
static void validateTask(const TimerTask::Ptr& pTask);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Timer(const Timer&);
|
Timer(const Timer&);
|
||||||
Timer& operator = (const Timer&);
|
Timer& operator = (const Timer&);
|
||||||
|
|
||||||
Poco::TimedNotificationQueue _queue;
|
Poco::TimedNotificationQueue _queue;
|
||||||
Poco::Thread _thread;
|
Poco::Thread _thread;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Util {
|
|||||||
|
|
||||||
|
|
||||||
class Util_API TimerTask: public Poco::RefCountedObject, public Poco::Runnable
|
class Util_API TimerTask: public Poco::RefCountedObject, public Poco::Runnable
|
||||||
/// A task that can be scheduled for one-time or
|
/// A task that can be scheduled for one-time or
|
||||||
/// repeated execution by a Timer.
|
/// repeated execution by a Timer.
|
||||||
///
|
///
|
||||||
/// This is an abstract class. Subclasses must override the run() member
|
/// This is an abstract class. Subclasses must override the run() member
|
||||||
@@ -38,45 +38,71 @@ class Util_API TimerTask: public Poco::RefCountedObject, public Poco::Runnable
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Ptr = Poco::AutoPtr<TimerTask>;
|
using Ptr = Poco::AutoPtr<TimerTask>;
|
||||||
|
|
||||||
TimerTask();
|
TimerTask();
|
||||||
/// Creates the TimerTask.
|
/// Creates the TimerTask.
|
||||||
|
|
||||||
void cancel();
|
void cancel();
|
||||||
/// Cancels the execution of the timer.
|
/// Cancels the execution of the timer.
|
||||||
/// If the task has been scheduled for one-time execution and has
|
/// If the task has been scheduled for one-time execution and has
|
||||||
/// not yet run, or has not yet been scheduled, it will never run.
|
/// not yet run, or has not yet been scheduled, it will never run.
|
||||||
/// If the task has been scheduled for repeated execution, it will never
|
/// If the task has been scheduled for repeated execution, it will never
|
||||||
/// run again. If the task is running when this call occurs, the task
|
/// run again. If the task is running when this call occurs, the task
|
||||||
/// will run to completion, but will never run again.
|
/// will run to completion, but will never run again.
|
||||||
///
|
///
|
||||||
/// Warning: A TimerTask that has been cancelled must not be scheduled again.
|
/// Warning: A TimerTask that has been cancelled must not be scheduled again.
|
||||||
/// An attempt to do so results in a Poco::Util::IllegalStateException being thrown.
|
/// An attempt to do so results in a Poco::Util::IllegalStateException being thrown.
|
||||||
|
|
||||||
bool isCancelled() const;
|
bool isCancelled() const;
|
||||||
/// Returns true iff the TimerTask has been cancelled by a call
|
/// Returns true iff the TimerTask has been cancelled by a call
|
||||||
/// to cancel().
|
/// to cancel().
|
||||||
|
|
||||||
Poco::Timestamp lastExecution() const;
|
Poco::Timestamp lastExecution() const;
|
||||||
/// Returns the time of the last execution of the timer task.
|
/// Returns the time of the last execution of the timer task.
|
||||||
///
|
///
|
||||||
/// Returns 0 if the timer has never been executed.
|
/// Returns 0 if the timer has never been executed.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~TimerTask();
|
~TimerTask();
|
||||||
/// Destroys the TimerTask.
|
/// Destroys the TimerTask.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TimerTask(const TimerTask&);
|
TimerTask(const TimerTask&);
|
||||||
TimerTask& operator = (const TimerTask&);
|
TimerTask& operator = (const TimerTask&);
|
||||||
|
|
||||||
Poco::Timestamp _lastExecution;
|
Poco::Timestamp _lastExecution;
|
||||||
bool _isCancelled;
|
bool _isCancelled;
|
||||||
|
|
||||||
friend class TaskNotification;
|
friend class TaskNotification;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Fn>
|
||||||
|
class TimerFunc: public TimerTask
|
||||||
|
/// A simple adapter that allows using a functor or lambda
|
||||||
|
/// with Poco::Util::Timer, used by timerFunc().
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TimerFunc(const Fn& fn):
|
||||||
|
_fn(fn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit TimerFunc(Fn&& fn):
|
||||||
|
_fn(std::move(fn))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
_fn();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Fn _fn;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// inlines
|
// inlines
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -260,6 +260,21 @@ void TimerTest::testCancelAllWaitStop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TimerTest::testFunc()
|
||||||
|
{
|
||||||
|
Timer timer;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
timer.schedule(Timer::func([&count]()
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}), Poco::Clock());
|
||||||
|
Poco::Thread::sleep(100);
|
||||||
|
|
||||||
|
assertTrue (count == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TimerTest::setUp()
|
void TimerTest::setUp()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -290,6 +305,7 @@ CppUnit::Test* TimerTest::suite()
|
|||||||
CppUnit_addTest(pSuite, TimerTest, testCancel);
|
CppUnit_addTest(pSuite, TimerTest, testCancel);
|
||||||
CppUnit_addTest(pSuite, TimerTest, testCancelAllStop);
|
CppUnit_addTest(pSuite, TimerTest, testCancelAllStop);
|
||||||
CppUnit_addTest(pSuite, TimerTest, testCancelAllWaitStop);
|
CppUnit_addTest(pSuite, TimerTest, testCancelAllWaitStop);
|
||||||
|
CppUnit_addTest(pSuite, TimerTest, testFunc);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public:
|
|||||||
void testCancel();
|
void testCancel();
|
||||||
void testCancelAllStop();
|
void testCancelAllStop();
|
||||||
void testCancelAllWaitStop();
|
void testCancelAllWaitStop();
|
||||||
|
void testFunc();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
|||||||
Reference in New Issue
Block a user