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 }