fifo.cpp \
fifo.h \
i2-base.h \
+ lock.cpp \
+ lock.h \
memory.cpp \
memory.h \
mutex.cpp \
<ClCompile Include="dictionary.cpp" />
<ClCompile Include="exception.cpp" />
<ClCompile Include="fifo.cpp" />
+ <ClCompile Include="lock.cpp" />
<ClCompile Include="memory.cpp" />
<ClCompile Include="mutex.cpp" />
<ClCompile Include="object.cpp" />
<ClInclude Include="cxx11-compat.h" />
<ClInclude Include="delegate.h" />
<ClInclude Include="dictionary.h" />
+ <ClInclude Include="lock.h" />
<ClInclude Include="observable.h" />
<ClInclude Include="exception.h" />
<ClInclude Include="fifo.h" />
* 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 */
}
#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);
#endif /* I2_BASE_BUILD */
#include "mutex.h"
+#include "lock.h"
#include "condvar.h"
#include "thread.h"
#include "utility.h"
--- /dev/null
+/******************************************************************************
+ * 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();
+}
--- /dev/null
+/******************************************************************************
+ * 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 */
{
private:
Object(const Object& other);
+ Object operator=(const Object& rhs);
protected:
Object(void);
--- /dev/null
+/******************************************************************************
+ * 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 TArgs>
+class Observable
+{
+public:
+ typedef function<int (const TArgs&)> ObserverType;
+
+private:
+ vector<ObserverType> m_Observers;
+
+public:
+ /**
+ * Adds an observer to this event.
+ *
+ * @param rhs The delegate.
+ */
+ Observable<TArgs>& operator +=(const ObserverType& rhs)
+ {
+ m_Observers.push_back(rhs);
+ return *this;
+ }
+
+ /**
+ * Removes an observer from this event.
+ *
+ * @param rhs The delegate.
+ */
+ Observable<TArgs>& 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<ObserverType>::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 */