Panda3D
 All Classes Functions Variables Enumerations
connectionReader.h
1 // Filename: connectionReader.h
2 // Created by: drose (08Feb00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #ifndef CONNECTIONREADER_H
16 #define CONNECTIONREADER_H
17 
18 #include "pandabase.h"
19 
20 #include "connection.h"
21 
22 #include "pointerTo.h"
23 #include "pmutex.h"
24 #include "lightMutex.h"
25 #include "pvector.h"
26 #include "pset.h"
27 #include "socket_fdset.h"
28 #include "atomicAdjust.h"
29 
30 class NetDatagram;
31 class ConnectionManager;
32 class Socket_Address;
33 class Socket_IP;
34 
35 ////////////////////////////////////////////////////////////////////
36 // Class : ConnectionReader
37 // Description : This is an abstract base class for a family of
38 // classes that listen for activity on a socket and
39 // respond to it, for instance by reading a datagram and
40 // serving it (or queueing it up for later service).
41 //
42 // A ConnectionReader may define an arbitrary number of
43 // threads (at least one) to process datagrams coming in
44 // from an arbitrary number of sockets that it is
45 // monitoring. The number of threads is specified at
46 // construction time and cannot be changed, but the set
47 // of sockets that is to be monitored may be constantly
48 // modified at will.
49 //
50 // This is an abstract class because it doesn't define
51 // how to process each received datagram. See
52 // QueuedConnectionReader. Also note that
53 // ConnectionListener derives from this class, extending
54 // it to accept connections on a rendezvous socket
55 // rather than read datagrams.
56 ////////////////////////////////////////////////////////////////////
57 class EXPCL_PANDA_NET ConnectionReader {
58 PUBLISHED:
59  // The implementation here used to involve NSPR's multi-wait
60  // interface, but that got too complicated to manage. It turns out
61  // to be difficult to protect against memory leaks caused by race
62  // conditions in that interface, as designed.
63 
64  // Instead, we do our own multi-wait type stuff. Only one thread at
65  // a time can extract the next-available socket with activity on it.
66  // That thread will either (a) simply extract the next socket from
67  // the arrays returned by a previous call to PR_Poll(), or (b)
68  // execute (and possibly block on) a new call to PR_Poll().
69 
70  ConnectionReader(ConnectionManager *manager, int num_threads,
71  const string &thread_name = string());
72  virtual ~ConnectionReader();
73 
74  bool add_connection(Connection *connection);
75  bool remove_connection(Connection *connection);
76  bool is_connection_ok(Connection *connection);
77 
78  void poll();
79 
80  ConnectionManager *get_manager() const;
81  INLINE bool is_polling() const;
82  int get_num_threads() const;
83 
84  void set_raw_mode(bool mode);
85  bool get_raw_mode() const;
86 
87  void set_tcp_header_size(int tcp_header_size);
88  int get_tcp_header_size() const;
89 
90  void shutdown();
91 
92 protected:
93  virtual void flush_read_connection(Connection *connection);
94  virtual void receive_datagram(const NetDatagram &datagram)=0;
95 
96  class SocketInfo {
97  public:
98  SocketInfo(const PT(Connection) &connection);
99  bool is_udp() const;
100  Socket_IP *get_socket() const;
101 
102  PT(Connection) _connection;
103  bool _busy;
104  bool _error;
105  };
107 
108  void clear_manager();
109  void finish_socket(SocketInfo *sinfo);
110 
111  virtual bool process_incoming_data(SocketInfo *sinfo);
112  virtual bool process_incoming_udp_data(SocketInfo *sinfo);
113  virtual bool process_incoming_tcp_data(SocketInfo *sinfo);
114  virtual bool process_raw_incoming_udp_data(SocketInfo *sinfo);
115  virtual bool process_raw_incoming_tcp_data(SocketInfo *sinfo);
116 
117 protected:
118  ConnectionManager *_manager;
119 
120  // These structures track the total set of sockets (connections) we
121  // know about.
122  Sockets _sockets;
123  // This is the list of recently-removed sockets. We can't actually
124  // delete them until they're no longer _busy.
125  Sockets _removed_sockets;
126  // Any operations on _sockets are protected by this mutex.
127  LightMutex _sockets_mutex;
128 
129 private:
130  void thread_run(int thread_index);
131 
132  SocketInfo *get_next_available_socket(bool allow_block,
133  int current_thread_index);
134 
135  void rebuild_select_list();
136  void accumulate_fdset(Socket_fdset &fdset);
137 
138 private:
139  bool _raw_mode;
140  int _tcp_header_size;
141  bool _shutdown;
142 
143  class ReaderThread : public Thread {
144  public:
145  ReaderThread(ConnectionReader *reader, const string &thread_name,
146  int thread_index);
147  virtual void thread_main();
148 
149  ConnectionReader *_reader;
150  int _thread_index;
151  };
152 
154  Threads _threads;
155  bool _polling;
156 
157  // These structures are used to manage selecting for noise on
158  // available sockets.
159  Socket_fdset _fdset;
160  Sockets _selecting_sockets;
161  int _next_index;
162  int _num_results;
163  // Threads go to sleep on this mutex waiting for their chance to
164  // read a socket.
165  Mutex _select_mutex;
166 
167  // This is atomically updated with the index (in _threads) of the
168  // thread that is currently waiting on the PR_Poll() call. It
169  // contains -1 if no thread is so waiting.
170  AtomicAdjust::Integer _currently_polling_thread;
171 
172  friend class ConnectionManager;
173  friend class ReaderThread;
174 };
175 
176 #include "connectionReader.I"
177 
178 #endif
A specific kind of Datagram, especially for sending across or receiving from a network.
Definition: netDatagram.h:43
Base functionality for a INET domain Socket this call should be the starting point for all other unix...
Definition: socket_ip.h:34
The primary interface to the low-level networking layer in this package.
A standard mutex, or mutual exclusion lock.
Definition: pmutex.h:44
This is an abstract base class for a family of classes that listen for activity on a socket and respo...
A simple place to store and munipulate tcp and port address for communication layer.
A thread; that is, a lightweight process.
Definition: thread.h:51
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:45
Represents a single TCP or UDP socket for input or output.
Definition: connection.h:32