static_object.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. #include "cereal/macros.hpp"
  31. #if CEREAL_THREAD_SAFE
  32. #include <mutex>
  33. #endif
  34. //! Prevent link optimization from removing non-referenced static objects
  35. /*! Especially for polymorphic support, we create static objects which
  36. may not ever be explicitly referenced. Most linkers will detect this
  37. and remove the code causing various unpleasant runtime errors. These
  38. macros, adopted from Boost (see force_include.hpp) prevent this
  39. (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
  40. Use, modification and distribution is subject to the Boost Software
  41. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  42. http://www.boost.org/LICENSE_1_0.txt) */
  43. #if defined(_MSC_VER) && !defined(__clang__)
  44. #if defined(ASIO2_ENABLE_CEREAL_DLL_EXPORT)
  45. # define CEREAL_DLL_EXPORT __declspec(dllexport)
  46. #else
  47. # define CEREAL_DLL_EXPORT
  48. #endif
  49. # define CEREAL_USED
  50. #else // clang or gcc
  51. #if defined(ASIO2_ENABLE_CEREAL_DLL_EXPORT)
  52. # define CEREAL_DLL_EXPORT __attribute__ ((visibility("default")))
  53. #else
  54. # define CEREAL_DLL_EXPORT
  55. #endif
  56. # define CEREAL_USED __attribute__ ((__used__))
  57. #endif
  58. namespace cereal
  59. {
  60. namespace detail
  61. {
  62. //! A static, pre-execution object
  63. /*! This class will create a single copy (singleton) of some
  64. type and ensures that merely referencing this type will
  65. cause it to be instantiated and initialized pre-execution.
  66. For example, this is used heavily in the polymorphic pointer
  67. serialization mechanisms to bind various archive types with
  68. different polymorphic classes */
  69. template <class T>
  70. class CEREAL_DLL_EXPORT StaticObject
  71. {
  72. private:
  73. static T & create()
  74. {
  75. static T t;
  76. //! Forces instantiation at pre-execution time
  77. (void)instance;
  78. return t;
  79. }
  80. StaticObject( StaticObject const & /*other*/ ) {}
  81. public:
  82. static T & getInstance()
  83. {
  84. return create();
  85. }
  86. //! A class that acts like std::lock_guard
  87. class LockGuard
  88. {
  89. #if CEREAL_THREAD_SAFE
  90. public:
  91. LockGuard(std::mutex & m) : lock(m) {}
  92. private:
  93. std::unique_lock<std::mutex> lock;
  94. #else
  95. public:
  96. LockGuard() = default;
  97. LockGuard(LockGuard const &) = default; // prevents implicit copy ctor warning
  98. ~LockGuard() CEREAL_NOEXCEPT {} // prevents variable not used
  99. #endif
  100. };
  101. //! Attempts to lock this static object for the current scope
  102. /*! @note This function is a no-op if cereal is not compiled with
  103. thread safety enabled (CEREAL_THREAD_SAFE = 1).
  104. This function returns an object that holds a lock for
  105. this StaticObject that will release its lock upon destruction. This
  106. call will block until the lock is available. */
  107. static LockGuard lock()
  108. {
  109. #if CEREAL_THREAD_SAFE
  110. static std::mutex instanceMutex;
  111. return LockGuard{instanceMutex};
  112. #else
  113. return LockGuard{};
  114. #endif
  115. }
  116. private:
  117. static T & instance;
  118. };
  119. template <class T> T & StaticObject<T>::instance = StaticObject<T>::create();
  120. } // namespace detail
  121. } // namespace cereal
  122. #endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_