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