From 7f381149dcff8bf6cb1f8abb2953a5b118e456bf Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 17 May 2012 20:34:51 +0200 Subject: [PATCH] Implemented Lock class. --- base/Makefile.am | 2 ++ base/base.vcxproj | 2 ++ base/condvar.cpp | 34 ++++++++++++++++-- base/condvar.h | 10 +++++- base/i2-base.h | 1 + base/lock.cpp | 40 +++++++++++++++++++++ base/lock.h | 42 ++++++++++++++++++++++ base/object.h | 1 + base/observable.h | 92 +++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 220 insertions(+), 4 deletions(-) create mode 100644 base/lock.cpp create mode 100644 base/lock.h create mode 100644 base/observable.h diff --git a/base/Makefile.am b/base/Makefile.am index 601d09d50..daa171ce8 100644 --- a/base/Makefile.am +++ b/base/Makefile.am @@ -27,6 +27,8 @@ libbase_la_SOURCES = \ fifo.cpp \ fifo.h \ i2-base.h \ + lock.cpp \ + lock.h \ memory.cpp \ memory.h \ mutex.cpp \ diff --git a/base/base.vcxproj b/base/base.vcxproj index bdcca97ad..44e415aea 100644 --- a/base/base.vcxproj +++ b/base/base.vcxproj @@ -20,6 +20,7 @@ + @@ -45,6 +46,7 @@ + diff --git a/base/condvar.cpp b/base/condvar.cpp index bc072ff24..01d1b754d 100644 --- a/base/condvar.cpp +++ b/base/condvar.cpp @@ -50,13 +50,41 @@ CondVar::~CondVar(void) * before it begins to wait and re-acquires the mutex after waiting. * * @param mtx The mutex that should be released during waiting. + * @param timeoutMilliseconds The timeout in milliseconds. Use the special + * constant CondVar::TimeoutInfinite for an + * infinite timeout. + * @returns false if a timeout occured, true otherwise. */ -void CondVar::Wait(Mutex& mtx) +bool CondVar::Wait(Mutex& mtx, WaitTimeout timeoutMilliseconds) { #ifdef _WIN32 - SleepConditionVariableCS(&m_CondVar, mtx.Get(), INFINITE); + return (SleepConditionVariableCS(&m_CondVar, mtx.Get(), + timeoutMilliseconds) != FALSE); #else /* _WIN32 */ - pthread_cond_wait(&m_CondVar, mtx.Get()); + if (timeoutMilliseconds == TimeoutInfinite) + pthread_cond_wait(&m_CondVar, mtx.Get()); + else { + timeval now; + timespec ts; + + if (gettimeofday(&now, NULL) < 0) + throw PosixException("gettimeofday failed.", errno); + + ts.tv_sec = now.tv_sec; + ts.tv_nsec = now.tv_usec * 1000; + ts.tv_nsec += timeoutMilliseconds * 1000; + + int rc = pthread_cond_timedwait(&m_CondVar, mtx.Get(), &ts); + + if (rc == 0) + return true; + + if (errno != ETIMEDOUT) + throw PosixException("pthread_cond_timedwait failed", + errno); + + return false; + } #endif /* _WIN32 */ } diff --git a/base/condvar.h b/base/condvar.h index 6b63d3be9..b8cbcd41b 100644 --- a/base/condvar.h +++ b/base/condvar.h @@ -36,10 +36,18 @@ private: #endif /* _WIN32 */ public: +#ifdef _WIN32 + typedef DWORD WaitTimeout; + static const WaitTimeout TimeoutInfinite = INFINITE; +#else /* _WIN32 */ + typedef int WaitTimeout; + static const WaitTimeout TimeoutInfinite = -1; +#endif /* _WIN32 */ + CondVar(void); ~CondVar(void); - void Wait(Mutex& mtx); + bool Wait(Mutex& mtx, WaitTimeout timeoutMilliseconds = TimeoutInfinite); void Signal(void); void Broadcast(void); diff --git a/base/i2-base.h b/base/i2-base.h index 985565e89..5dba56915 100644 --- a/base/i2-base.h +++ b/base/i2-base.h @@ -96,6 +96,7 @@ using namespace std::tr1::placeholders; #endif /* I2_BASE_BUILD */ #include "mutex.h" +#include "lock.h" #include "condvar.h" #include "thread.h" #include "utility.h" diff --git a/base/lock.cpp b/base/lock.cpp new file mode 100644 index 000000000..fd93adc45 --- /dev/null +++ b/base/lock.cpp @@ -0,0 +1,40 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "i2-base.h" + +using namespace icinga; + +/** + * Constructor for the Lock class. Acquires a lock on the specified mutex. + * + * @param mutex The mutex that is to be locked. + */ +Lock::Lock(Mutex& mutex) : m_Mutex(mutex) +{ + m_Mutex.Exit(); +} + +/** + * Destructor for the Lock class. Releases the lock. + */ +Lock::~Lock(void) +{ + m_Mutex.Exit(); +} diff --git a/base/lock.h b/base/lock.h new file mode 100644 index 000000000..62db329d4 --- /dev/null +++ b/base/lock.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef LOCK_H +#define LOCK_H + +namespace icinga +{ + +/** + * A lock that is held on a mutex and automatically released when the Lock + * object is destroyed. + */ +class I2_BASE_API Lock +{ +private: + Mutex& m_Mutex; + +public: + Lock(Mutex& mutex); + ~Lock(void); +}; + +} + +#endif /* LOCK_H */ diff --git a/base/object.h b/base/object.h index 5b7776c02..cf054a77c 100644 --- a/base/object.h +++ b/base/object.h @@ -31,6 +31,7 @@ class I2_BASE_API Object : public enable_shared_from_this { private: Object(const Object& other); + Object operator=(const Object& rhs); protected: Object(void); diff --git a/base/observable.h b/base/observable.h new file mode 100644 index 000000000..c9edfd893 --- /dev/null +++ b/base/observable.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef OBSERVABLE_H +#define OBSERVABLE_H + +namespace icinga +{ + +/** + * Base class for event arguments. + */ +struct I2_BASE_API EventArgs +{ + Object::Ptr Source; /**< The source of the event. */ +}; + +/** + * An observable event. Observers can be registered for it. + */ +template +class Observable +{ +public: + typedef function ObserverType; + +private: + vector m_Observers; + +public: + /** + * Adds an observer to this event. + * + * @param rhs The delegate. + */ + Observable& operator +=(const ObserverType& rhs) + { + m_Observers.push_back(rhs); + return *this; + } + + /** + * Removes an observer from this event. + * + * @param rhs The delegate. + */ + Observable& operator -=(const ObserverType& rhs) + { + m_Observers.erase(rhs); + return *this; + } + + /** + * Invokes each observer function that is registered for this event. Any + * observer function which returns -1 is removed. + * + * @param args Event arguments. + */ + void operator()(const TArgs& args) + { + typename vector::iterator i; + + for (i = m_Observers.begin(); i != m_Observers.end(); ) { + int result = (*i)(args); + + if (result == -1) + i = m_Observers.erase(i); + else + i++; + } + } +}; + +} + +#endif /* OBSERVABLE_H */ -- 2.40.0