Panda3D
 All Classes Functions Variables Enumerations
datagramQueue.cxx
00001 // Filename: datagramQueue.cxx
00002 // Created by:  drose (08Feb00)
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 "datagramQueue.h"
00016 #include "config_net.h"
00017 #include "mutexHolder.h"
00018 
00019 ////////////////////////////////////////////////////////////////////
00020 //     Function: DatagramQueue::Constructor
00021 //       Access: Public
00022 //  Description:
00023 ////////////////////////////////////////////////////////////////////
00024 DatagramQueue::
00025 DatagramQueue() : 
00026   _cvlock("DatagramQueue::_cvlock"),
00027   _cv(_cvlock) 
00028 {
00029   _shutdown = false;
00030   _max_queue_size = get_net_max_write_queue();
00031 }
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: DatagramQueue::Destructor
00035 //       Access: Public
00036 //  Description:
00037 ////////////////////////////////////////////////////////////////////
00038 DatagramQueue::
00039 ~DatagramQueue() {
00040   // It's an error to delete a DatagramQueue without first shutting it
00041   // down (and waiting for any associated threads to terminate).
00042   nassertv(_shutdown);
00043 }
00044 
00045 ////////////////////////////////////////////////////////////////////
00046 //     Function: DatagramQueue::shutdown
00047 //       Access: Public
00048 //  Description: Marks the queue as shutting down, which will
00049 //               eventually cause all threads blocking on extract() to
00050 //               return false.  The normal way to delete a
00051 //               DatagramQueue will be to call first shutdown() and
00052 //               then wait for all known threads to terminate.  Then
00053 //               it is safe to delete the queue.
00054 ////////////////////////////////////////////////////////////////////
00055 void DatagramQueue::
00056 shutdown() {
00057   // Notify all of our threads that we're shutting down.  This will
00058   // cause any thread blocking on extract() to return false.
00059   MutexHolder holder(_cvlock);
00060 
00061   _shutdown = true;
00062   _cv.notify_all();
00063 }
00064 
00065 
00066 ////////////////////////////////////////////////////////////////////
00067 //     Function: DatagramQueue::insert
00068 //       Access: Public
00069 //  Description: Inserts the indicated datagram onto the end of the
00070 //               queue, and returns.  If the queue is empty and any
00071 //               threads are waiting on the queue, this will wake one
00072 //               of them up.  Returns true if successful, false if the
00073 //               queue was full.
00074 //
00075 //               If block is true, this will not return until
00076 //               successful, waiting until the queue has space
00077 //               available if necessary.
00078 ////////////////////////////////////////////////////////////////////
00079 bool DatagramQueue::
00080 insert(const NetDatagram &data, bool block) {
00081   MutexHolder holder(_cvlock);
00082 
00083   bool enqueue_ok = ((int)_queue.size() < _max_queue_size);
00084   if (block) {
00085     while (!enqueue_ok && !_shutdown) {
00086       _cv.wait();
00087       enqueue_ok = ((int)_queue.size() < _max_queue_size);
00088     }
00089   }
00090 
00091   if (enqueue_ok) {
00092     _queue.push_back(data);
00093   }
00094   _cv.notify();  // Only need to wake up one thread.
00095 
00096   return enqueue_ok;
00097 }
00098 
00099 
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: DatagramQueue::extract
00102 //       Access: Public
00103 //  Description: Extracts a datagram from the head of the queue, if
00104 //               one is available.  If a datagram is available, this
00105 //               will immediately return; otherwise, it will block
00106 //               until a datagram becomes available.  Multiple threads
00107 //               may simultaneously block on extract(); when a
00108 //               datagram is subsequently inserted into the queue, one
00109 //               of the threads will return from extract() with the
00110 //               datagram.
00111 //
00112 //               The return value is true if the datagram is
00113 //               successfully extracted, or false if the queue was
00114 //               destroyed while waiting.  (In the case of a false
00115 //               return, the thread should not attempt to operate on
00116 //               the queue again.)
00117 ////////////////////////////////////////////////////////////////////
00118 bool DatagramQueue::
00119 extract(NetDatagram &result) {
00120   // First, clear the datagram result in case it's got an outstanding
00121   // connection pointer--we're about to go to sleep for a while.
00122   result.clear();
00123 
00124   MutexHolder holder(_cvlock);
00125 
00126   while (_queue.empty() && !_shutdown) {
00127     _cv.wait();
00128   }
00129 
00130   if (_shutdown) {
00131     return false;
00132   }
00133 
00134   nassertr(!_queue.empty(), false);
00135   result = _queue.front();
00136   _queue.pop_front();
00137 
00138   // Wake up any threads waiting to stuff things into the queue.
00139   _cv.notify_all();
00140 
00141   return true;
00142 }
00143 
00144 ////////////////////////////////////////////////////////////////////
00145 //     Function: DatagramQueue::set_max_queue_size
00146 //       Access: Public
00147 //  Description: Sets the maximum size the queue is allowed to grow
00148 //               to.  This is primarily for a sanity check; this is a
00149 //               limit beyond which we can assume something bad has
00150 //               happened.
00151 //
00152 //               It's also a crude check against unfortunate seg
00153 //               faults due to the queue filling up and quietly
00154 //               consuming all available memory.
00155 ////////////////////////////////////////////////////////////////////
00156 void DatagramQueue::
00157 set_max_queue_size(int max_size) {
00158   MutexHolder holder(_cvlock);
00159   _max_queue_size = max_size;
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: DatagramQueue::get_max_queue_size
00164 //       Access: Public
00165 //  Description: Returns the maximum size the queue is allowed to grow
00166 //               to.  See set_max_queue_size().
00167 ////////////////////////////////////////////////////////////////////
00168 int DatagramQueue::
00169 get_max_queue_size() const {
00170   return _max_queue_size;
00171 }
00172 
00173 ////////////////////////////////////////////////////////////////////
00174 //     Function: DatagramQueue::get_current_queue_size
00175 //       Access: Public
00176 //  Description: Returns the current number of things in the queue.
00177 ////////////////////////////////////////////////////////////////////
00178 int DatagramQueue::
00179 get_current_queue_size() const {
00180   MutexHolder holder(_cvlock);
00181   int size = _queue.size();
00182   return size;
00183 }
 All Classes Functions Variables Enumerations