-/*
-This file is part of libmspframework
-Copyright © 2006 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
#ifndef MSP_TIME_TIMER_H_
#define MSP_TIME_TIMER_H_
-#include <set>
+#include <vector>
#include <sigc++/sigc++.h>
-#include "../core/mutex.h"
-#include "../core/semaphore.h"
-#include "../core/thread.h"
+#include <msp/core/mutex.h>
+#include <msp/core/semaphore.h>
#include "timedelta.h"
#include "timestamp.h"
namespace Time {
/**
-A class for executing functions periodically. Every time the timeout is
-reached, signal_timeout will be emitted. If the functor connected to this
-signal returns true, the timer is rescheduled by incrementing the timeout
-by the interval. Otherwise the timer is canceled.
+A class for executing functions in a deferred or periodical fashion. The add a
+timer, use one of the add functions and connect a functor to the timeout signal
+of the returned slot.
-A separate thread is used for running the timers. All signal emissions will
-happen in this thread - be careful with your variables.
+This class is thread-safe, to allow running timers in a separate thread.
*/
class Timer
{
public:
- sigc::signal<bool> signal_timeout;
-
- Timer(const Time::TimeDelta &);
- const Time::TimeStamp &get_timeout() const { return timeout; }
- ~Timer();
-private:
- /**
- A thread to run the timers independently of the rest of the program.
- */
- class Thread: public Msp::Thread
+ class Slot
{
public:
- Thread();
- void nudge();
- void finish();
+ sigc::signal<bool> signal_timeout;
+
private:
- bool done;
- Semaphore sem;
-
- void main();
+ TimeDelta interval;
+ TimeStamp timeout;
+
+ public:
+ Slot(const TimeDelta &);
+ Slot(const TimeStamp &);
+ const TimeStamp &get_timeout() const { return timeout; }
+ bool increment();
};
- /**
- Proxy class to handle automatic starting and termination of the thread.
- */
- class ThreadProxy
+private:
+ struct SlotProxy
{
- public:
- ThreadProxy(): thread(0) { }
- void nudge();
- ~ThreadProxy();
- private:
- Thread *thread;
+ Slot *slot;
+
+ SlotProxy(Slot *);
+ bool operator<(const SlotProxy &) const;
};
- Time::TimeDelta interval;
- Time::TimeStamp timeout;
+ std::vector<SlotProxy> slots;
+ Semaphore sem;
+ Mutex mutex;
+
+public:
+ ~Timer();
+
+ /** Adds a timer that will be executed periodically as long as the timeout
+ signal hander returns true. */
+ Slot &add(const TimeDelta &);
+
+ /** Adds a timer that will be executed once at a specific time. The return
+ value of the timeout signal handler is ignored. */
+ Slot &add(const TimeStamp &);
+
+ /** Cancels a previously added timer. */
+ void cancel(Slot &);
+
+ /** Checks all timers, executing any that have timed out. If block is true,
+ waits until one times out.
+
+ Note: If there are no active timers when a blocking tick is executed, it
+ won't return until a timer is added from another thread. */
+ void tick(bool block = true);
- static ThreadProxy thread;
- static Mutex set_mutex;
- static std::set<Timer *> timers;
+ TimeStamp get_next_timeout() const;
};
} // namespace Time