Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/net/queuedConnectionReader.cxx

Go to the documentation of this file.
00001 // Filename: queuedConnectionReader.cxx
00002 // Created by:  drose (08Feb00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "queuedConnectionReader.h"
00020 #include "config_net.h"
00021 #include "clockObject.h"
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: QueuedConnectionReader::Constructor
00025 //       Access: Published
00026 //  Description:
00027 ////////////////////////////////////////////////////////////////////
00028 QueuedConnectionReader::
00029 QueuedConnectionReader(ConnectionManager *manager, int num_threads) :
00030   ConnectionReader(manager, num_threads)
00031 {
00032 #ifdef SIMULATE_NETWORK_DELAY
00033   _dd_mutex = PR_NewLock();
00034   _delay_active = false;
00035   _min_delay = 0.0;
00036   _delay_variance = 0.0;
00037 #endif  // SIMULATE_NETWORK_DELAY
00038 }
00039 
00040 ////////////////////////////////////////////////////////////////////
00041 //     Function: QueuedConnectionReader::Destructor
00042 //       Access: Published, Virtual
00043 //  Description:
00044 ////////////////////////////////////////////////////////////////////
00045 QueuedConnectionReader::
00046 ~QueuedConnectionReader() {
00047   // We call shutdown() here to guarantee that all threads are gone
00048   // before the QueuedReturn destructs.
00049   shutdown();
00050 
00051 #ifdef SIMULATE_NETWORK_DELAY
00052   PR_DestroyLock(_dd_mutex);
00053 #endif  // SIMULATE_NETWORK_DELAY
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: QueuedConnectionReader::data_available
00058 //       Access: Published
00059 //  Description: Returns true if a datagram is available on the queue;
00060 //               call get_data() to extract the datagram.
00061 ////////////////////////////////////////////////////////////////////
00062 bool QueuedConnectionReader::
00063 data_available() {
00064   poll();
00065 #ifdef SIMULATE_NETWORK_DELAY
00066   get_delayed();  
00067 #endif  // SIMULATE_NETWORK_DELAY
00068   return thing_available();
00069 }
00070 
00071 ////////////////////////////////////////////////////////////////////
00072 //     Function: QueuedConnectionReader::get_data
00073 //       Access: Published
00074 //  Description: If a previous call to data_available() returned
00075 //               true, this function will return the datagram that has
00076 //               become available.
00077 //
00078 //               The return value is true if a datagram was
00079 //               successfully returned, or false if there was, in
00080 //               fact, no datagram available.  (This may happen if
00081 //               there are multiple threads accessing the
00082 //               QueuedConnectionReader).
00083 ////////////////////////////////////////////////////////////////////
00084 bool QueuedConnectionReader::
00085 get_data(NetDatagram &result) {
00086   return get_thing(result);
00087 }
00088 
00089 ////////////////////////////////////////////////////////////////////
00090 //     Function: QueuedConnectionReader::get_data
00091 //       Access: Published
00092 //  Description: This flavor of QueuedConnectionReader::get_data(),
00093 //               works like the other, except that it only fills a
00094 //               Datagram object, not a NetDatagram object.  This
00095 //               means that the Datagram cannot be queried for its
00096 //               source Connection and/or NetAddress, but it is useful
00097 //               in all other respects.
00098 ////////////////////////////////////////////////////////////////////
00099 bool QueuedConnectionReader::
00100 get_data(Datagram &result) {
00101   NetDatagram nd;
00102   if (!get_thing(nd)) {
00103     return false;
00104   }
00105   result = nd;
00106   return true;
00107 }
00108 
00109 ////////////////////////////////////////////////////////////////////
00110 //     Function: QueuedConnectionReader::receive_datagram
00111 //       Access: Protected, Virtual
00112 //  Description: An internal function called by ConnectionReader()
00113 //               when a new datagram has become available.  The
00114 //               QueuedConnectionReader simply queues it up for later
00115 //               retrieval by get_data().
00116 ////////////////////////////////////////////////////////////////////
00117 void QueuedConnectionReader::
00118 receive_datagram(const NetDatagram &datagram) {
00119   /*
00120   if (net_cat.is_spam()) {
00121     net_cat.spam()
00122       << "Received datagram of " << datagram.get_length()
00123       << " bytes\n";
00124   }
00125   */
00126 
00127 #ifdef SIMULATE_NETWORK_DELAY
00128   delay_datagram(datagram);
00129 
00130 #else  // SIMULATE_NETWORK_DELAY
00131   if (!enqueue_thing(datagram)) {
00132     net_cat.error()
00133       << "QueuedConnectionReader queue full!\n";
00134   }
00135 #endif  // SIMULATE_NETWORK_DELAY
00136 }
00137 
00138 
00139 #ifdef SIMULATE_NETWORK_DELAY
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: QueuedConnectionReader::start_delay
00142 //       Access: Published
00143 //  Description: Enables a simulated network latency.  All packets
00144 //               received from this point on will be held for a random
00145 //               interval of least min_delay seconds, and no more than
00146 //               max_delay seconds, before being visible to the
00147 //               data_available()/get_data() interface.  It is as if
00148 //               packets suddenly took much longer to arrive.
00149 ////////////////////////////////////////////////////////////////////
00150 void QueuedConnectionReader::
00151 start_delay(double min_delay, double max_delay) {
00152   PR_Lock(_dd_mutex);
00153   _min_delay = min_delay;
00154   _delay_variance = max(max_delay - min_delay, 0.0);
00155   _delay_active = true;
00156   PR_Unlock(_dd_mutex);
00157 }
00158 
00159 ////////////////////////////////////////////////////////////////////
00160 //     Function: QueuedConnectionReader::stop_delay
00161 //       Access: Published
00162 //  Description: Disables the simulated network latency started by a
00163 //               previous call to start_delay().  Packets will once
00164 //               again be visible as soon as they are received.
00165 ////////////////////////////////////////////////////////////////////
00166 void QueuedConnectionReader::
00167 stop_delay() {
00168   PR_Lock(_dd_mutex);
00169   _delay_active = false;
00170 
00171   // Copy the entire contents of the delay queue to the normal queue.
00172   while (!_delayed.empty()) {
00173     const DelayedDatagram &dd = _delayed.front();
00174     if (!enqueue_thing(dd._datagram)) {
00175       net_cat.error()
00176         << "QueuedConnectionReader queue full!\n";
00177     }
00178     _delayed.pop_front();
00179   }
00180     
00181   PR_Unlock(_dd_mutex);
00182 }
00183 
00184 ////////////////////////////////////////////////////////////////////
00185 //     Function: QueuedConnectionReader::get_delayed
00186 //       Access: Private
00187 //  Description: Checks the delayed queue for any now available
00188 //               datagrams, and adds them to the normal queue if they
00189 //               are available.
00190 ////////////////////////////////////////////////////////////////////
00191 void QueuedConnectionReader::
00192 get_delayed() {
00193   if (_delay_active) {
00194     PR_Lock(_dd_mutex);
00195     double now = ClockObject::get_global_clock()->get_real_time();
00196     while (!_delayed.empty()) {
00197       const DelayedDatagram &dd = _delayed.front();
00198       if (dd._reveal_time > now) {
00199         // Not yet.
00200         break;
00201       }
00202       if (!enqueue_thing(dd._datagram)) {
00203         net_cat.error()
00204           << "QueuedConnectionReader queue full!\n";
00205       }
00206       _delayed.pop_front();
00207     }
00208     PR_Unlock(_dd_mutex);
00209   }
00210 }
00211 
00212 ////////////////////////////////////////////////////////////////////
00213 //     Function: QueuedConnectionReader::delay_datagram
00214 //       Access: Private
00215 //  Description: Adds the datagram to the delay queue for a random
00216 //               time interval.
00217 ////////////////////////////////////////////////////////////////////
00218 void QueuedConnectionReader::
00219 delay_datagram(const NetDatagram &datagram) {
00220   if (!_delay_active) {
00221     if (!enqueue_thing(datagram)) {
00222       net_cat.error()
00223         << "QueuedConnectionReader queue full!\n";
00224     }
00225   } else {
00226     PR_Lock(_dd_mutex);
00227     // Check the delay_active flag again, now that we have grabbed the
00228     // mutex.
00229     if (!_delay_active) {
00230       if (!enqueue_thing(datagram)) {
00231         net_cat.error()
00232           << "QueuedConnectionReader queue full!\n";
00233       }
00234 
00235     } else {
00236       double now = ClockObject::get_global_clock()->get_real_time();
00237       double reveal_time = now + _min_delay;
00238       
00239       if (_delay_variance > 0.0) {
00240         reveal_time += _delay_variance * ((double)rand() / (double)RAND_MAX);
00241       }
00242       _delayed.push_back(DelayedDatagram());
00243       DelayedDatagram &dd = _delayed.back();
00244       dd._reveal_time = reveal_time;
00245       dd._datagram = datagram;
00246     }
00247     PR_Unlock(_dd_mutex);
00248   }
00249 }
00250 
00251 #endif  // SIMULATE_NETWORK_DELAY

Generated on Fri May 2 00:40:36 2003 for Panda by doxygen1.3