forked from panda3d/panda3d
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconnectionReader.h
More file actions
171 lines (138 loc) · 5.13 KB
/
connectionReader.h
File metadata and controls
171 lines (138 loc) · 5.13 KB
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
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file connectionReader.h
* @author drose
* @date 2000-02-08
*/
#ifndef CONNECTIONREADER_H
#define CONNECTIONREADER_H
#include "pandabase.h"
#include "connection.h"
#include "pointerTo.h"
#include "pmutex.h"
#include "lightMutex.h"
#include "pvector.h"
#include "pset.h"
#include "socket_fdset.h"
#include "atomicAdjust.h"
class NetDatagram;
class ConnectionManager;
class Socket_Address;
class Socket_IP;
/**
* This is an abstract base class for a family of classes that listen for
* activity on a socket and respond to it, for instance by reading a datagram
* and serving it (or queueing it up for later service).
*
* A ConnectionReader may define an arbitrary number of threads (at least one)
* to process datagrams coming in from an arbitrary number of sockets that it
* is monitoring. The number of threads is specified at construction time and
* cannot be changed, but the set of sockets that is to be monitored may be
* constantly modified at will.
*
* This is an abstract class because it doesn't define how to process each
* received datagram. See QueuedConnectionReader. Also note that
* ConnectionListener derives from this class, extending it to accept
* connections on a rendezvous socket rather than read datagrams.
*/
class EXPCL_PANDA_NET ConnectionReader {
PUBLISHED:
// The implementation here used to involve NSPR's multi-wait interface, but
// that got too complicated to manage. It turns out to be difficult to
// protect against memory leaks caused by race conditions in that interface,
// as designed.
// Instead, we do our own multi-wait type stuff. Only one thread at a time
// can extract the next-available socket with activity on it. That thread
// will either (a) simply extract the next socket from the arrays returned
// by a previous call to PR_Poll(), or (b) execute (and possibly block on) a
// new call to PR_Poll().
explicit ConnectionReader(ConnectionManager *manager, int num_threads,
const std::string &thread_name = std::string());
virtual ~ConnectionReader();
bool add_connection(Connection *connection);
bool remove_connection(Connection *connection);
bool is_connection_ok(Connection *connection);
void poll();
ConnectionManager *get_manager() const;
INLINE bool is_polling() const;
int get_num_threads() const;
void set_raw_mode(bool mode);
bool get_raw_mode() const;
void set_tcp_header_size(int tcp_header_size);
int get_tcp_header_size() const;
void shutdown();
protected:
virtual void flush_read_connection(Connection *connection);
virtual void receive_datagram(const NetDatagram &datagram)=0;
class SocketInfo {
public:
SocketInfo(const PT(Connection) &connection);
bool is_udp() const;
Socket_IP *get_socket() const;
PT(Connection) _connection;
bool _busy;
bool _error;
};
typedef pvector<SocketInfo *> Sockets;
void clear_manager();
void finish_socket(SocketInfo *sinfo);
virtual bool process_incoming_data(SocketInfo *sinfo);
virtual bool process_incoming_udp_data(SocketInfo *sinfo);
virtual bool process_incoming_tcp_data(SocketInfo *sinfo);
virtual bool process_raw_incoming_udp_data(SocketInfo *sinfo);
virtual bool process_raw_incoming_tcp_data(SocketInfo *sinfo);
protected:
ConnectionManager *_manager;
// These structures track the total set of sockets (connections) we know
// about.
Sockets _sockets;
// This is the list of recently-removed sockets. We can't actually delete
// them until they're no longer _busy.
Sockets _removed_sockets;
// Any operations on _sockets are protected by this mutex.
LightMutex _sockets_mutex;
private:
void thread_run(int thread_index);
SocketInfo *get_next_available_socket(bool allow_block,
int current_thread_index);
void rebuild_select_list();
void accumulate_fdset(Socket_fdset &fdset);
private:
bool _raw_mode;
int _tcp_header_size;
bool _shutdown;
class ReaderThread : public Thread {
public:
ReaderThread(ConnectionReader *reader, const std::string &thread_name,
int thread_index);
virtual void thread_main();
ConnectionReader *_reader;
int _thread_index;
};
typedef pvector< PT(ReaderThread) > Threads;
Threads _threads;
bool _polling;
// These structures are used to manage selecting for noise on available
// sockets.
Socket_fdset _fdset;
Sockets _selecting_sockets;
int _next_index;
int _num_results;
// Threads go to sleep on this mutex waiting for their chance to read a
// socket.
Mutex _select_mutex;
// This is atomically updated with the index (in _threads) of the thread
// that is currently waiting on the PR_Poll() call. It contains -1 if no
// thread is so waiting.
AtomicAdjust::Integer _currently_polling_thread;
friend class ConnectionManager;
friend class ReaderThread;
};
#include "connectionReader.I"
#endif