Panda3D
Loading...
Searching...
No Matches
pStatServer.cxx
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 pStatServer.cxx
10 * @author drose
11 * @date 2000-07-09
12 */
13
14#include "pStatServer.h"
15#include "pStatReader.h"
16#include "thread.h"
17#include "config_pstatclient.h"
18
19/**
20 *
21 */
22PStatServer::
23PStatServer() {
24 _listener = new PStatListener(this);
25 _next_udp_port = 0;
26}
27
28/**
29 *
30 */
31PStatServer::
32~PStatServer() {
33 delete _listener;
34}
35
36
37/**
38 * Establishes a port number that the manager will listen on for TCP
39 * connections. This may be called more than once to listen simulataneously
40 * on multiple connections, as if that were at all useful.
41 *
42 * The default parameter, -1, indicates the use of whatever port number has
43 * been indicated in the Config file.
44 *
45 * This function returns true if the port was successfully opened, or false if
46 * it could not open the port.
47 */
49listen(int port) {
50 if (port < 0) {
51 port = pstats_port;
52 }
53
54 // Now try to listen to the port.
55 PT(Connection) rendezvous = open_TCP_server_rendezvous(port, 5);
56
57 if (rendezvous.is_null()) {
58 // Couldn't get it.
59 return false;
60 }
61
62 // Tell the listener about the new port.
63 _listener->add_connection(rendezvous);
64
65 if (_next_udp_port == 0) {
66 _next_udp_port = port + 1;
67 }
68 return true;
69}
70
71
72/**
73 * Checks for any network activity and handles it, if appropriate, and then
74 * returns. This must be called periodically unless is_thread_safe() is
75 * redefined to return true on this class and also on all PStatMonitors in
76 * use.
77 *
78 * Alternatively, a program may call main_loop() and yield control of the
79 * program entirely to the PStatServer.
80 */
82poll() {
83 // Delete all the readers that we couldn't delete before.
84 while (!_lost_readers.empty()) {
85 PStatReader *reader = _lost_readers.back();
86 _lost_readers.pop_back();
87
88 reader->lost_connection();
89 delete reader;
90 }
91 while (!_removed_readers.empty()) {
92 PStatReader *reader = _removed_readers.back();
93 _removed_readers.pop_back();
94 delete reader;
95 }
96
97 _listener->poll();
98
99 Readers::const_iterator ri = _readers.begin();
100 while (ri != _readers.end()) {
101 // Preincrement the iterator, in case we remove it as a result of calling
102 // poll().
103 Readers::const_iterator rnext = ri;
104 ++rnext;
105 PStatReader *reader = (*ri).second;
106
107 reader->poll();
108 reader->idle();
109
110 ri = rnext;
111 }
112}
113
114/**
115 * An alternative to repeatedly calling poll(), this function yields control
116 * of the program to the PStatServer. It does not return until the program is
117 * done.
118 *
119 * If interrupt_flag is non-NULL, it is the address of a bool variable that is
120 * initially false, and may be asynchronously set true to indicate the loop
121 * should terminate.
122 */
124main_loop(bool *interrupt_flag) {
125 while (interrupt_flag == nullptr || !*interrupt_flag) {
126 poll();
127 Thread::sleep(0.1);
128 }
129}
130
131/**
132 * Adds the newly-created PStatReader to the list of currently active readers.
133 */
135add_reader(Connection *connection, PStatReader *reader) {
136 _readers[connection] = reader;
137}
138
139/**
140 * Removes the indicated reader.
141 */
143remove_reader(Connection *connection, PStatReader *reader) {
144 Readers::iterator ri;
145 ri = _readers.find(connection);
146 if (ri == _readers.end() || (*ri).second != reader) {
147 nout << "Attempt to remove undefined reader.\n";
148 } else {
149 _readers.erase(ri);
150 _removed_readers.push_back(reader);
151 }
152}
153
154/**
155 * Returns a new port number that will probably be free to use as a UDP port.
156 * The caller should be prepared to accept the possibility that it will be
157 * already in use by another process, however.
158 */
160get_udp_port() {
161 if (_available_udp_ports.empty()) {
162 return _next_udp_port++;
163 }
164 int udp_port = _available_udp_ports.front();
165 _available_udp_ports.pop_front();
166 return udp_port;
167}
168
169/**
170 * Indicates that the given UDP port is once again free for use.
171 */
173release_udp_port(int port) {
174 _available_udp_ports.push_back(port);
175}
176
177/**
178 * Returns the current number of user-defined guide bars.
179 */
182 return _user_guide_bars.size();
183}
184
185/**
186 * Returns the height of the nth user-defined guide bar.
187 */
189get_user_guide_bar_height(int n) const {
190 nassertr(n >= 0 && n < (int)_user_guide_bars.size(), 0.0f);
191 return _user_guide_bars[n];
192}
193
194/**
195 * Adjusts the height of the nth user-defined guide bar.
196 */
198move_user_guide_bar(int n, double height) {
199 nassertv(n >= 0 && n < (int)_user_guide_bars.size());
200 _user_guide_bars[n] = height;
201 user_guide_bars_changed();
202}
203
204/**
205 * Creates a new user guide bar and returns its index number.
206 */
208add_user_guide_bar(double height) {
209 int n = (int)_user_guide_bars.size();
210 _user_guide_bars.push_back(height);
211 user_guide_bars_changed();
212
213 return n;
214}
215
216/**
217 * Removes the user guide bar with the indicated index number. All subsequent
218 * index numbers are adjusted down one.
219 */
222 nassertv(n >= 0 && n < (int)_user_guide_bars.size());
223 _user_guide_bars.erase(_user_guide_bars.begin() + n);
224 user_guide_bars_changed();
225}
226
227/**
228 * Returns the index number of the first user guide bar found whose height is
229 * within the indicated range, or -1 if no user guide bars fall within the
230 * range.
231 */
233find_user_guide_bar(double from_height, double to_height) const {
234 GuideBars::const_iterator gbi;
235 for (gbi = _user_guide_bars.begin();
236 gbi != _user_guide_bars.end();
237 ++gbi) {
238 double height = (*gbi);
239 if (height >= from_height && height <= to_height) {
240 return (int)(gbi - _user_guide_bars.begin());
241 }
242 }
243
244 return -1;
245}
246
247/**
248 * Called when the user guide bars have been changed.
249 */
250void PStatServer::
251user_guide_bars_changed() {
252 Readers::iterator ri;
253 for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
254 (*ri).second->get_monitor()->user_guide_bars_changed();
255 }
256}
257
258/**
259 * This should be redefined to return true in derived classes that want to
260 * deal with multithreaded readers and such. If this returns true, the
261 * manager will create the listener in its own thread, and thus the
262 * PStatReader constructors at least will run in a different thread.
263 *
264 * This is not related to the question of whether the reader can handle
265 * multiple different PStatThreadDatas; it's strictly a question of whether
266 * the readers themselves can run in a separate thread.
267 */
270 return false;
271}
272
273/**
274 * Called when a lost connection is detected by the net code, this should pass
275 * the word on to the interested parties and clean up gracefully.
276 */
277void PStatServer::
278connection_reset(const PT(Connection) &connection, bool okflag) {
279 // Was this a client connection? Tell the reader about it if it was.
280 close_connection(connection);
281
282 Readers::iterator ri;
283 ri = _readers.find(connection);
284 if (ri != _readers.end()) {
285 PStatReader *reader = (*ri).second;
286 _readers.erase(ri);
287
288 // Unfortunately, we can't delete the reader right away, because we might
289 // have been called from a method on the reader! We'll have to save the
290 // reader pointer and delete it some time later.
291 _lost_readers.push_back(reader);
292 }
293}
PT(Connection) open_TCP_client_connection(const std bool close_connection(const PT(Connection) &connection)
Terminates a UDP or TCP socket previously opened.
void poll()
Explicitly polls the available sockets to see if any of them have any noise.
bool add_connection(Connection *connection)
Adds a new socket to the list of sockets the ConnectionReader will monitor.
Represents a single TCP or UDP socket for input or output.
Definition connection.h:29
This is the TCP rendezvous socket listener.
This is the class that does all the work for handling communications from a single Panda client.
Definition pStatReader.h:41
void lost_connection()
This is called by the PStatServer when it detects that the connection has been lost.
void idle()
Called each frame to do what needs to be done for the monitor's user- defined idle routines.
void remove_user_guide_bar(int n)
Removes the user guide bar with the indicated index number.
int add_user_guide_bar(double height)
Creates a new user guide bar and returns its index number.
virtual bool is_thread_safe()
This should be redefined to return true in derived classes that want to deal with multithreaded reade...
void main_loop(bool *interrupt_flag=nullptr)
An alternative to repeatedly calling poll(), this function yields control of the program to the PStat...
void move_user_guide_bar(int n, double height)
Adjusts the height of the nth user-defined guide bar.
void remove_reader(Connection *connection, PStatReader *reader)
Removes the indicated reader.
void poll()
Checks for any network activity and handles it, if appropriate, and then returns.
int get_num_user_guide_bars() const
Returns the current number of user-defined guide bars.
void add_reader(Connection *connection, PStatReader *reader)
Adds the newly-created PStatReader to the list of currently active readers.
bool listen(int port=-1)
Establishes a port number that the manager will listen on for TCP connections.
void release_udp_port(int port)
Indicates that the given UDP port is once again free for use.
int get_udp_port()
Returns a new port number that will probably be free to use as a UDP port.
double get_user_guide_bar_height(int n) const
Returns the height of the nth user-defined guide bar.
int find_user_guide_bar(double from_height, double to_height) const
Returns the index number of the first user guide bar found whose height is within the indicated range...
static void sleep(double seconds)
Suspends the current thread for at least the indicated amount of time.
Definition thread.I:192
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.