Line data Source code
1 : /*! \file static_object.hpp 2 : \brief Internal polymorphism static object support 3 : \ingroup Internal */ 4 : /* 5 : Copyright (c) 2014, Randolph Voorhies, Shane Grant 6 : All rights reserved. 7 : Redistribution and use in source and binary forms, with or without 8 : modification, are permitted provided that the following conditions are met: 9 : * Redistributions of source code must retain the above copyright 10 : notice, this list of conditions and the following disclaimer. 11 : * Redistributions in binary form must reproduce the above copyright 12 : notice, this list of conditions and the following disclaimer in the 13 : documentation and/or other materials provided with the distribution. 14 : * Neither the name of the copyright holder nor the 15 : names of its contributors may be used to endorse or promote products 16 : derived from this software without specific prior written permission. 17 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 : ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 : WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 : DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 21 : DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 : (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 : LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 : ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 : SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 : */ 28 : #ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_ 29 : #define CEREAL_DETAILS_STATIC_OBJECT_HPP_ 30 : 31 : #include "cereal/macros.hpp" 32 : 33 : #if CEREAL_THREAD_SAFE 34 : #include <mutex> 35 : #endif 36 : 37 : //! Prevent link optimization from removing non-referenced static objects 38 : /*! Especially for polymorphic support, we create static objects which 39 : may not ever be explicitly referenced. Most linkers will detect this 40 : and remove the code causing various unpleasant runtime errors. These 41 : macros, adopted from Boost (see force_include.hpp) prevent this 42 : (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 43 : Use, modification and distribution is subject to the Boost Software 44 : License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 45 : http://www.boost.org/LICENSE_1_0.txt) */ 46 : 47 : #if defined(_MSC_VER) && !defined(__clang__) 48 : # define CEREAL_DLL_EXPORT __declspec(dllexport) 49 : # define CEREAL_USED 50 : #else // clang or gcc 51 : # define CEREAL_DLL_EXPORT __attribute__ ((visibility("default"))) 52 : # define CEREAL_USED __attribute__ ((__used__)) 53 : #endif 54 : 55 : namespace cereal 56 : { 57 : namespace detail 58 : { 59 : //! A static, pre-execution object 60 : /*! This class will create a single copy (singleton) of some 61 : type and ensures that merely referencing this type will 62 : cause it to be instantiated and initialized pre-execution. 63 : For example, this is used heavily in the polymorphic pointer 64 : serialization mechanisms to bind various archive types with 65 : different polymorphic classes */ 66 : template <class T> 67 : class CEREAL_DLL_EXPORT StaticObject 68 : { 69 : private: 70 : 71 39780 : static T & create() 72 : { 73 39772 : static T t; 74 : //! Forces instantiation at pre-execution time 75 : (void)instance; 76 39780 : return t; 77 : } 78 : 79 : StaticObject( StaticObject const & /*other*/ ) {} 80 : 81 : public: 82 39676 : static T & getInstance() 83 : { 84 39676 : return create(); 85 : } 86 : 87 : //! A class that acts like std::lock_guard 88 : class LockGuard 89 : { 90 : #if CEREAL_THREAD_SAFE 91 : public: 92 : LockGuard(std::mutex & m) : lock(m) {} 93 : private: 94 : std::unique_lock<std::mutex> lock; 95 : #else 96 : public: 97 : LockGuard() = default; 98 : LockGuard(LockGuard const &) = default; // prevents implicit copy ctor warning 99 7624 : ~LockGuard() CEREAL_NOEXCEPT {} // prevents variable not used 100 : #endif 101 : }; 102 : 103 : //! Attempts to lock this static object for the current scope 104 : /*! @note This function is a no-op if cereal is not compiled with 105 : thread safety enabled (CEREAL_THREAD_SAFE = 1). 106 : 107 : This function returns an object that holds a lock for 108 : this StaticObject that will release its lock upon destruction. This 109 : call will block until the lock is available. */ 110 7624 : static LockGuard lock() 111 : { 112 : #if CEREAL_THREAD_SAFE 113 : static std::mutex instanceMutex; 114 : return LockGuard{instanceMutex}; 115 : #else 116 7624 : return LockGuard{}; 117 : #endif 118 : } 119 : 120 : private: 121 : static T & instance; 122 : }; 123 : 124 : template <class T> T & StaticObject<T>::instance = StaticObject<T>::create(); 125 : } // namespace detail 126 : } // namespace cereal 127 : 128 : #endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_