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