From e1ea831a640fba534e7e42e399f04cdf681ef8d3 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 28 Aug 2006 07:59:47 +0000 Subject: [PATCH] Rename to libmspcore Combine with libmsptime --- Package | 4 +- source/Module | 4 - source/core/Module | 5 ++ source/{ => core}/application.cpp | 0 source/{ => core}/application.h | 0 source/{ => core}/error.h | 0 source/{ => core}/event.cpp | 0 source/{ => core}/event.h | 0 source/{ => core}/main.cpp | 0 source/{ => core}/mutex.h | 0 source/{ => core}/pollable.cpp | 0 source/{ => core}/pollable.h | 0 source/{ => core}/poller.cpp | 0 source/{ => core}/poller.h | 0 source/core/semaphore.cpp | 33 +++++++++ source/core/semaphore.h | 34 +++++++++ source/{ => core}/thread.cpp | 0 source/{ => core}/thread.h | 0 source/{ => core}/types.h | 0 source/{ => core}/win32poll.h | 0 source/semaphore.h | 30 -------- source/time/Module | 1 + source/time/timedelta.cpp | 99 +++++++++++++++++++++++++ source/time/timedelta.h | 83 +++++++++++++++++++++ source/time/timer.cpp | 119 ++++++++++++++++++++++++++++++ source/time/timer.h | 78 ++++++++++++++++++++ source/time/timestamp.h | 62 ++++++++++++++++ source/time/units.cpp | 21 ++++++ source/time/units.h | 25 +++++++ source/time/utils.cpp | 52 +++++++++++++ source/time/utils.h | 22 ++++++ 31 files changed, 636 insertions(+), 36 deletions(-) delete mode 100644 source/Module create mode 100644 source/core/Module rename source/{ => core}/application.cpp (100%) rename source/{ => core}/application.h (100%) rename source/{ => core}/error.h (100%) rename source/{ => core}/event.cpp (100%) rename source/{ => core}/event.h (100%) rename source/{ => core}/main.cpp (100%) rename source/{ => core}/mutex.h (100%) rename source/{ => core}/pollable.cpp (100%) rename source/{ => core}/pollable.h (100%) rename source/{ => core}/poller.cpp (100%) rename source/{ => core}/poller.h (100%) create mode 100644 source/core/semaphore.cpp create mode 100644 source/core/semaphore.h rename source/{ => core}/thread.cpp (100%) rename source/{ => core}/thread.h (100%) rename source/{ => core}/types.h (100%) rename source/{ => core}/win32poll.h (100%) delete mode 100644 source/semaphore.h create mode 100644 source/time/Module create mode 100644 source/time/timedelta.cpp create mode 100644 source/time/timedelta.h create mode 100644 source/time/timer.cpp create mode 100644 source/time/timer.h create mode 100644 source/time/timestamp.h create mode 100644 source/time/units.cpp create mode 100644 source/time/units.h create mode 100644 source/time/utils.cpp create mode 100644 source/time/utils.h diff --git a/Package b/Package index 70efd84..42d52e4 100644 --- a/Package +++ b/Package @@ -1,5 +1,5 @@ -package="mspframework" +package="mspcore" version="0.1" -description="Mikkosoft Productions application framework library" +description="Mikkosoft Productions core library" requires=("mspmisc","pthread","sigc++-2.0") tarballfile=("License.txt",) diff --git a/source/Module b/source/Module deleted file mode 100644 index 8e1936d..0000000 --- a/source/Module +++ /dev/null @@ -1,4 +0,0 @@ -type="library" -target="mspframework" -installheaders="framework" -installtarget=1 diff --git a/source/core/Module b/source/core/Module new file mode 100644 index 0000000..536d2d4 --- /dev/null +++ b/source/core/Module @@ -0,0 +1,5 @@ +type="library" +target="mspcore" +extradirs=("time",) +installheaders="core" +installtarget=1 diff --git a/source/application.cpp b/source/core/application.cpp similarity index 100% rename from source/application.cpp rename to source/core/application.cpp diff --git a/source/application.h b/source/core/application.h similarity index 100% rename from source/application.h rename to source/core/application.h diff --git a/source/error.h b/source/core/error.h similarity index 100% rename from source/error.h rename to source/core/error.h diff --git a/source/event.cpp b/source/core/event.cpp similarity index 100% rename from source/event.cpp rename to source/core/event.cpp diff --git a/source/event.h b/source/core/event.h similarity index 100% rename from source/event.h rename to source/core/event.h diff --git a/source/main.cpp b/source/core/main.cpp similarity index 100% rename from source/main.cpp rename to source/core/main.cpp diff --git a/source/mutex.h b/source/core/mutex.h similarity index 100% rename from source/mutex.h rename to source/core/mutex.h diff --git a/source/pollable.cpp b/source/core/pollable.cpp similarity index 100% rename from source/pollable.cpp rename to source/core/pollable.cpp diff --git a/source/pollable.h b/source/core/pollable.h similarity index 100% rename from source/pollable.h rename to source/core/pollable.h diff --git a/source/poller.cpp b/source/core/poller.cpp similarity index 100% rename from source/poller.cpp rename to source/core/poller.cpp diff --git a/source/poller.h b/source/core/poller.h similarity index 100% rename from source/poller.h rename to source/core/poller.h diff --git a/source/core/semaphore.cpp b/source/core/semaphore.cpp new file mode 100644 index 0000000..9139ce1 --- /dev/null +++ b/source/core/semaphore.cpp @@ -0,0 +1,33 @@ +/* +This file is part of libmspframework +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ +#include +#include +#include "semaphore.h" +#include "../time/timestamp.h" +#include "../time/utils.h" + +namespace Msp { + +#ifndef WIN32 +int Semaphore::wait(const Time::TimeDelta &d) +{ + Time::TimeStamp ts=Time::now()+d; + + timespec timeout; + timeout.tv_sec=ts.raw()/1000000; + timeout.tv_nsec=(ts.raw()%1000000)*1000; + + MutexLock l(mutex); + int r=pthread_cond_timedwait(&cond, &mutex.mutex, &timeout); + if(r==ETIMEDOUT) + return 1; + else if(r) + return -1; + return 0; +} +#endif + +} // namespace Msp diff --git a/source/core/semaphore.h b/source/core/semaphore.h new file mode 100644 index 0000000..75c51e6 --- /dev/null +++ b/source/core/semaphore.h @@ -0,0 +1,34 @@ +/* +This file is part of libmspframework +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ +#ifndef MSP_FRAMEWORK_SEMAPHORE_H_ +#define MSP_FRAMEWORK_SEMAPHORE_H_ + +#include +#include "mutex.h" +#include "../time/timedelta.h" + +namespace Msp { + +class Semaphore +{ +public: +#ifndef WIN32 + Semaphore() { pthread_cond_init(&cond, 0); } + //Mutex &get_mutex() { return mutex; } + int signal() { MutexLock l(mutex); return pthread_cond_signal(&cond); } + int broadcast() { MutexLock l(mutex); return pthread_cond_broadcast(&cond); } + int wait() { mutex.lock(); return pthread_cond_wait(&cond, &mutex.mutex); } + int wait(const Time::TimeDelta &); + ~Semaphore() { pthread_cond_destroy(&cond); } +#endif +private: + Mutex mutex; + pthread_cond_t cond; +}; + +} + +#endif diff --git a/source/thread.cpp b/source/core/thread.cpp similarity index 100% rename from source/thread.cpp rename to source/core/thread.cpp diff --git a/source/thread.h b/source/core/thread.h similarity index 100% rename from source/thread.h rename to source/core/thread.h diff --git a/source/types.h b/source/core/types.h similarity index 100% rename from source/types.h rename to source/core/types.h diff --git a/source/win32poll.h b/source/core/win32poll.h similarity index 100% rename from source/win32poll.h rename to source/core/win32poll.h diff --git a/source/semaphore.h b/source/semaphore.h deleted file mode 100644 index 36e9690..0000000 --- a/source/semaphore.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -This file is part of libmspframework -Copyright © 2006 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ -#ifndef MSP_FRAMEWORK_SEMAPHORE_H_ -#define MSP_FRAMEWORK_SEMAPHORE_H_ - -#include -#include "mutex.h" - -namespace Msp { - -class Semaphore -{ -public: - Semaphore() { pthread_cond_init(&cond, 0); } - Mutex &get_mutex() { return mutex; } - int signal() { return pthread_cond_signal(&cond); } - int broadcast() { return pthread_cond_broadcast(&cond); } - int wait() { return pthread_cond_wait(&cond, &mutex.mutex); } - ~Semaphore() { pthread_cond_destroy(&cond); } -private: - Mutex mutex; - pthread_cond_t cond; -}; - -} - -#endif diff --git a/source/time/Module b/source/time/Module new file mode 100644 index 0000000..9ccc1f2 --- /dev/null +++ b/source/time/Module @@ -0,0 +1 @@ +installheaders="time" diff --git a/source/time/timedelta.cpp b/source/time/timedelta.cpp new file mode 100644 index 0000000..891d560 --- /dev/null +++ b/source/time/timedelta.cpp @@ -0,0 +1,99 @@ +/* +This file is part of libmspframework +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ +#include +#include "timedelta.h" +#include "units.h" + +using namespace std; + +namespace Msp { +namespace Time { + +void print_part(ostream &out, int64_t &value, int64_t unit, char sep, bool &first) +{ + if(value>=unit || !first) + { + if(first) + out< +#include +#include + +namespace Msp { +namespace Time { + +/** +Represents a quantity of time, such as five seconds. +*/ +class TimeDelta +{ +public: + /** + Constructs a zero TimeDelta. + */ + TimeDelta(): usec(0) { } + + /** + Constructs a TimeDelta from a plain number. The purpose of this is to allow + serialization together with the raw() function. For creating TimeDeltas + with a specific length, see units.h. + */ + explicit TimeDelta(int64_t u): usec(u) { } + + /** + Returns the raw number stored inside the TimeDelta. This should only be used + for serialization and the result should not be interpreted in any way. + */ + int64_t raw() const { return usec; } + + /** + Fills in a timespec struct. To get a meaningful scalar value from the + TimeDelta, divide with one of the values in units.h. + */ + void fill_timespec(timespec &ts) const { ts.tv_sec=usec/1000000; ts.tv_nsec=(usec%1000000)*1000; } + + TimeDelta operator+(const TimeDelta &t) const { return TimeDelta(usec+t.usec); } + TimeDelta &operator+=(const TimeDelta &t) { usec+=t.usec; return *this; } + TimeDelta operator-(const TimeDelta &t) const { return TimeDelta(usec-t.usec); } + TimeDelta &operator-=(const TimeDelta &t) { usec-=t.usec; return *this; } + + template + TimeDelta operator*(T a) const { return TimeDelta((int64_t)(usec*a)); } + template + TimeDelta &operator*=(T a) { usec=(int64_t)(usec*a); return *this; } + + template + TimeDelta operator/(T a) const { return TimeDelta((int64_t)(usec/a)); } + template + TimeDelta &operator/=(T a) { usec=(int64_t)(usec/a); return *this; } + + double operator/(const TimeDelta &t) const { return (double)usec/t.usec; } + + bool operator>(const TimeDelta &t) const { return usec>t.usec; } + bool operator>=(const TimeDelta &t) const { return usec>=t.usec; } + bool operator<(const TimeDelta &t) const { return usec +inline TimeDelta operator*(T a, const TimeDelta &t) { return t*a; } + +} // namespace Time +} // namespace Msp + +#endif diff --git a/source/time/timer.cpp b/source/time/timer.cpp new file mode 100644 index 0000000..641d55f --- /dev/null +++ b/source/time/timer.cpp @@ -0,0 +1,119 @@ +/* +This file is part of libmspframework +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ +#include +#include "timer.h" +#include "utils.h" + +using namespace std; + +namespace Msp { +namespace Time { + +Timer::Timer(const Time::TimeDelta &d): + interval(d), + timeout(now()+d) +{ + MutexLock l(set_mutex); + timers.insert(this); + thread.nudge(); +} + +Timer::~Timer() +{ + MutexLock l(set_mutex); + timers.erase(this); + thread.nudge(); +} + +Timer::ThreadProxy Timer::thread; +Mutex Timer::set_mutex; +set Timer::timers; + +Timer::Thread::Thread(): + done(false) +{ + launch(); +} + +/** +Notifies the thread that a change in the timers occurred. +*/ +void Timer::Thread::nudge() +{ + sem.signal(); +} + +/** +Tells the thread to finish and terminate gracefully. This function will return +after the thread has terminated. +*/ +void Timer::Thread::finish() +{ + if(!done) + { + done=true; + sem.signal(); + } + + join(); +} + +void Timer::Thread::main() +{ + while(!done) + { + set_mutex.lock(); + Timer *next=0; + TimeStamp next_ts; + for(set::iterator i=timers.begin(); i!=timers.end(); ++i) + { + const TimeStamp &ts=(*i)->get_timeout(); + if(tssignal_timeout.emit()) + next->timeout+=next->interval; + else + delete next; + } + } + else + pause(); + } +} + +/** +Creates the thread if it doesn't exist, otherwise nudges it. +*/ +void Timer::ThreadProxy::nudge() +{ + if(!thread) + thread=new Thread(); + else + thread->nudge(); +} + +Timer::ThreadProxy::~ThreadProxy() +{ + if(thread) + { + thread->finish(); + delete thread; + } +} + +} // namespace Time +} // namespace Msp diff --git a/source/time/timer.h b/source/time/timer.h new file mode 100644 index 0000000..ef7ea8b --- /dev/null +++ b/source/time/timer.h @@ -0,0 +1,78 @@ +/* +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 +#include +#include "../core/mutex.h" +#include "../core/semaphore.h" +#include "../core/thread.h" +#include "timedelta.h" +#include "timestamp.h" + +namespace Msp { +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 separate thread is used for running the timers. All signal emissions will +happen in this thread - be careful with your variables. +*/ +class Timer +{ +public: + sigc::signal 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 + { + public: + Thread(); + void nudge(); + void finish(); + private: + bool done; + Semaphore sem; + + void main(); + }; + + /** + Proxy class to handle automatic starting and termination of the thread. + */ + class ThreadProxy + { + public: + ThreadProxy(): thread(0) { } + void nudge(); + ~ThreadProxy(); + private: + Thread *thread; + }; + + Time::TimeDelta interval; + Time::TimeStamp timeout; + + static ThreadProxy thread; + static Mutex set_mutex; + static std::set timers; +}; + +} // namespace Time +} // namespace Msp + +#endif diff --git a/source/time/timestamp.h b/source/time/timestamp.h new file mode 100644 index 0000000..da4e457 --- /dev/null +++ b/source/time/timestamp.h @@ -0,0 +1,62 @@ +/* +This file is part of libmspframework +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ +#ifndef MSP_TIME_TIMESTAMP_H_ +#define MSP_TIME_TIMESTAMP_H_ + +#include +#include "timedelta.h" + +namespace Msp { +namespace Time { + +/** +Represents a moment in time, such as the last tick. This class is NOT intended +to be used for storing arbitary user-defined times, I'll add a DateTime class +if the need arises. +*/ +class TimeStamp +{ +public: + /** + Construct a TimeStamp that represents an arbitarily distant point in the + past. It's guaranteed to be less than any valid timestamp. + */ + TimeStamp(): usec(0) { } + + /** + Constructs a TimeStamp from a plain number. The purpose of this is to allow + serialization together with the raw() function. + */ + explicit TimeStamp(int64_t u): usec(u) { } + + /** + Returns the raw number stored inside the TimeStamp. This should only be used + for serialization and the result should not be interpreted in any way. + */ + int64_t raw() const { return usec; } + + TimeStamp operator+(const TimeDelta &t) const { return TimeStamp(usec+t.raw()); } + TimeStamp &operator+=(const TimeDelta &t) { usec+=t.raw(); return *this; } + TimeStamp operator-(const TimeDelta &t) const { return TimeStamp(usec-t.raw()); } + TimeStamp &operator-=(const TimeDelta &t) { usec-=t.raw(); return *this; } + TimeDelta operator-(const TimeStamp &t) const { return TimeDelta(usec-t.usec); } + bool operator>=(const TimeStamp &t) const { return usec>=t.usec; } + bool operator>(const TimeStamp &t) const { return usec>t.usec; } + bool operator<=(const TimeStamp &t) const { return usec<=t.usec; } + bool operator<(const TimeStamp &t) const { return usec0; } + + static TimeStamp from_unixtime(time_t t) { return TimeStamp(t*1000000LL); } +private: + int64_t usec; +}; + +} // namespace Time +} // namespace Msp + +#endif diff --git a/source/time/units.cpp b/source/time/units.cpp new file mode 100644 index 0000000..e37987b --- /dev/null +++ b/source/time/units.cpp @@ -0,0 +1,21 @@ +/* +This file is part of libmspframework +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ +#include "units.h" + +namespace Msp { +namespace Time { + +// Constants to be used in creation of TimeDeltas +const TimeDelta usec(1); +const TimeDelta msec(1000); +const TimeDelta sec(1000000); +const TimeDelta min(60*1000000); +const TimeDelta hour(3600*1000000LL); +const TimeDelta day(86400*1000000LL); +const TimeDelta week(7*86400*1000000LL); + +} // namespace Time +} // namespace Msp diff --git a/source/time/units.h b/source/time/units.h new file mode 100644 index 0000000..6417782 --- /dev/null +++ b/source/time/units.h @@ -0,0 +1,25 @@ +/* +This file is part of libmspframework +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ +#ifndef MSP_TIME_UNITS_H_ +#define MSP_TIME_UNITS_H_ + +#include "timedelta.h" + +namespace Msp { +namespace Time { + +extern const TimeDelta usec; +extern const TimeDelta msec; +extern const TimeDelta sec; +extern const TimeDelta min; +extern const TimeDelta hour; +extern const TimeDelta day; +extern const TimeDelta week; + +} // namespace Time +} // namespace Msp + +#endif diff --git a/source/time/utils.cpp b/source/time/utils.cpp new file mode 100644 index 0000000..00c389d --- /dev/null +++ b/source/time/utils.cpp @@ -0,0 +1,52 @@ +/* +This file is part of libmspframework +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ +#include +#include +#include "timedelta.h" +#include "timestamp.h" +#include "units.h" +#include "utils.h" + +namespace Msp { +namespace Time { + +/** +Returns the current timestamp. +*/ +TimeStamp now() +{ + timeval tv; + gettimeofday(&tv, 0); + return TimeStamp(tv.tv_sec*1000000LL+tv.tv_usec); +} + +/** +Returns the CPU time used by the program so far. +*/ +TimeDelta get_cpu_time() +{ + rusage ru; + getrusage(RUSAGE_SELF, &ru); + return (ru.ru_utime.tv_sec+ru.ru_stime.tv_sec)*sec + (ru.ru_utime.tv_usec+ru.ru_stime.tv_usec)*usec; +} + +/** +Sleeps for the given time. +*/ +int sleep(const TimeDelta &d) +{ +#ifndef WIN32 + timespec ts; + d.fill_timespec(ts); + return nanosleep(&ts, 0); +#else + Sleep(d/msec); + return 0; +#endif +} + +} // namespace Time +} // namespace Msp diff --git a/source/time/utils.h b/source/time/utils.h new file mode 100644 index 0000000..9efe39a --- /dev/null +++ b/source/time/utils.h @@ -0,0 +1,22 @@ +/* +This file is part of libmspframework +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ +#ifndef MSP_TIME_UTILS_H_ +#define MSP_TIME_UTILS_H_ + +namespace Msp { +namespace Time { + +class TimeDelta; +class TimeStamp; + +extern TimeStamp now(); +extern TimeDelta get_cpu_time(); +extern int sleep(const TimeDelta &); + +} // namespace Time +} // namespace Msp + +#endif -- 2.43.0