Line data Source code
1 : /*============================================================================= 2 : Copyright (c) 2006 Joao Abecasis 3 : http://spirit.sourceforge.net/ 4 : 5 : Distributed under the Boost Software License, Version 1.0. (See accompanying 6 : file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 : =============================================================================*/ 8 : #if !defined(BOOST_SPIRIT_STATIC_HPP) 9 : #define BOOST_SPIRIT_STATIC_HPP 10 : 11 : #include <boost/noncopyable.hpp> 12 : #include <boost/call_traits.hpp> 13 : #include <boost/aligned_storage.hpp> 14 : 15 : #include <boost/type_traits/add_pointer.hpp> 16 : #include <boost/type_traits/alignment_of.hpp> 17 : 18 : #include <boost/thread/once.hpp> 19 : 20 : #include <memory> // for placement new 21 : 22 : #include <boost/spirit/home/classic/namespace.hpp> 23 : 24 : namespace boost { namespace spirit { 25 : 26 : BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 27 : 28 : // 29 : // Provides thread-safe initialization of a single static instance of T. 30 : // 31 : // This instance is guaranteed to be constructed on static storage in a 32 : // thread-safe manner, on the first call to the constructor of static_. 33 : // 34 : // Requirements: 35 : // T is default constructible 36 : // (There's an alternate implementation that relaxes this 37 : // requirement -- Joao Abecasis) 38 : // T::T() MUST not throw! 39 : // this is a requirement of boost::call_once. 40 : // 41 : template <class T, class Tag> 42 : struct static_ 43 : : boost::noncopyable 44 : { 45 : private: 46 : 47 : struct destructor 48 : { 49 0 : ~destructor() 50 : { 51 0 : static_::get_address()->~value_type(); 52 0 : } 53 : }; 54 : 55 : struct default_ctor 56 : { 57 0 : static void construct() 58 : { 59 0 : ::new (static_::get_address()) value_type(); 60 0 : static destructor d; 61 0 : } 62 : }; 63 : 64 : public: 65 : 66 : typedef T value_type; 67 : typedef typename boost::call_traits<T>::reference reference; 68 : typedef typename boost::call_traits<T>::const_reference const_reference; 69 : 70 0 : static_(Tag = Tag()) 71 : { 72 0 : boost::call_once(&default_ctor::construct, constructed_); 73 : } 74 : 75 0 : operator reference() 76 : { 77 0 : return this->get(); 78 : } 79 : 80 : operator const_reference() const 81 : { 82 : return this->get(); 83 : } 84 : 85 0 : reference get() 86 : { 87 : return *this->get_address(); 88 : } 89 : 90 : const_reference get() const 91 : { 92 : return *this->get_address(); 93 : } 94 : 95 : private: 96 : typedef typename boost::add_pointer<value_type>::type pointer; 97 : 98 0 : static pointer get_address() 99 : { 100 0 : return static_cast<pointer>(data_.address()); 101 : } 102 : 103 : typedef boost::aligned_storage<sizeof(value_type), 104 : boost::alignment_of<value_type>::value> storage_type; 105 : 106 : static storage_type data_; 107 : static once_flag constructed_; 108 : }; 109 : 110 : template <class T, class Tag> 111 : typename static_<T, Tag>::storage_type static_<T, Tag>::data_; 112 : 113 : template <class T, class Tag> 114 : #ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11 115 : once_flag static_<T, Tag>::constructed_ = BOOST_ONCE_INIT; 116 : #else 117 : once_flag static_<T, Tag>::constructed_; 118 : #endif 119 : 120 : BOOST_SPIRIT_CLASSIC_NAMESPACE_END 121 : 122 : }} // namespace BOOST_SPIRIT_CLASSIC_NS 123 : 124 : #endif // include guard