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