|
reSIProcate/rutil
9694
|
00001 #if !defined(RESIP_SHAREDCOUNT_HXX) 00002 #define RESIP_SHAREDCOUNT_HXX 00003 00012 #include <memory> // std::auto_ptr, std::allocator 00013 #include <functional> // std::less 00014 #include <exception> // std::exception 00015 #include <new> // std::bad_alloc 00016 #include <typeinfo> // std::type_info in get_deleter 00017 #include <cstddef> // std::size_t 00018 #include "rutil/Lock.hxx" 00019 #include "rutil/Mutex.hxx" 00020 //#include "rutil/Logger.hxx" 00021 00022 #ifdef __BORLANDC__ 00023 # pragma warn -8026 // Functions with excep. spec. are not expanded inline 00024 # pragma warn -8027 // Functions containing try are not expanded inline 00025 #endif 00026 00027 namespace resip 00028 { 00029 00030 // verify that types are complete for increased safety 00031 template<class T> inline void checked_delete(T * x) 00032 { 00033 // intentionally complex - simplification causes regressions 00034 typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; 00035 (void) sizeof(type_must_be_complete); 00036 delete x; 00037 }; 00038 00039 template<class T> struct checked_deleter 00040 { 00041 typedef void result_type; 00042 typedef T * argument_type; 00043 00044 void operator()(T * x) const 00045 { 00046 // resip:: disables ADL 00047 resip::checked_delete(x); 00048 } 00049 }; 00050 00051 // The standard library that comes with Borland C++ 5.5.1 00052 // defines std::exception and its members as having C calling 00053 // convention (-pc). When the definition of bad_weak_ptr 00054 // is compiled with -ps, the compiler issues an error. 00055 // Hence, the temporary #pragma option -pc below. The version 00056 // check is deliberately conservative. 00057 #if defined(__BORLANDC__) && __BORLANDC__ == 0x551 00058 # pragma option push -pc 00059 #endif 00060 00061 class bad_weak_ptr: public std::exception 00062 { 00063 public: 00064 00065 virtual char const * what() const throw() 00066 { 00067 return "resip::bad_weak_ptr"; 00068 } 00069 }; 00070 00071 #if defined(__BORLANDC__) && __BORLANDC__ == 0x551 00072 # pragma option pop 00073 #endif 00074 00075 class sp_counted_base 00076 { 00077 private: 00078 00079 public: 00080 00081 sp_counted_base(): use_count_(1), weak_count_(1) 00082 { 00083 } 00084 00085 virtual ~sp_counted_base() // nothrow 00086 { 00087 } 00088 00089 // dispose() is called when use_count_ drops to zero, to release 00090 // the resources managed by *this. 00091 virtual void dispose() = 0; // nothrow 00092 00093 // destruct() is called when weak_count_ drops to zero. 00094 virtual void destruct() // nothrow 00095 { 00096 delete this; 00097 } 00098 00099 virtual void * get_deleter(std::type_info const & ti) = 0; 00100 00101 void add_ref_copy() 00102 { 00103 Lock lock(mMutex); (void)lock; 00104 ++use_count_; 00105 //GenericLog(Subsystem::SIP, resip::Log::Info, << "********* SharedCount::add_ref_copy: " << use_count_); 00106 } 00107 00108 void add_ref_lock() 00109 { 00110 Lock lock(mMutex); (void)lock; 00111 // if(use_count_ == 0) throw(resip::bad_weak_ptr()); 00112 if (use_count_ == 0) throw resip::bad_weak_ptr(); 00113 ++use_count_; 00114 //GenericLog(Subsystem::SIP, resip::Log::Info, << "********* SharedCount::add_ref_lock: " << use_count_); 00115 } 00116 00117 void release() // nothrow 00118 { 00119 { 00120 Lock lock(mMutex); (void)lock; 00121 long new_use_count = --use_count_; 00122 //GenericLog(Subsystem::SIP, resip::Log::Info, << "********* SharedCount::release: " << use_count_); 00123 00124 if(new_use_count != 0) return; 00125 } 00126 00127 dispose(); 00128 weak_release(); 00129 } 00130 00131 void weak_add_ref() // nothrow 00132 { 00133 Lock lock(mMutex); (void)lock; 00134 ++weak_count_; 00135 } 00136 00137 void weak_release() // nothrow 00138 { 00139 long new_weak_count; 00140 00141 { 00142 Lock lock(mMutex); (void)lock; 00143 new_weak_count = --weak_count_; 00144 } 00145 00146 if(new_weak_count == 0) 00147 { 00148 destruct(); 00149 } 00150 } 00151 00152 long use_count() const // nothrow 00153 { 00154 Lock lock(mMutex); (void)lock; 00155 return use_count_; 00156 } 00157 00158 private: 00159 00160 sp_counted_base(sp_counted_base const &); 00161 sp_counted_base & operator= (sp_counted_base const &); 00162 00163 long use_count_; // #shared 00164 long weak_count_; // #weak + (#shared != 0) 00165 00166 mutable Mutex mMutex; 00167 }; 00168 00169 // 00170 // Borland's Codeguard trips up over the -Vx- option here: 00171 // 00172 #ifdef __CODEGUARD__ 00173 # pragma option push -Vx- 00174 #endif 00175 00176 template<class P, class D> class sp_counted_base_impl: public sp_counted_base 00177 { 00178 private: 00179 00180 P ptr; // copy constructor must not throw 00181 D del; // copy constructor must not throw 00182 00183 sp_counted_base_impl(sp_counted_base_impl const &); 00184 sp_counted_base_impl & operator= (sp_counted_base_impl const &); 00185 00186 typedef sp_counted_base_impl<P, D> this_type; 00187 00188 public: 00189 00190 // pre: initial_use_count <= initial_weak_count, d(p) must not throw 00191 sp_counted_base_impl(P p, D d): ptr(p), del(d) 00192 { 00193 } 00194 00195 virtual void dispose() // nothrow 00196 { 00197 del(ptr); 00198 } 00199 00200 virtual void * get_deleter(std::type_info const & ti) 00201 { 00202 return ti == typeid(D)? &del: 0; 00203 } 00204 00205 void * operator new(size_t) 00206 { 00207 return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0)); 00208 } 00209 00210 void operator delete(void * p) 00211 { 00212 std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1); 00213 } 00214 00215 }; 00216 00217 class shared_count 00218 { 00219 private: 00220 00221 sp_counted_base * pi_; 00222 00223 public: 00224 00225 shared_count(): pi_(0) // nothrow 00226 { 00227 } 00228 00229 template<class P, class D> shared_count(P p, D d): pi_(0) 00230 { 00231 try 00232 { 00233 pi_ = new sp_counted_base_impl<P, D>(p, d); 00234 } 00235 catch(...) 00236 { 00237 d(p); // delete p 00238 throw; 00239 } 00240 } 00241 00242 // auto_ptr<Y> is special cased to provide the strong guarantee 00243 template<class Y> 00244 explicit shared_count(std::auto_ptr<Y> & r): pi_(new sp_counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>())) 00245 { 00246 r.release(); 00247 } 00248 00249 ~shared_count() // nothrow 00250 { 00251 if(pi_ != 0) pi_->release(); 00252 } 00253 00254 shared_count(shared_count const & r): pi_(r.pi_) // nothrow 00255 { 00256 if(pi_ != 0) pi_->add_ref_copy(); 00257 } 00258 00259 shared_count & operator= (shared_count const & r) // nothrow 00260 { 00261 sp_counted_base * tmp = r.pi_; 00262 if(tmp != 0) tmp->add_ref_copy(); 00263 if(pi_ != 0) pi_->release(); 00264 pi_ = tmp; 00265 00266 return *this; 00267 } 00268 00269 void swap(shared_count & r) // nothrow 00270 { 00271 sp_counted_base * tmp = r.pi_; 00272 r.pi_ = pi_; 00273 pi_ = tmp; 00274 } 00275 00276 long use_count() const // nothrow 00277 { 00278 return pi_ != 0? pi_->use_count(): 0; 00279 } 00280 00281 bool unique() const // nothrow 00282 { 00283 return use_count() == 1; 00284 } 00285 00286 friend inline bool operator==(shared_count const & a, shared_count const & b) 00287 { 00288 return a.pi_ == b.pi_; 00289 } 00290 00291 friend inline bool operator<(shared_count const & a, shared_count const & b) 00292 { 00293 return std::less<sp_counted_base *>()(a.pi_, b.pi_); 00294 } 00295 00296 void * get_deleter(std::type_info const & ti) const 00297 { 00298 return pi_? pi_->get_deleter(ti): 0; 00299 } 00300 }; 00301 00302 #ifdef __CODEGUARD__ 00303 # pragma option pop 00304 #endif 00305 00306 } // namespace resip 00307 00308 #ifdef __BORLANDC__ 00309 # pragma warn .8027 // Functions containing try are not expanded inline 00310 # pragma warn .8026 // Functions with excep. spec. are not expanded inline 00311 #endif 00312 00313 00314 #endif 00315 00316 // Note: This implementation is a modified version of shared_count from 00317 // Boost.org 00318 // 00319 00320 /* ==================================================================== 00321 * 00322 * Boost Software License - Version 1.0 - August 17th, 2003 00323 * 00324 * Permission is hereby granted, free of charge, to any person or organization 00325 * obtaining a copy of the software and accompanying documentation covered by 00326 * this license (the "Software") to use, reproduce, display, distribute, 00327 * execute, and transmit the Software, and to prepare derivative works of the 00328 * Software, and to permit third-parties to whom the Software is furnished to 00329 * do so, all subject to the following: 00330 * 00331 * The copyright notices in the Software and this entire statement, including 00332 * the above license grant, this restriction and the following disclaimer, 00333 * must be included in all copies of the Software, in whole or in part, and 00334 * all derivative works of the Software, unless such copies or derivative 00335 * works are solely in the form of machine-executable object code generated by 00336 * a source language processor. 00337 * 00338 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00339 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00340 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 00341 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 00342 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 00343 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00344 * DEALINGS IN THE SOFTWARE. 00345 * 00346 * ==================================================================== 00347 */ 00348 00349 00350 /* ==================================================================== 00351 * The Vovida Software License, Version 1.0 00352 * 00353 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00354 * 00355 * Redistribution and use in source and binary forms, with or without 00356 * modification, are permitted provided that the following conditions 00357 * are met: 00358 * 00359 * 1. Redistributions of source code must retain the above copyright 00360 * notice, this list of conditions and the following disclaimer. 00361 * 00362 * 2. Redistributions in binary form must reproduce the above copyright 00363 * notice, this list of conditions and the following disclaimer in 00364 * the documentation and/or other materials provided with the 00365 * distribution. 00366 * 00367 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00368 * and "Vovida Open Communication Application Library (VOCAL)" must 00369 * not be used to endorse or promote products derived from this 00370 * software without prior written permission. For written 00371 * permission, please contact vocal@vovida.org. 00372 * 00373 * 4. Products derived from this software may not be called "VOCAL", nor 00374 * may "VOCAL" appear in their name, without prior written 00375 * permission of Vovida Networks, Inc. 00376 * 00377 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00378 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00379 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00380 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00381 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00382 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00383 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00384 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00385 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00386 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00387 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00388 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00389 * DAMAGE. 00390 * 00391 * ==================================================================== 00392 * 00393 * This software consists of voluntary contributions made by Vovida 00394 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00395 * Inc. For more information on Vovida Networks, Inc., please see 00396 * <http://www.vovida.org/>. 00397 * 00398 */
1.7.5.1