00001 // Filename: queuedReturn.I 00002 // Created by: drose (25Feb00) 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 "config_net.h" 00020 00021 #include <algorithm> 00022 00023 //////////////////////////////////////////////////////////////////// 00024 // Function: QueuedReturn::set_max_queue_size 00025 // Access: Public 00026 // Description: Sets the maximum size the queue is allowed to grow 00027 // to. This is primarily for a sanity check; this is a 00028 // limit beyond which we can assume something bad has 00029 // happened. 00030 // 00031 // It's also a crude check against unfortunate seg 00032 // faults due to the queue filling up and quietly 00033 // consuming all available memory. 00034 //////////////////////////////////////////////////////////////////// 00035 template<class Thing> 00036 void QueuedReturn<Thing>:: 00037 set_max_queue_size(int max_size) { 00038 PR_Lock(_mutex); 00039 _max_queue_size = max_size; 00040 PR_Unlock(_mutex); 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: QueuedReturn::get_max_queue_size 00045 // Access: Public 00046 // Description: Returns the maximum size the queue is allowed to grow 00047 // to. See set_max_queue_size(). 00048 //////////////////////////////////////////////////////////////////// 00049 template<class Thing> 00050 int QueuedReturn<Thing>:: 00051 get_max_queue_size() const { 00052 return _max_queue_size; 00053 } 00054 00055 //////////////////////////////////////////////////////////////////// 00056 // Function: QueuedReturn::get_current_queue_size 00057 // Access: Public 00058 // Description: Returns the current number of things in the queue. 00059 //////////////////////////////////////////////////////////////////// 00060 template<class Thing> 00061 int QueuedReturn<Thing>:: 00062 get_current_queue_size() const { 00063 PR_Lock(_mutex); 00064 int size = _things.size(); 00065 PR_Unlock(_mutex); 00066 return size; 00067 } 00068 00069 //////////////////////////////////////////////////////////////////// 00070 // Function: QueuedReturn::Constructor 00071 // Access: Protected 00072 // Description: 00073 //////////////////////////////////////////////////////////////////// 00074 template<class Thing> 00075 QueuedReturn<Thing>:: 00076 QueuedReturn() { 00077 _mutex = PR_NewLock(); 00078 _available = false; 00079 _max_queue_size = get_net_max_response_queue(); 00080 } 00081 00082 //////////////////////////////////////////////////////////////////// 00083 // Function: QueuedReturn::Destructor 00084 // Access: Protected 00085 // Description: 00086 //////////////////////////////////////////////////////////////////// 00087 template<class Thing> 00088 QueuedReturn<Thing>:: 00089 ~QueuedReturn() { 00090 PR_DestroyLock(_mutex); 00091 } 00092 00093 //////////////////////////////////////////////////////////////////// 00094 // Function: QueuedReturn::thing_available 00095 // Access: Protected 00096 // Description: Returns true if a thing is available on the queue; 00097 // call get_thing() to extract the thing. 00098 //////////////////////////////////////////////////////////////////// 00099 template<class Thing> 00100 INLINE bool QueuedReturn<Thing>:: 00101 thing_available() const { 00102 return _available; 00103 } 00104 00105 //////////////////////////////////////////////////////////////////// 00106 // Function: QueuedReturn::get_thing 00107 // Access: Protected 00108 // Description: If a previous call to thing_available() returned 00109 // true, this function will return the thing that has 00110 // become available. 00111 // 00112 // The return value is true if a thing was 00113 // successfully returned, or false if there was, in 00114 // fact, no thing available. (This may happen if 00115 // there are multiple threads accessing the 00116 // QueuedReturn). 00117 //////////////////////////////////////////////////////////////////// 00118 template<class Thing> 00119 bool QueuedReturn<Thing>:: 00120 get_thing(Thing &result) { 00121 PR_Lock(_mutex); 00122 if (_things.empty()) { 00123 // Huh. Nothing after all. 00124 _available = false; 00125 PR_Unlock(_mutex); 00126 return false; 00127 } 00128 00129 result = _things.front(); 00130 _things.pop_front(); 00131 _available = !_things.empty(); 00132 PR_Unlock(_mutex); 00133 return true; 00134 } 00135 00136 //////////////////////////////////////////////////////////////////// 00137 // Function: QueuedReturn::enqueue_thing 00138 // Access: Protected 00139 // Description: Adds a new thing to the queue for later retrieval. 00140 // Returns true if successful, false if the queue is 00141 // full (i.e. has reached _max_queue_size). 00142 //////////////////////////////////////////////////////////////////// 00143 template<class Thing> 00144 bool QueuedReturn<Thing>:: 00145 enqueue_thing(const Thing &thing) { 00146 PR_Lock(_mutex); 00147 bool enqueue_ok = ((int)_things.size() < _max_queue_size); 00148 if (enqueue_ok) { 00149 _things.push_back(thing); 00150 } 00151 _available = true; 00152 PR_Unlock(_mutex); 00153 00154 return enqueue_ok; 00155 } 00156 00157 //////////////////////////////////////////////////////////////////// 00158 // Function: QueuedReturn::enqueue_unique_thing 00159 // Access: Protected 00160 // Description: The same as enqueue_thing(), except the queue is 00161 // first checked that it doesn't already have something 00162 // like thing. The return value is true if the enqueue 00163 // operation was successful, false if the queue was full 00164 // or the thing was already on the queue. 00165 //////////////////////////////////////////////////////////////////// 00166 template<class Thing> 00167 bool QueuedReturn<Thing>:: 00168 enqueue_unique_thing(const Thing &thing) { 00169 PR_Lock(_mutex); 00170 bool enqueue_ok = ((int)_things.size() < _max_queue_size); 00171 if (enqueue_ok) { 00172 if (find(_things.begin(), _things.end(), thing) == _things.end()) { 00173 // It wasn't there already; add it now. 00174 _things.push_back(thing); 00175 } else { 00176 // It was already there; return false to indicate this. 00177 enqueue_ok = false; 00178 } 00179 } 00180 _available = true; 00181 PR_Unlock(_mutex); 00182 00183 return enqueue_ok; 00184 }