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 cereal 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 RANDOLPH VOORHIES OR SHANE GRANT 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 : #ifdef _MSC_VER
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 79560 : static T & create()
72 : {
73 79544 : static T t;
74 : //! Forces instantiation at pre-execution time
75 : (void)instance;
76 79560 : return t;
77 : }
78 11222 :
79 : StaticObject( StaticObject const & /*other*/ ) {}
80 11222 :
81 : public:
82 : static T & getInstance()
83 11222 : {
84 : return create();
85 1614 : }
86 :
87 1614 : //! A class that acts like std::lock_guard
88 : class LockGuard
89 : {
90 1614 : #if CEREAL_THREAD_SAFE
91 : public:
92 6 : LockGuard(std::mutex & m) : lock(m) {}
93 : private:
94 2 : std::unique_lock<std::mutex> lock;
95 : #else
96 11212 : public:
97 6 : LockGuard(LockGuard const &) = default; // prevents implicit copy ctor warning
98 11212 : ~LockGuard() CEREAL_NOEXCEPT {} // prevents variable not used
99 4 : #endif
100 : };
101 4 :
102 : //! Attempts to lock this static object for the current scope
103 : /*! @note This function is a no-op if cereal is not compiled with
104 4 : thread safety enabled (CEREAL_THREAD_SAFE = 1).
105 :
106 4 : This function returns an object that holds a lock for
107 : this StaticObject that will release its lock upon destruction. This
108 4 : call will block until the lock is available. */
109 : static LockGuard lock()
110 : {
111 4 : #if CEREAL_THREAD_SAFE
112 11200 : static std::mutex instanceMutex;
113 4 : return LockGuard{instanceMutex};
114 : #else
115 4 : return LockGuard{};
116 : #endif
117 : }
118 4 :
119 : private:
120 4 : static T & instance;
121 : };
122 4 :
123 11200 : template <class T> T & StaticObject<T>::instance = StaticObject<T>::create();
124 : } // namespace detail
125 4 : } // namespace cereal
126 :
127 4 : #endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_
|