barrier/lib/base/CEventQueue.h

193 lines
4.9 KiB
C++

/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2004 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.
*/
#ifndef CEVENTQUEUE_H
#define CEVENTQUEUE_H
#include "IEventQueue.h"
#include "CEvent.h"
#include "CPriorityQueue.h"
#include "CStopwatch.h"
#include "IArchMultithread.h"
#include "stdmap.h"
#include "stdset.h"
//! Event queue
/*!
An event queue that implements the platform independent parts and
delegates the platform dependent parts to a subclass.
*/
class CEventQueue : public IEventQueue {
public:
CEventQueue();
virtual ~CEventQueue();
//! @name manipulators
//@{
//@}
//! @name accessors
//@{
//! Get the system event type target
/*!
Returns the target to use for dispatching \c CEvent::kSystem events.
*/
static void* getSystemTarget();
//! Get the singleton instance
/*!
Returns the singleton instance of the event queue
*/
static CEventQueue* getInstance();
//@}
// IEventQueue overrides
virtual bool getEvent(CEvent& event, double timeout = -1.0);
virtual bool dispatchEvent(const CEvent& event);
virtual void addEvent(const CEvent& event);
virtual CEventQueueTimer*
newTimer(double duration, void* target = NULL);
virtual CEventQueueTimer*
newOneShotTimer(double duration, void* target = NULL);
virtual void deleteTimer(CEventQueueTimer*);
virtual void adoptHandler(void* target, IEventJob* dispatcher);
virtual IEventJob* orphanHandler(void* target);
virtual bool isEmpty() const;
virtual IEventJob* getHandler(void* target) const;
protected:
//! @name manipulators
//@{
//! Get the data for a given id
/*!
Takes a saved event id, \p eventID, and returns a \c CEvent. The
event id becomes invalid after this call. The \p eventID must have
been passed to a successful call to \c doAddEvent() and not removed
since.
*/
CEvent removeEvent(UInt32 eventID);
//! Block waiting for an event
/*!
Wait for an event in the system event queue for up to \p timeout
seconds.
*/
virtual void waitForEvent(double timeout) = 0;
//! Get the next event
/*!
Remove the next system event (one should be pending) and convert it
to a \c CEvent. The event type should be either \c CEvent::kSystem
if the event was not added by \c doAddEvent() or a type returned by
\c CEvent::registerType() if it was (and not \c CEvent::kTimer). A
non-system event will normally be retrieved by \c removeEvent(), but
the implementation must be able to tell the difference between a
system event and one added by \c doAddEvent().
*/
virtual bool doGetEvent(CEvent& event) = 0;
//! Post an event
/*!
Add the given event to the end of the system queue. This is a user
event and \c doGetEvent() must be able to identify it as such.
This method must cause \c waitForEvent() to return at some future
time if it's blocked waiting on an event.
*/
virtual bool doAddEvent(UInt32 dataID) = 0;
//@}
//! @name accessors
//@{
//! Check if system queue is empty
/*!
Return true iff the system queue is empty.
*/
virtual bool doIsEmpty() const = 0;
//! Create a timer object
/*!
Create and return a timer object. The object is opaque and is
used only by the subclass but it must be a valid object (i.e.
not NULL).
*/
virtual CEventQueueTimer*
doNewTimer(double duration, bool oneShot) const = 0;
//! Destroy a timer object
/*!
Destroy a timer object previously returned by \c doNewTimer().
*/
virtual void doDeleteTimer(CEventQueueTimer*) const = 0;
//@}
private:
UInt32 saveEvent(const CEvent& event);
bool hasTimerExpired(CEvent& event);
double getNextTimerTimeout() const;
private:
class CTimer {
public:
CTimer(CEventQueueTimer*, double timeout, void* target, bool oneShot);
~CTimer();
void reset();
CTimer& operator-=(double);
operator double() const;
bool isOneShot() const;
CEventQueueTimer*
getTimer() const;
void* getTarget() const;
void fillEvent(CTimerEvent&) const;
bool operator<(const CTimer&) const;
private:
CEventQueueTimer* m_timer;
double m_timeout;
void* m_target;
bool m_oneShot;
double m_time;
};
typedef std::set<CEventQueueTimer*> CTimers;
typedef CPriorityQueue<CTimer> CTimerQueue;
typedef std::map<UInt32, CEvent> CEventTable;
typedef std::vector<UInt32> CEventIDList;
typedef std::map<void*, IEventJob*> CHandlerTable;
static CEventQueue* s_instance;
CArchMutex m_mutex;
CEventTable m_events;
CEventIDList m_oldEventIDs;
CStopwatch m_time;
CTimers m_timers;
CTimerQueue m_timerQueue;
CTimerEvent m_timerEvent;
CHandlerTable m_handlers;
};
#endif