Skip to content

Commit

Permalink
Make sure sync primitives are not copyable nor movable
Browse files Browse the repository at this point in the history
Fixes #1471
  • Loading branch information
K-ballo committed May 19, 2015
1 parent 86fa5f6 commit 4d02297
Show file tree
Hide file tree
Showing 14 changed files with 142 additions and 66 deletions.
11 changes: 7 additions & 4 deletions hpx/config/emulate_deleted.hpp
Expand Up @@ -6,9 +6,9 @@
#if !defined(HPX_CONFIG_EMULATE_DELETED_JAN_06_2013_0919PM)
#define HPX_CONFIG_EMULATE_DELETED_JAN_06_2013_0919PM

#include <boost/config.hpp>
#include <hpx/config.hpp>

#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
#ifdef HPX_HAVE_CXX11_DELETED_FUNCTIONS

#define HPX_DELETE_COPY_CTOR(cls) \
cls(cls const&) = delete; \
Expand All @@ -32,15 +32,18 @@
public: \
/**/

#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
#endif // HPX_HAVE_CXX11_DELETED_FUNCTIONS

#define HPX_NON_COPYABLE(cls) \
HPX_DELETE_COPY_CTOR(cls) \
HPX_DELETE_COPY_ASSIGN(cls) \
cls(cls&&) = delete; cls& operator=(cls&&) = delete; \
/**/

#include <boost/config.hpp>

#if !defined(BOOST_DELETED_FUNCTION)
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
#if HPX_HAVE_CXX11_DELETED_FUNCTIONS
# define BOOST_DELETED_FUNCTION(fun) fun = delete;
#else
# define BOOST_DELETED_FUNCTION(fun) private: fun;
Expand Down
6 changes: 4 additions & 2 deletions hpx/lcos/local/mutex.hpp
Expand Up @@ -8,6 +8,7 @@
#define HPX_LCOS_MUTEX_JUN_23_2008_0530PM

#include <hpx/config.hpp>
#include <hpx/config/emulate_deleted.hpp>
#include <hpx/lcos/local/spinlock.hpp>
#include <hpx/lcos/local/detail/condition_variable.hpp>
#include <hpx/runtime/threads/thread_helpers.hpp>
Expand All @@ -18,13 +19,12 @@
#include <hpx/util/scoped_unlock.hpp>

#include <boost/intrusive/slist.hpp>
#include <boost/noncopyable.hpp>
#include <boost/thread/locks.hpp>

