blob: a994814a08c438658badb76aee33130b8d541feb [file] [log] [blame]
/*=============================================================================
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