Panda3D
Loading...
Searching...
No Matches
queuedConnectionReader.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 queuedConnectionReader.cxx
10 * @author drose
11 * @date 2000-02-08
12 */
13
15#include "config_net.h"
16#include "trueClock.h"
17#include "lightMutexHolder.h"
18
19template class QueuedReturn<NetDatagram>;
20
21/**
22 *
23 */
24QueuedConnectionReader::
25QueuedConnectionReader(ConnectionManager *manager, int num_threads) :
26 ConnectionReader(manager, num_threads)
27{
28#ifdef SIMULATE_NETWORK_DELAY
29 _delay_active = false;
30 _min_delay = 0.0;
31 _delay_variance = 0.0;
32#endif // SIMULATE_NETWORK_DELAY
33}
34
35/**
36 *
37 */
38QueuedConnectionReader::
39~QueuedConnectionReader() {
40 // We call shutdown() here to guarantee that all threads are gone before the
41 // QueuedReturn destructs.
42 shutdown();
43}
44
45/**
46 * Returns true if a datagram is available on the queue; call get_data() to
47 * extract the datagram.
48 */
51 poll();
52#ifdef SIMULATE_NETWORK_DELAY
53 get_delayed();
54#endif // SIMULATE_NETWORK_DELAY
55 return thing_available();
56}
57
58/**
59 * If a previous call to data_available() returned true, this function will
60 * return the datagram that has become available.
61 *
62 * The return value is true if a datagram was successfully returned, or false
63 * if there was, in fact, no datagram available. (This may happen if there
64 * are multiple threads accessing the QueuedConnectionReader).
65 */
67get_data(NetDatagram &result) {
68 return get_thing(result);
69}
70
71/**
72 * This flavor of QueuedConnectionReader::get_data(), works like the other,
73 * except that it only fills a Datagram object, not a NetDatagram object.
74 * This means that the Datagram cannot be queried for its source Connection
75 * and/or NetAddress, but it is useful in all other respects.
76 */
78get_data(Datagram &result) {
79 NetDatagram nd;
80 if (!get_thing(nd)) {
81 return false;
82 }
83 result = nd;
84 return true;
85}
86
87/**
88 * An internal function called by ConnectionReader() when a new datagram has
89 * become available. The QueuedConnectionReader simply queues it up for later
90 * retrieval by get_data().
91 */
92void QueuedConnectionReader::
93receive_datagram(const NetDatagram &datagram) {
94 /*
95 if (net_cat.is_spam()) {
96 net_cat.spam()
97 << "Received datagram of " << datagram.get_length()
98 << " bytes\n";
99 }
100 */
101
102#ifdef SIMULATE_NETWORK_DELAY
103 delay_datagram(datagram);
104
105#else // SIMULATE_NETWORK_DELAY
106 if (!enqueue_thing(datagram)) {
107 net_cat.error()
108 << "QueuedConnectionReader queue full!\n";
109 }
110#endif // SIMULATE_NETWORK_DELAY
111}
112
113
114#ifdef SIMULATE_NETWORK_DELAY
115/**
116 * Enables a simulated network latency. All packets received from this point
117 * on will be held for a random interval of least min_delay seconds, and no
118 * more than max_delay seconds, before being visible to the
119 * data_available()/get_data() interface. It is as if packets suddenly took
120 * much longer to arrive.
121 */
122void QueuedConnectionReader::
123start_delay(double min_delay, double max_delay) {
124 LightMutexHolder holder(_dd_mutex);
125 _min_delay = min_delay;
126 _delay_variance = std::max(max_delay - min_delay, 0.0);
127 _delay_active = true;
128}
129
130/**
131 * Disables the simulated network latency started by a previous call to
132 * start_delay(). Packets will once again be visible as soon as they are
133 * received.
134 */
135void QueuedConnectionReader::
136stop_delay() {
137 LightMutexHolder holder(_dd_mutex);
138 _delay_active = false;
139
140 // Copy the entire contents of the delay queue to the normal queue.
141 while (!_delayed.empty()) {
142 const DelayedDatagram &dd = _delayed.front();
143 if (!enqueue_thing(dd._datagram)) {
144 net_cat.error()
145 << "QueuedConnectionReader queue full!\n";
146 }
147 _delayed.pop_front();
148 }
149}
150
151/**
152 * Checks the delayed queue for any now available datagrams, and adds them to
153 * the normal queue if they are available.
154 */
155void QueuedConnectionReader::
156get_delayed() {
157 if (_delay_active) {
158 LightMutexHolder holder(_dd_mutex);
159 double now = TrueClock::get_global_ptr()->get_short_time();
160 while (!_delayed.empty()) {
161 const DelayedDatagram &dd = _delayed.front();
162 if (dd._reveal_time > now) {
163 // Not yet.
164 break;
165 }
166 if (!enqueue_thing(dd._datagram)) {
167 net_cat.error()
168 << "QueuedConnectionReader queue full!\n";
169 }
170 _delayed.pop_front();
171 }
172 }
173}
174
175/**
176 * Adds the datagram to the delay queue for a random time interval.
177 */
178void QueuedConnectionReader::
179delay_datagram(const NetDatagram &datagram) {
180 if (!_delay_active) {
181 if (!enqueue_thing(datagram)) {
182 net_cat.error()
183 << "QueuedConnectionReader queue full!\n";
184 }
185 } else {
186 LightMutexHolder holder(_dd_mutex);
187 // Check the delay_active flag again, now that we have grabbed the mutex.
188 if (!_delay_active) {
189 if (!enqueue_thing(datagram)) {
190 net_cat.error()
191 << "QueuedConnectionReader queue full!\n";
192 }
193
194 } else {
195 double now = TrueClock::get_global_ptr()->get_short_time();
196 double reveal_time = now + _min_delay;
197
198 if (_delay_variance > 0.0) {
199 reveal_time += _delay_variance * ((double)rand() / (double)RAND_MAX);
200 }
201 _delayed.push_back(DelayedDatagram());
202 DelayedDatagram &dd = _delayed.back();
203 dd._reveal_time = reveal_time;
204 dd._datagram = datagram;
205 }
206 }
207}
208
209#endif // SIMULATE_NETWORK_DELAY
The primary interface to the low-level networking layer in this package.
This is an abstract base class for a family of classes that listen for activity on a socket and respo...
void poll()
Explicitly polls the available sockets to see if any of them have any noise.
void shutdown()
Terminates all threads cleanly.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
Similar to MutexHolder, but for a light mutex.
A specific kind of Datagram, especially for sending across or receiving from a network.
Definition netDatagram.h:40
bool get_data(NetDatagram &result)
If a previous call to data_available() returned true, this function will return the datagram that has...
bool data_available()
Returns true if a datagram is available on the queue; call get_data() to extract the datagram.
This is the implementation of a family of things that queue up their return values for later retrieva...
static TrueClock * get_global_ptr()
Returns a pointer to the one TrueClock object in the world.
Definition trueClock.I:68
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.