-/*
+/* $Id$
+
This file is part of libmspcore
-Copyright © 2006 Mikko Rasa, Mikkosoft Productions
+Copyright © 2006, 2009 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 "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;
+ TimeDelta interval;
+ TimeStamp timeout;
+
+ public:
+ Slot(const TimeDelta &);
+ Slot(const TimeStamp &);
+ const TimeStamp &get_timeout() const { return timeout; }
+ bool increment();
+ };
+
+private:
+ struct SlotProxy
+ {
+ Slot *slot;
- void main();
+ SlotProxy(Slot *);
+ bool operator<(const SlotProxy &) const;
};
+ std::vector<SlotProxy> slots;
+ Semaphore sem;
+ Mutex mutex;
+
+public:
+ ~Timer();
+
/**
- Proxy class to handle automatic starting and termination of the thread.
+ Adds a timer that will be executed periodically as long as the timeout
+ signal hander returns true.
*/
- class ThreadProxy
- {
- public:
- ThreadProxy(): thread(0) { }
- void nudge();
- ~ThreadProxy();
- private:
- Thread *thread;
- };
+ 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 &);
- Time::TimeDelta interval;
- Time::TimeStamp timeout;
+ /**
+ 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