2002-08-02 19:57:46 +00:00
|
|
|
/*
|
|
|
|
* synergy -- mouse and keyboard sharing utility
|
|
|
|
* Copyright (C) 2002 Chris Schoeneman
|
|
|
|
*
|
|
|
|
* This package is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* found in the file COPYING that should have accompanied this file.
|
|
|
|
*
|
|
|
|
* This package 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.
|
|
|
|
*/
|
|
|
|
|
2001-10-06 14:13:28 +00:00
|
|
|
#ifndef CCONDVAR_H
|
|
|
|
#define CCONDVAR_H
|
|
|
|
|
|
|
|
#include "CMutex.h"
|
|
|
|
#include "BasicTypes.h"
|
|
|
|
|
|
|
|
class CStopwatch;
|
|
|
|
|
2002-07-28 13:34:19 +00:00
|
|
|
//! Generic condition variable
|
|
|
|
/*!
|
|
|
|
This class provides functionality common to all condition variables
|
|
|
|
but doesn't provide the actual variable storage. A condition variable
|
|
|
|
is a multiprocessing primitive that can be waited on. Every condition
|
|
|
|
variable has an associated mutex.
|
|
|
|
*/
|
2001-10-06 14:13:28 +00:00
|
|
|
class CCondVarBase {
|
2002-04-29 14:40:01 +00:00
|
|
|
public:
|
2002-07-28 13:34:19 +00:00
|
|
|
/*!
|
|
|
|
\c mutex must not be NULL. All condition variables have an
|
|
|
|
associated mutex. The mutex needn't be unique to one condition
|
|
|
|
variable.
|
|
|
|
*/
|
2001-10-06 14:13:28 +00:00
|
|
|
CCondVarBase(CMutex* mutex);
|
|
|
|
~CCondVarBase();
|
|
|
|
|
2002-07-28 13:34:19 +00:00
|
|
|
//! @name manipulators
|
|
|
|
//@{
|
2001-10-06 14:13:28 +00:00
|
|
|
|
2002-07-28 13:34:19 +00:00
|
|
|
//! Lock the condition variable's mutex
|
|
|
|
/*!
|
|
|
|
Lock the condition variable's mutex. The condition variable should
|
|
|
|
be locked before reading or writing it. It must be locked for a
|
|
|
|
call to wait(). Locks are not recursive; locking a locked mutex
|
|
|
|
will deadlock the thread.
|
|
|
|
*/
|
2001-10-14 16:58:01 +00:00
|
|
|
void lock() const;
|
2002-07-28 13:34:19 +00:00
|
|
|
|
|
|
|
//! Unlock the condition variable's mutex
|
2001-10-14 16:58:01 +00:00
|
|
|
void unlock() const;
|
2001-10-06 14:13:28 +00:00
|
|
|
|
2002-07-28 13:34:19 +00:00
|
|
|
//! Signal the condition variable
|
|
|
|
/*!
|
|
|
|
Wake up one waiting thread, if there are any. Which thread gets
|
|
|
|
woken is undefined.
|
|
|
|
*/
|
2001-10-14 16:58:01 +00:00
|
|
|
void signal();
|
2002-07-28 13:34:19 +00:00
|
|
|
|
|
|
|
//! Signal the condition variable
|
|
|
|
/*!
|
|
|
|
Wake up all waiting threads, if any.
|
|
|
|
*/
|
2001-10-14 16:58:01 +00:00
|
|
|
void broadcast();
|
2001-10-06 14:13:28 +00:00
|
|
|
|
2002-07-28 13:34:19 +00:00
|
|
|
//@}
|
|
|
|
//! @name accessors
|
|
|
|
//@{
|
|
|
|
|
|
|
|
//! Wait on the condition variable
|
|
|
|
/*!
|
|
|
|
Wait on the condition variable. If \c timeout < 0 then wait until
|
|
|
|
signalled, otherwise up to \c timeout seconds or until signalled,
|
|
|
|
whichever comes first. Returns true if the object was signalled
|
|
|
|
during the wait, false otherwise.
|
|
|
|
|
|
|
|
The proper way to wait for a condition is:
|
|
|
|
\code
|
|
|
|
cv.lock();
|
|
|
|
while (cv-expr) {
|
|
|
|
cv.wait();
|
|
|
|
}
|
|
|
|
cv.unlock();
|
|
|
|
\endcode
|
|
|
|
where \c cv-expr involves the value of \c cv and is false when the
|
|
|
|
condition is satisfied.
|
|
|
|
|
|
|
|
(cancellation point)
|
|
|
|
*/
|
2001-10-06 14:13:28 +00:00
|
|
|
bool wait(double timeout = -1.0) const;
|
|
|
|
|
2002-07-28 13:34:19 +00:00
|
|
|
//! Wait on the condition variable
|
|
|
|
/*!
|
|
|
|
Same as \c wait(double) but use \c timer to compare against \timeout.
|
|
|
|
Since clients normally wait on condition variables in a loop, clients
|
|
|
|
can use this to avoid recalculating \c timeout on each iteration.
|
|
|
|
Passing a stopwatch with a negative \c timeout is pointless (it will
|
|
|
|
never time out) but permitted.
|
|
|
|
|
|
|
|
(cancellation point)
|
|
|
|
*/
|
|
|
|
bool wait(CStopwatch& timer, double timeout) const;
|
|
|
|
|
|
|
|
//! Get the mutex
|
|
|
|
/*!
|
|
|
|
Get the mutex passed to the c'tor.
|
|
|
|
*/
|
2001-10-14 16:58:01 +00:00
|
|
|
CMutex* getMutex() const;
|
2001-10-06 14:13:28 +00:00
|
|
|
|
2002-07-28 13:34:19 +00:00
|
|
|
//@}
|
|
|
|
|
2002-04-29 14:40:01 +00:00
|
|
|
private:
|
2001-10-06 14:13:28 +00:00
|
|
|
// not implemented
|
|
|
|
CCondVarBase(const CCondVarBase&);
|
|
|
|
CCondVarBase& operator=(const CCondVarBase&);
|
|
|
|
|
2002-04-29 14:40:01 +00:00
|
|
|
private:
|
2001-10-06 14:13:28 +00:00
|
|
|
CMutex* m_mutex;
|
2003-01-04 22:01:32 +00:00
|
|
|
CArchCond m_cond;
|
2001-10-06 14:13:28 +00:00
|
|
|
};
|
|
|
|
|
2002-07-28 13:34:19 +00:00
|
|
|
//! Condition variable
|
|
|
|
/*!
|
|
|
|
A condition variable with storage for type \c T.
|
|
|
|
*/
|
2001-10-06 14:13:28 +00:00
|
|
|
template <class T>
|
|
|
|
class CCondVar : public CCondVarBase {
|
2002-04-29 14:40:01 +00:00
|
|
|
public:
|
2002-07-28 13:34:19 +00:00
|
|
|
//! Initialize using \c value
|
|
|
|
CCondVar(CMutex* mutex, const T& value);
|
|
|
|
//! Initialize using another condition variable's value
|
2001-10-06 14:13:28 +00:00
|
|
|
CCondVar(const CCondVar&);
|
|
|
|
~CCondVar();
|
|
|
|
|
2002-07-28 13:34:19 +00:00
|
|
|
//! @name manipulators
|
|
|
|
//@{
|
|
|
|
|
|
|
|
//! Assigns the value of \c cv to this
|
|
|
|
/*!
|
|
|
|
Set the variable's value. The condition variable should be locked
|
|
|
|
before calling this method.
|
|
|
|
*/
|
|
|
|
CCondVar& operator=(const CCondVar& cv);
|
|
|
|
|
|
|
|
//! Assigns \c value to this
|
|
|
|
/*!
|
|
|
|
Set the variable's value. The condition variable should be locked
|
|
|
|
before calling this method.
|
|
|
|
*/
|
|
|
|
CCondVar& operator=(const T& v);
|
|
|
|
|
|
|
|
//@}
|
|
|
|
//! @name accessors
|
|
|
|
//@{
|
|
|
|
|
|
|
|
//! Get the variable's value
|
|
|
|
/*!
|
|
|
|
Get the variable's value. The condition variable should be locked
|
|
|
|
before calling this method.
|
|
|
|
*/
|
2004-11-10 21:00:30 +00:00
|
|
|
operator const volatile T&() const;
|
2001-10-06 14:13:28 +00:00
|
|
|
|
2002-07-28 13:34:19 +00:00
|
|
|
//@}
|
|
|
|
|
2002-04-29 14:40:01 +00:00
|
|
|
private:
|
2004-11-10 21:00:30 +00:00
|
|
|
volatile T m_data;
|
2001-10-06 14:13:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline
|
2002-06-10 22:06:45 +00:00
|
|
|
CCondVar<T>::CCondVar(
|
|
|
|
CMutex* mutex,
|
|
|
|
const T& data) :
|
|
|
|
CCondVarBase(mutex),
|
|
|
|
m_data(data)
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline
|
2002-06-10 22:06:45 +00:00
|
|
|
CCondVar<T>::CCondVar(
|
|
|
|
const CCondVar& cv) :
|
|
|
|
CCondVarBase(cv.getMutex()),
|
|
|
|
m_data(cv.m_data)
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline
|
|
|
|
CCondVar<T>::~CCondVar()
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline
|
2002-06-10 22:06:45 +00:00
|
|
|
CCondVar<T>&
|
2004-11-10 21:00:30 +00:00
|
|
|
CCondVar<T>::operator=(const CCondVar<T>& cv)
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
|
|
|
m_data = cv.m_data;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline
|
2002-06-10 22:06:45 +00:00
|
|
|
CCondVar<T>&
|
2004-11-10 21:00:30 +00:00
|
|
|
CCondVar<T>::operator=(const T& data)
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
|
|
|
m_data = data;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline
|
2004-11-10 21:00:30 +00:00
|
|
|
CCondVar<T>::operator const volatile T&() const
|
2001-10-06 14:13:28 +00:00
|
|
|
{
|
|
|
|
return m_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|