/*============================================================================= | |
Copyright (c) 2006 Joao Abecasis | |
http://spirit.sourceforge.net/ | |
Distributed under the Boost Software License, Version 1.0. (See accompanying | |
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
=============================================================================*/ | |
#if !defined(BOOST_SPIRIT_STATIC_HPP) | |
#define BOOST_SPIRIT_STATIC_HPP | |
#include <boost/noncopyable.hpp> | |
#include <boost/call_traits.hpp> | |
#include <boost/aligned_storage.hpp> | |
#include <boost/type_traits/add_pointer.hpp> | |
#include <boost/type_traits/alignment_of.hpp> | |
#include <boost/thread/once.hpp> | |
#include <memory> // for placement new | |
#include <boost/spirit/home/classic/namespace.hpp> | |
namespace boost { namespace spirit { | |
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN | |
// | |
// Provides thread-safe initialization of a single static instance of T. | |
// | |
// This instance is guaranteed to be constructed on static storage in a | |
// thread-safe manner, on the first call to the constructor of static_. | |
// | |
// Requirements: | |
// T is default constructible | |
// (There's an alternate implementation that relaxes this | |
// requirement -- Joao Abecasis) | |
// T::T() MUST not throw! | |
// this is a requirement of boost::call_once. | |
// | |
template <class T, class Tag> | |
struct static_ | |
: boost::noncopyable | |
{ | |
private: | |
struct destructor | |
{ | |
~destructor() | |
{ | |
static_::get_address()->~value_type(); | |
} | |
}; | |
struct default_ctor | |
{ | |
static void construct() | |
{ | |
::new (static_::get_address()) value_type(); | |
static destructor d; | |
} | |
}; | |
public: | |
typedef T value_type; | |
typedef typename boost::call_traits<T>::reference reference; | |
typedef typename boost::call_traits<T>::const_reference const_reference; | |
static_(Tag = Tag()) | |
{ | |
boost::call_once(&default_ctor::construct, constructed_); | |
} | |
operator reference() | |
{ | |
return this->get(); | |
} | |
operator const_reference() const | |
{ | |
return this->get(); | |
} | |
reference get() | |
{ | |
return *this->get_address(); | |
} | |
const_reference get() const | |
{ | |
return *this->get_address(); | |
} | |
private: | |
typedef typename boost::add_pointer<value_type>::type pointer; | |
static pointer get_address() | |
{ | |
return static_cast<pointer>(data_.address()); | |
} | |
typedef boost::aligned_storage<sizeof(value_type), | |
boost::alignment_of<value_type>::value> storage_type; | |
static storage_type data_; | |
static once_flag constructed_; | |
}; | |
template <class T, class Tag> | |
typename static_<T, Tag>::storage_type static_<T, Tag>::data_; | |
template <class T, class Tag> | |
once_flag static_<T, Tag>::constructed_ = BOOST_ONCE_INIT; | |
BOOST_SPIRIT_CLASSIC_NAMESPACE_END | |
}} // namespace BOOST_SPIRIT_CLASSIC_NS | |
#endif // include guard |