Panda3D
|
00001 // Filename: datagramGeneratorNet.cxx 00002 // Created by: drose (15Feb09) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "pandabase.h" 00016 00017 #include "datagramGeneratorNet.h" 00018 #include "mutexHolder.h" 00019 #include "lightMutexHolder.h" 00020 00021 //////////////////////////////////////////////////////////////////// 00022 // Function: DatagramGeneratorNet::Constructor 00023 // Access: Published 00024 // Description: Creates a new DatagramGeneratorNet with the indicated 00025 // number of threads to handle requests. Normally 00026 // num_threads should be either 0 or 1 to guarantee that 00027 // datagrams are generated in the same order in which 00028 // they were received. 00029 //////////////////////////////////////////////////////////////////// 00030 DatagramGeneratorNet:: 00031 DatagramGeneratorNet(ConnectionManager *manager, int num_threads) : 00032 ConnectionReader(manager, num_threads), 00033 _dg_received(_dg_lock), 00034 _dg_processed(_dg_lock) 00035 { 00036 } 00037 00038 //////////////////////////////////////////////////////////////////// 00039 // Function: DatagramGeneratorNet::Destructor 00040 // Access: Published, Virtual 00041 // Description: 00042 //////////////////////////////////////////////////////////////////// 00043 DatagramGeneratorNet:: 00044 ~DatagramGeneratorNet() { 00045 } 00046 00047 //////////////////////////////////////////////////////////////////// 00048 // Function: DatagramGeneratorNet::get_datagram 00049 // Access: Published, Virtual 00050 // Description: Reads the next datagram from the stream. Blocks 00051 // until a datagram is available. Returns true on 00052 // success, false on stream closed or error. 00053 //////////////////////////////////////////////////////////////////// 00054 bool DatagramGeneratorNet:: 00055 get_datagram(Datagram &data) { 00056 if (is_polling()) { 00057 // Single-threaded case: we poll. No need to lock. 00058 if (!thing_available()) { 00059 if (net_cat.is_spam()) { 00060 net_cat.spam() 00061 << "DatagramGeneratorNet polling\n"; 00062 } 00063 poll(); 00064 } 00065 while (!thing_available()) { 00066 if (is_eof()) { 00067 if (net_cat.is_spam()) { 00068 net_cat.spam() 00069 << "DatagramGeneratorNet returning EOF\n"; 00070 } 00071 return false; 00072 } 00073 poll(); 00074 Thread::force_yield(); 00075 } 00076 bool got_dg = get_thing(data); 00077 nassertr(got_dg, false); 00078 00079 } else { 00080 // Threaded case: no polling, we use mutexes and cvars to block 00081 // instead. 00082 MutexHolder holder(_dg_lock); 00083 while (!thing_available()) { 00084 if (is_eof()) { 00085 if (net_cat.is_spam()) { 00086 net_cat.spam() 00087 << "DatagramGeneratorNet returning EOF\n"; 00088 } 00089 return false; 00090 } 00091 if (net_cat.is_spam()) { 00092 net_cat.spam() 00093 << "DatagramGeneratorNet waiting\n"; 00094 } 00095 _dg_received.wait(); 00096 } 00097 bool got_dg = get_thing(data); 00098 nassertr(got_dg, false); 00099 _dg_processed.notify(); 00100 } 00101 00102 if (net_cat.is_spam()) { 00103 net_cat.spam() 00104 << "DatagramGeneratorNet returning datagram of length " 00105 << data.get_length() << "\n"; 00106 } 00107 00108 return true; 00109 } 00110 00111 //////////////////////////////////////////////////////////////////// 00112 // Function: DatagramGeneratorNet::is_eof 00113 // Access: Published, Virtual 00114 // Description: Returns true if the stream has been closed normally. 00115 // This test may only be made after a call to 00116 // get_datagram() has failed. 00117 //////////////////////////////////////////////////////////////////// 00118 bool DatagramGeneratorNet:: 00119 is_eof() { 00120 // We're at eof if we have no more connected sockets. 00121 LightMutexHolder holder(_sockets_mutex); 00122 return _sockets.empty(); 00123 } 00124 00125 //////////////////////////////////////////////////////////////////// 00126 // Function: DatagramGeneratorNet::is_error 00127 // Access: Published, Virtual 00128 // Description: Returns true if the stream has an error condition. 00129 //////////////////////////////////////////////////////////////////// 00130 bool DatagramGeneratorNet:: 00131 is_error() { 00132 // There's an error if any one of our connected sockets reports an error. 00133 LightMutexHolder holder(_sockets_mutex); 00134 Sockets::const_iterator si; 00135 for (si = _sockets.begin(); si != _sockets.end(); ++si) { 00136 SocketInfo *sinfo = (*si); 00137 if (sinfo->_error) { 00138 return true; 00139 } 00140 } 00141 00142 return false; 00143 } 00144 00145 //////////////////////////////////////////////////////////////////// 00146 // Function: DatagramGeneratorNet::receive_datagram 00147 // Access: Protected, Virtual 00148 // Description: An internal function called by ConnectionReader() 00149 // when a new datagram has become available. This call 00150 // may be received in a sub-thread. 00151 //////////////////////////////////////////////////////////////////// 00152 void DatagramGeneratorNet:: 00153 receive_datagram(const NetDatagram &datagram) { 00154 MutexHolder holder(_dg_lock); 00155 while (!enqueue_thing(datagram)) { 00156 _dg_processed.wait(); 00157 } 00158 _dg_received.notify(); 00159 } 00160