00001 // /// // C++ Cross Platform 00002 // ///// //// 00003 // /// XXX XXX /// /////////// ///////// /// /// 00004 // /// XXX XXX /// /// /// /// /// /// 00005 // /// XXX /// ///////// /// // ////// 00006 // /// XXX XXX /// /// /// /// /// /// 00007 // //// XXX XXX //// //////////// ////////// /// /// 00008 // //// //// 00009 // //// M O B O T I X //////////////////////////////////////////////// 00010 // //// Security Vision Systems ////////////////////////////////////////////// 00011 // 00012 // $Author: khe_admin $ 00013 // $LastChangedBy: khe_admin $ 00014 // $LastChangedDate: 2007-06-29 12:31:37 +0200 (Fri, 29 Jun 2007) $ 00015 // $HeadURL: http://svn.mobotix.net/svn/mxsdk/src/mxm/trunk/include/mxm/core/mxmSmartHandle.h $ 00016 // 00018 // 00019 // MOBOTIX MxPEG SDK 00020 // 00021 // This file belongs to the C++ library released as part of the MxPEG SDK. 00022 // 00023 // This software is licenced under the BSD licence, 00024 // http://www.opensource.org/licenses/bsd-license.php 00025 // 00026 // Copyright (c) 2005 - 2007, MOBOTIX AG 00027 // All rights reserved. 00028 // 00029 // Redistribution and use in source and binary forms, with or without 00030 // modification, are permitted provided that the following conditions are 00031 // met: 00032 // 00033 // - Redistributions of source code must retain the above copyright 00034 // notice, this list of conditions and the following disclaimer. 00035 // 00036 // - Redistributions in binary form must reproduce the above copyright 00037 // notice, this list of conditions and the following disclaimer in the 00038 // documentation and/or other materials provided with the distribution. 00039 // 00040 // - Neither the name of MOBOTIX AG nor the names of its contributors may 00041 // be used to endorse or promote products derived from this software 00042 // without specific prior written permission. 00043 // 00044 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00045 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00046 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00047 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00048 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00049 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00050 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00051 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00052 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00053 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00054 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00055 // 00057 00058 00059 00060 #ifndef __MXM_SMARTHANDLE_H__ 00061 #define __MXM_SMARTHANDLE_H__ 00062 00063 00064 00065 #include <mxm/core/mxmLockInterface.h> 00066 #include <mxm/core/mxmSmartHandleCore.h> 00067 00068 00069 00070 namespace mxm { 00071 00074 00341 template<class T> class smart : public mxmSmartHandleCore { 00342 00343 public: 00346 smart(); 00348 smart(const smart<T> &other); 00351 smart(T *handlee); 00353 ~smart(); 00354 00355 public: 00357 smart<T> &operator=(const smart<T> &other); 00359 smart<T> &operator=(T *handlee); 00361 T *operator->(void) const; 00363 T &operator*(void) const; 00365 bool operator==(const smart<T> &other) const; 00370 template<class NewT> 00371 operator smart<NewT>(void) const; 00372 00373 private: 00375 void deleteHandlee(void); 00376 }; 00377 00378 }; // namespace _mxm_ 00379 00380 00381 00382 template<class T> 00383 mxm::smart<T>::smart() { 00384 00385 } 00386 00387 00388 template<class T> 00389 mxm::smart<T>::smart(const smart<T> &other) { 00390 00391 joinGroup(other); 00392 } 00393 00394 00395 template<class T> 00396 mxm::smart<T>::smart(T *handlee) { 00397 00398 Handlee = static_cast<void *>(handlee); // OK, if _0_ (= no effect) 00399 } 00400 00401 00402 template<class T> 00403 mxm::smart<T>::~smart() { 00404 00405 // kills potential handlee and lock stuff... 00406 reset(); 00407 // this should have been called by the mxmSmartHandleCore 00408 // destructor - however, since it calls the virtual method 00409 // deleteHandlee(), the latter would then not be correctly 00410 // activated due to virtual function invocation working 00411 // differently when triggered directly or indirectly from a 00412 // destructor 00413 } 00414 00415 00416 00421 template<class T> 00422 mxm::smart<T> &mxm::smart<T>::operator=(const smart<T> &other) { 00423 00424 reset(); 00425 00426 // NOTE : synchronization breach: problem here is 00427 // - there are potentially two locks involved 00428 // - the handle is temporarily unprotected 00429 // Scenario of pain: Another thread can now read Lock==0 as part of some 00430 // handle operation and decide that the handle (group) is unprotected. 00431 // <preempt> We join another protected handle group by calling joinGroup() 00432 // below and link into the group's doublelinked ring structure. <preempt> The 00433 // other thread resumes its operation and modifies the same ring structure 00434 // without having acquired the lock. Very unfortunate situation. 00435 00436 joinGroup(other); 00437 00438 return(*this); 00439 } 00440 00441 00446 template<class T> 00447 mxm::smart<T> &mxm::smart<T>::operator=(T *handlee) { 00448 00449 reset(); 00450 00451 Handlee = static_cast<void *>(handlee); // OK, if _0_ (= no effect) 00452 00453 // NOTE : synchronization breach possible: a potential previous lock 00454 // protection has just been removed by reset(). If later on the handle 00455 // joins another protected handle group, the process as a whole is a 00456 // transition from one lock protection space to another, with a 00457 // temporary lack of protection in between, just like the 00458 // operator=(const smart<T> &other) assignment above. 00459 00460 return(*this); 00461 } 00462 00463 00464 template<class T> 00465 T *mxm::smart<T>::operator->(void) const { 00466 00467 return(static_cast<T *>(Handlee)); 00468 } 00469 00470 00471 template<class T> 00472 T &mxm::smart<T>::operator*(void) const { 00473 00474 return(*static_cast<T *>(Handlee)); 00475 } 00476 00477 00478 template<class T> 00479 bool mxm::smart<T>::operator==(const mxm::smart<T> &other) const { 00480 00481 return(Handlee == other.Handlee); 00482 } 00483 00484 00491 template<class T> 00492 template<class NewT> 00493 mxm::smart<T>::operator mxm::smart<NewT>(void) const { 00494 00495 smart<NewT> new_handle; // creates deafult state handle 00496 00497 if(Lock) Lock->acquire(); // ----------------------------------------------- 00498 00499 NewT *new_type = dynamic_cast<NewT *>(static_cast<T *>(Handlee)); 00500 00501 if(new_type) new_handle.joinGroup(*this, 00502 static_cast<void *>(new_type), 00503 true); 00504 // _true_ => don't synchronize, already did that 00505 00506 if(Lock) Lock->release(); // ----------------------------------------------- 00507 00508 return(new_handle); 00509 } 00510 00511 00512 template<class T> 00513 void mxm::smart<T>::deleteHandlee(void) { 00514 00515 delete static_cast<T *>(Handlee); 00516 } 00517 00518 00519 00520 #endif // __MXM_SMARTHANDLE_H__