/usr/include/gnelib/EventThread.h is in libgnelib-dev 0.75+svn20091130-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | #ifndef _EVENTTHREAD_H_
#define _EVENTTHREAD_H_
/* GNE - Game Networking Engine, a portable multithreaded networking library.
* Copyright (C) 2001-2006 Jason Winnebeck
* Project website: http://www.gillius.org/gne/
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <gnelib/Thread.h>
#include <gnelib/Error.h>
#include <gnelib/Mutex.h>
#include <gnelib/ConditionVariable.h>
#include <gnelib/Time.h>
#include <gnelib/SmartPtr.h>
#include <gnelib/WeakPtr.h>
namespace GNE {
class ConnectionListener;
class Connection;
/**
* @ingroup internal
*
* Internal class used by GNE to manage Connection events.
*
* Each Connection has an EventThread. This is used internally by the
* Connection class to act as a proxy to dispatch events to the
* ConnectionListener. Because of this, only one event per Connection will
* be active at any one time. Another appropriate name that might describe
* this would be an EventQueue. But to improve efficency and stability,
* some events may be reordered or combined. Remember that onReceive means 1
* or more packets have been received. If multiple onReceive or
* onDoneWriting occur, they will probably be combined. Error events will
* always have first priority, and if the error leads to a disconnect,
* pending events after that will not be called (except for onDisconnect).
*
* EventThread was created to solve several things:
* <ul>
* <li>Complexities due to multiple threads calling the ConnectionListener at
* the same time.</li>
* <li>Serialized events and all events executing in the same thread is easy
* to control and eliminates lots of previous ways for syncronization errors
* to creep in.</li>
* <li>Events taking a while to execute or block (although this is an error),
* won't stop the rest of GNE from functioning, but will only stop a single
* Connection.</li>
* <li>Multiple event threads take better advantage of multiprocessor
* machines.</li>
* </ul>
*/
class EventThread : public Thread {
protected:
/**
* @see create
*/
EventThread( const SmartPtr<Connection>& conn );
public:
typedef SmartPtr<EventThread> sptr;
typedef WeakPtr<EventThread> wptr;
/**
* Initializes this class as a event thread for a listener.
* The conn pointer is used to call disconnect when an onFailure
* event is finally processed. This is to assure that disconnect is called
* from a safe thread that won't lead to deadlock when a failure occurs.
*
* The SmartPtr also keeps the Connection alive if it is still active.
*/
static sptr create( const SmartPtr<Connection>& conn );
virtual ~EventThread();
/**
* Use GNE::Connection::getListener.
*/
SmartPtr<ConnectionListener> getListener() const;
/**
* Use GNE::Connection::setListener.
*/
void setListener( const SmartPtr<ConnectionListener>& listener );
/**
* Use GNE::Connection::getTimeout.
*/
int getTimeout() const;
/**
* Use GNE::Connection::setTimeout.
*/
void setTimeout(int ms);
/**
* For more information about these events, see ConnectionListener. The
* processing of an onDisconnect event will be the last, and the thread
* will essentially stop when onDisconnect completes.
*/
void onDisconnect();
/**
* For more information about these events, see ConnectionListener.
*/
void onExit();
/**
* For more information about these events, see ConnectionListener.
*/
void onFailure(const Error& error);
/**
* For more information about these events, see ConnectionListener.
*/
void onError(const Error& error);
/**
* For more information about these events, see ConnectionListener.
*/
void onReceive();
/**
* Overrides Thread::shutDown so that the daemon thread will
* be woken up since it might be waiting on a ConditionVariable. Once it
* shuts down it should not be activated again.
*/
void shutDown();
protected:
/**
* This thread serializes events for a Connection.
*/
void run();
private:
/**
* Checks for timeout, triggering an onTimeout event and handling the time
* variables, if needed.
*/
void checkForTimeout();
/**
* Resets the timeout counter by making nextTimeout be the current absolute
* time + the timeout interval.
*/
void resetTimeout();
void onTimeout();
//See the ctor for more information about ourConn.
SmartPtr<Connection> ourConn;
//The listener for our events. All on* events go here. This is protected
//so ClientConnection can send events as well.
SmartPtr<ConnectionListener> eventListener;
ConditionVariable eventSync;
mutable ConditionVariable listenSync;
//Variables for handling onTimeout events.
Mutex timeSync;
Time timeout;
Time nextTimeout;
volatile bool onReceiveEvent;
volatile bool onTimeoutEvent;
//If this is true, we should not receive any more events. It should be the
//next event called, and everything else should stop.
volatile bool onDisconnectEvent;
//If this is true, an graceful exit notice was received, and the next event
//is an onDisconnectEvent.
volatile bool onExitEvent;
//Wish we could combine error events and report the last error, but this
//really isn't what the API specifies, so we should keep track of every
//error.
std::queue<Error*> eventQueue;
//If this is true, we have a onFailure event which takes precedence over
//everything.
Error* failure;
};
}
#endif /* _EVENTTHREAD_H_ */
|