Skip to content

Commit

Permalink
Fixed #630: Event synchronization example is broken
Browse files Browse the repository at this point in the history
(cherry picked from commit 7d957b5860e9c9457627c5698a595cbded86be00)
  • Loading branch information
hkaiser committed Jan 5, 2013
1 parent 3e4992c commit d372a9a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 41 deletions.
55 changes: 42 additions & 13 deletions hpx/util/reinitializable_static.hpp
Expand Up @@ -33,6 +33,38 @@

namespace hpx { namespace util
{
namespace detail
{
template <typename T, typename Tag, typename Once>
struct initialize_once;

//////////////////////////////////////////////////////////////////////
template <typename T, typename Tag>
struct initialize_once<T, Tag, boost::once_flag>
: private boost::noncopyable
{
static boost::once_flag constructed_;
};

template <typename T, typename Tag>
boost::once_flag
initialize_once<T, Tag, boost::once_flag>::constructed_ =
BOOST_ONCE_INIT;

//////////////////////////////////////////////////////////////////////
template <typename T, typename Tag>
struct initialize_once<T, Tag, lcos::local::once_flag>
: private boost::noncopyable
{
static lcos::local::once_flag constructed_;
};

template <typename T, typename Tag>
lcos::local::once_flag
initialize_once<T, Tag, lcos::local::once_flag>::constructed_ =
HPX_ONCE_INIT;
}

///////////////////////////////////////////////////////////////////////////
// Provides thread-safe initialization of a single static instance of T.
//
Expand All @@ -47,9 +79,10 @@ namespace hpx { namespace util
// In addition this type registers global construction and destruction
// functions used by the HPX runtime system to reinitialize the held data
// structures.
template <typename T, typename Tag = T, std::size_t N = 1>
template <typename T, typename Tag = T, std::size_t N = 1,
typename Once = boost::once_flag>
struct HPX_EXPORT_REINITIALIZABLE_STATIC reinitializable_static
: boost::noncopyable
: util::detail::initialize_once<T, Tag, Once>
{
public:
typedef T value_type;
Expand Down Expand Up @@ -96,14 +129,15 @@ namespace hpx { namespace util

reinitializable_static()
{
boost::call_once(constructed_,
&reinitializable_static::default_constructor);
// rely on ADL to find the proper call_once
call_once(constructed_, &reinitializable_static::default_constructor);
}

template <typename U>
reinitializable_static(U const& val)
{
boost::call_once(constructed_,
// rely on ADL to find the proper call_once
call_once(constructed_,
boost::bind(&reinitializable_static::value_constructor<U>,
boost::addressof(val)));
}
Expand Down Expand Up @@ -141,16 +175,11 @@ namespace hpx { namespace util
boost::alignment_of<value_type>::value> storage_type;

static storage_type data_[N];
static boost::once_flag constructed_;
};

template <typename T, typename Tag, std::size_t N>
typename reinitializable_static<T, Tag, N>::storage_type
reinitializable_static<T, Tag, N>::data_[N];

template <typename T, typename Tag, std::size_t N>
boost::once_flag reinitializable_static<T, Tag, N>::constructed_ =
BOOST_ONCE_INIT;
template <typename T, typename Tag, std::size_t N, typename Once>
typename reinitializable_static<T, Tag, N, Once>::storage_type
reinitializable_static<T, Tag, N, Once>::data_[N];
}}

#endif
Expand Down
49 changes: 21 additions & 28 deletions src/components/iostreams/standard_streams.cpp
Expand Up @@ -16,17 +16,17 @@
#include <hpx/util/reinitializable_static.hpp>
#include <hpx/components/iostreams/lazy_ostream.hpp>
#include <hpx/components/iostreams/standard_streams.hpp>
#include <hpx/lcos/local/spinlock.hpp>
#include <hpx/lcos/local/once.hpp>

///////////////////////////////////////////////////////////////////////////////
typedef hpx::actions::plain_action0<hpx::iostreams::create_cout>
create_cout_action;
typedef hpx::actions::plain_action0<hpx::iostreams::create_cerr>
create_cerr_action;

HPX_REGISTER_PLAIN_ACTION(create_cout_action, create_cout_action,
HPX_REGISTER_PLAIN_ACTION(create_cout_action, create_cout_action,
hpx::components::factory_enabled)
HPX_REGISTER_PLAIN_ACTION(create_cerr_action, create_cerr_action,
HPX_REGISTER_PLAIN_ACTION(create_cerr_action, create_cerr_action,
hpx::components::factory_enabled)

///////////////////////////////////////////////////////////////////////////////
Expand All @@ -36,12 +36,12 @@ HPX_REGISTER_PLAIN_ACTION(create_cerr_action, create_cerr_action,
namespace hpx { namespace iostreams
{
///////////////////////////////////////////////////////////////////////////
// Tag types to be used for the RAII wrappers below
struct raii_cout_tag {};
struct raii_cerr_tag {};

namespace detail
{
// Tag types to be used for the RAII wrappers below
struct raii_cout_tag {};
struct raii_cerr_tag {};

std::ostream& get_outstream(raii_cout_tag)
{
return std::cout;
Expand All @@ -51,6 +51,9 @@ namespace hpx { namespace iostreams
{
return std::cerr;
}

char const* const cout_name = "/locality(console)/output_stream(cout)";
char const* const cerr_name = "/locality(console)/output_stream(cerr)";
}

///////////////////////////////////////////////////////////////////////////
Expand All @@ -61,7 +64,7 @@ namespace hpx { namespace iostreams
{
typedef components::managed_component<server::output_stream> ostream_type;

stream_raii(std::string const& cout_name)
stream_raii(char const* cout_name)
{
LRT_(info) << "stream_raii::stream_raii: creating '"
<< cout_name << "' stream object";
Expand Down Expand Up @@ -122,36 +125,26 @@ namespace hpx { namespace iostreams
boost::shared_ptr<lazy_ostream> client;
};

// provide thread-safely initialized mutex
typedef lcos::local::spinlock mutex_type;
mutex_type& get_mutex()
{
util::static_<mutex_type> mtx_;
return mtx_.get();
}

// return the singleton stream objects
lazy_ostream& cout()
{
// Protect using a HPX spinlock to avoid deadlocks inside boost::call_once
// which is used by util::reinitializable_static. This is a temporary hack
// to be used until we have a hpx::call_once.
mutex_type::scoped_lock l(get_mutex());
typedef util::reinitializable_static<
stream_raii<detail::raii_cout_tag>, detail::raii_cout_tag,
1, lcos::local::once_flag
> static_type;

util::reinitializable_static<stream_raii<raii_cout_tag>, raii_cout_tag> cout_(
std::string("/locality(console)/output_stream(cout)"));
static_type cout_(detail::cout_name);
return *cout_.get().client;
}

lazy_ostream& cerr()
{
// Protect using a HPX spinlock to avoid deadlocks inside boost::call_once
// which is used by util::reinitializable_static. This is a temporary hack
// to be used until we have a hpx::call_once.
mutex_type::scoped_lock l(get_mutex());
typedef util::reinitializable_static<
stream_raii<detail::raii_cerr_tag>, detail::raii_cerr_tag,
1, lcos::local::once_flag
> static_type;

util::reinitializable_static<stream_raii<raii_cerr_tag>, raii_cerr_tag> cerr_(
std::string("/locality(console)/output_stream(cerr)"));
static_type cerr_(detail::cerr_name);
return *cerr_.get().client;
}

Expand Down

0 comments on commit d372a9a

Please sign in to comment.