///////////////////////////////////////////////////////////////////////////////
namespace hpx { namespace lcos { namespace local
{
class mutex : boost::noncopyable
class mutex
{
private:
typedef lcos::local::spinlock mutex_type;
Expand All @@ -41,6 +41,8 @@ namespace hpx { namespace lcos { namespace local
HPX_ITT_SYNC_RENAME(this, "lcos::local::mutex");
}

HPX_NON_COPYABLE(mutex);

~mutex()
{
HPX_ITT_SYNC_DESTROY(this);
Expand Down
3 changes: 1 addition & 2 deletions hpx/lcos/local/once.hpp
Expand Up @@ -11,14 +11,13 @@
#define HPX_LCOS_LOCAL_ONCE_JAN_03_2013_0810PM

#include <hpx/hpx_fwd.hpp>
#include <hpx/config/emulate_deleted.hpp>
#include <hpx/lcos/local/event.hpp>
#include <hpx/lcos/local/once_fwd.hpp>
#include <hpx/config/emulate_deleted.hpp>
#include <hpx/util/assert.hpp>

#include <boost/atomic.hpp>
#include <boost/config.hpp>
#include <boost/noncopyable.hpp>

namespace hpx { namespace lcos { namespace local
{
Expand Down
25 changes: 2 additions & 23 deletions hpx/lcos/local/spinlock.hpp
Expand Up @@ -13,7 +13,7 @@
#define HPX_B3A83B49_92E0_4150_A551_488F9F5E1113

#include <hpx/config.hpp>

#include <hpx/config/emulate_deleted.hpp>
#include <hpx/util/move.hpp>
#include <hpx/util/itt_notify.hpp>
#include <hpx/util/register_locks.hpp>
Expand Down Expand Up @@ -45,8 +45,6 @@ namespace hpx { namespace lcos { namespace local
boost::uint64_t v_;
#endif

HPX_MOVABLE_BUT_NOT_COPYABLE(spinlock)

public:
///////////////////////////////////////////////////////////////////////
static void yield(std::size_t k)
Expand Down Expand Up @@ -112,32 +110,13 @@ namespace hpx { namespace lcos { namespace local
HPX_ITT_SYNC_CREATE(this, desc, "");
}

spinlock(spinlock && rhs)
#if defined(BOOST_WINDOWS)
: v_(BOOST_INTERLOCKED_EXCHANGE(&rhs.v_, 0))
#else
: v_(__sync_lock_test_and_set(&rhs.v_, 0))
#endif
{}
HPX_NON_COPYABLE(spinlock);

~spinlock()
{
HPX_ITT_SYNC_DESTROY(this);
}

spinlock& operator=(spinlock && rhs)
{
if (this != &rhs) {
unlock();
#if defined(BOOST_WINDOWS)
v_ = BOOST_INTERLOCKED_EXCHANGE(&rhs.v_, 0);
#else
v_ = __sync_lock_test_and_set(&rhs.v_, 0);
#endif
}
return *this;
}

void lock()
{
HPX_ITT_SYNC_PREPARE(this);
Expand Down
24 changes: 2 additions & 22 deletions hpx/lcos/local/spinlock_no_backoff.hpp
Expand Up @@ -10,6 +10,7 @@
#if !defined(HPX_LCOS_LOCAL_SPINLOCK_NO_BACKOFF)
#define HPX_LCOS_LOCAL_SPINLOCK_NO_BACKOFF

#include <hpx/config/emulate_deleted.hpp>
#include <hpx/util/move.hpp>
#include <hpx/util/itt_notify.hpp>
#include <hpx/util/register_locks.hpp>
Expand All @@ -36,40 +37,19 @@ namespace hpx { namespace lcos { namespace local
private:
boost::uint64_t v_;

HPX_MOVABLE_BUT_NOT_COPYABLE(spinlock_no_backoff)

public:
spinlock_no_backoff() : v_(0)
{
HPX_ITT_SYNC_CREATE(this, "hpx::lcos::local::spinlock_no_backoff", "");
}

spinlock_no_backoff(spinlock_no_backoff && rhs)
#if defined(BOOST_WINDOWS)
: v_(BOOST_INTERLOCKED_EXCHANGE(&rhs.v_, 0))
#else
: v_(__sync_lock_test_and_set(&rhs.v_, 0))
#endif
{}
HPX_NON_COPYABLE(spinlock_no_backoff);

~spinlock_no_backoff()
{
HPX_ITT_SYNC_DESTROY(this);
}

spinlock_no_backoff& operator=(spinlock_no_backoff && rhs)
{
if (this != &rhs) {
unlock();
#if defined(BOOST_WINDOWS)
v_ = BOOST_INTERLOCKED_EXCHANGE(&rhs.v_, 0);
#else
v_ = __sync_lock_test_and_set(&rhs.v_, 0);
#endif
}
return *this;
}

void lock()
{
HPX_ITT_SYNC_PREPARE(this);
Expand Down
3 changes: 2 additions & 1 deletion hpx/lcos/local/spinlock_pool.hpp
Expand Up @@ -13,6 +13,7 @@
#ifndef HPX_LCOS_LOCAL_SPINLOCK_POOL_HPP
#define HPX_LCOS_LOCAL_SPINLOCK_POOL_HPP

#include <hpx/config/emulate_deleted.hpp>
#include <hpx/runtime/threads/thread_helpers.hpp>
#include <hpx/lcos/local/spinlock.hpp>

Expand Down Expand Up @@ -52,7 +53,7 @@ namespace hpx { namespace lcos { namespace local
private:
hpx::lcos::local::spinlock & sp_;

HPX_MOVABLE_BUT_NOT_COPYABLE(scoped_lock);
HPX_NON_COPYABLE(scoped_lock);

public:
explicit scoped_lock(void const * pv)
Expand Down
12 changes: 7 additions & 5 deletions hpx/util/spinlock.hpp
Expand Up @@ -8,18 +8,18 @@
#if !defined(HPX_DF595582_FEBC_4EE0_A606_A1EEB171D770)
#define HPX_DF595582_FEBC_4EE0_A606_A1EEB171D770

#include <boost/noncopyable.hpp>
#include <boost/thread/locks.hpp>
#include <boost/smart_ptr/detail/spinlock.hpp>

#include <hpx/config/emulate_deleted.hpp>
#include <hpx/util/itt_notify.hpp>
#include <hpx/util/register_locks.hpp>

#include <boost/thread/locks.hpp>
#include <boost/smart_ptr/detail/spinlock.hpp>

namespace hpx { namespace util
{

/// boost::mutex-compatible spinlock class
struct spinlock : boost::noncopyable
struct spinlock
{
private:
boost::detail::spinlock m;
Expand All @@ -33,6 +33,8 @@ struct spinlock : boost::noncopyable
m = l;
}

HPX_NON_COPYABLE(spinlock);

~spinlock()
{
HPX_ITT_SYNC_DESTROY(this);
Expand Down
11 changes: 6 additions & 5 deletions hpx/util/spinlock_pool.hpp
Expand Up @@ -18,14 +18,15 @@
# pragma once
#endif

#include <hpx/config/emulate_deleted.hpp>
#include <hpx/util/itt_notify.hpp>
#include <hpx/util/register_locks.hpp>

#include <boost/config.hpp>
#include <boost/version.hpp>
#include <boost/smart_ptr/detail/spinlock.hpp>
#include <cstddef>

#include <hpx/util/itt_notify.hpp>
#include <hpx/util/register_locks.hpp>

namespace hpx { namespace util
{
#if HPX_HAVE_ITTNOTIFY != 0
Expand Down Expand Up @@ -62,9 +63,9 @@ namespace hpx { namespace util
private:
boost::detail::spinlock & sp_;

HPX_MOVABLE_BUT_NOT_COPYABLE(scoped_lock);
public:
HPX_NON_COPYABLE(scoped_lock);

public:
explicit scoped_lock( void const * pv ): sp_( spinlock_for( pv ) )
{
lock();
Expand Down
5 changes: 4 additions & 1 deletion tests/performance/local/spinlock_overhead1.cpp
Expand Up @@ -4,6 +4,7 @@
// 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)

#include <hpx/config/emulate_deleted.hpp>
#include <hpx/runtime.hpp>
#include <hpx/hpx_init.hpp>
#include <hpx/lcos/wait_each.hpp>
Expand Down Expand Up @@ -53,8 +54,10 @@ std::size_t k2 = 0;

namespace test
{
struct local_spinlock : boost::noncopyable
struct local_spinlock
{
HPX_NON_COPYABLE(local_spinlock);

private:
boost::uint64_t v_;

Expand Down
5 changes: 4 additions & 1 deletion tests/performance/local/spinlock_overhead2.cpp
Expand Up @@ -4,6 +4,7 @@
// 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)

#include <hpx/config/emulate_deleted.hpp>
#include <hpx/runtime.hpp>
#include <hpx/hpx_init.hpp>
#include <hpx/lcos/wait_each.hpp>
Expand Down Expand Up @@ -55,8 +56,10 @@ std::size_t k3 = 0;

namespace test
{
struct local_spinlock : boost::noncopyable
struct local_spinlock
{
HPX_NON_COPYABLE(local_spinlock);

private:
boost::uint64_t v_;

Expand Down
46 changes: 46 additions & 0 deletions tests/unit/lcos/CMakeLists.txt
Expand Up @@ -101,3 +101,49 @@ foreach(test ${tests})
${test}_test_exe)
endforeach()

if(HPX_WITH_COMPILE_ONLY_TESTS)
# add compile time tests
set(compile_tests
fail_compile_mutex_move
fail_compile_spinlock_move
fail_compile_spinlock_no_backoff_move
)

set(fail_compile_mutex_move_FLAGS FAILURE_EXPECTED)
set(fail_compile_spinlock_move_FLAGS FAILURE_EXPECTED)
set(fail_compile_spinlock_no_backoff_move_FLAGS FAILURE_EXPECTED)

foreach(compile_test ${compile_tests})
set(sources
${compile_test}.cpp)

source_group("Source Files" FILES ${sources})

if(MSVC)
# add dummy library for MSVC to generate a project in VS
add_hpx_library(${compile_test}_compile_test
SOURCES ${sources}
EXCLUDE_FROM_ALL
FOLDER "Tests/Unit/LCOs/CompileOnly")
endif()

add_hpx_unit_compile_test(
"lcos"
${compile_test}
SOURCES ${sources}
${${compile_test}_FLAGS}
FOLDER "Tests/Unit/LCOs/CompileOnly")

# add a custom target for this example
add_hpx_pseudo_target(tests.unit.lcos.${compile_test})

# make pseudo-targets depend on master pseudo-target
add_hpx_pseudo_dependencies(tests.unit.lcos
tests.unit.lcos.${compile_test})

# add dependencies to pseudo-target
add_hpx_pseudo_dependencies(tests.unit.lcos.${compile_test}
${compile_test}_test_exe)
endforeach()
endif()

19 changes: 19 additions & 0 deletions tests/unit/lcos/fail_compile_mutex_move.cpp
@@ -0,0 +1,19 @@
// Copyright (c) 2015 Agustin Berge
//
// 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)

// This must fail compiling

#include <hpx/hpx_fwd.hpp>
#include <hpx/lcos/local/mutex.hpp>

#include <utility>

///////////////////////////////////////////////////////////////////////////////
int main()
{
using hpx::lcos::local::mutex;
mutex m1, m2(std::move(m1));
return 0;
}
19 changes: 19 additions & 0 deletions tests/unit/lcos/fail_compile_spinlock_move.cpp
@@ -0,0 +1,19 @@
// Copyright (c) 2015 Agustin Berge
//
// 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)

// This must fail compiling

#include <hpx/hpx_fwd.hpp>
#include <hpx/lcos/local/spinlock.hpp>

#include <utility>

///////////////////////////////////////////////////////////////////////////////
int main()
{
using hpx::lcos::local::spinlock;
spinlock m1, m2(std::move(m1));
return 0;
}

0 comments on commit 4d02297

Please sign in to comment.