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 { ~destructorboost::spirit::static_::destructor49 ~destructor() 50 { 51 static_::get_address()->~value_type(); 52 } 53 }; 54 55 struct default_ctor 56 { constructboost::spirit::static_::default_ctor57 static void construct() 58 { 59 ::new (static_::get_address()) value_type(); 60 static destructor d; 61 } 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 static_boost::spirit::static_70 static_(Tag = Tag()) 71 { 72 boost::call_once(&default_ctor::construct, constructed_); 73 } 74 operator referenceboost::spirit::static_75 operator reference() 76 { 77 return this->get(); 78 } 79 operator const_referenceboost::spirit::static_80 operator const_reference() const 81 { 82 return this->get(); 83 } 84 getboost::spirit::static_85 reference get() 86 { 87 return *this->get_address(); 88 } 89 getboost::spirit::static_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 get_addressboost::spirit::static_98 static pointer get_address() 99 { 100 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 125