Panda3D
 All Classes Functions Variables Enumerations
datagramGeneratorNet.cxx
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 
 All Classes Functions Variables Enumerations