stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,180 @@
// helper code for dealing with tracking non-boost shared_ptr/weak_ptr
// Copyright Frank Mori Hess 2009.
// 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)
// See http://www.boost.org/libs/signals2 for library home page.
#ifndef BOOST_SIGNALS2_FOREIGN_PTR_HPP
#define BOOST_SIGNALS2_FOREIGN_PTR_HPP
#include <algorithm>
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/smart_ptr/bad_weak_ptr.hpp>
#include <boost/utility/swap.hpp>
#ifndef BOOST_NO_CXX11_SMART_PTR
#include <memory>
#endif
namespace boost
{
template<typename T> class shared_ptr;
template<typename T> class weak_ptr;
namespace signals2
{
template<typename WeakPtr> struct weak_ptr_traits
{};
template<typename T> struct weak_ptr_traits<boost::weak_ptr<T> >
{
typedef boost::shared_ptr<T> shared_type;
};
#ifndef BOOST_NO_CXX11_SMART_PTR
template<typename T> struct weak_ptr_traits<std::weak_ptr<T> >
{
typedef std::shared_ptr<T> shared_type;
};
#endif
template<typename SharedPtr> struct shared_ptr_traits
{};
template<typename T> struct shared_ptr_traits<boost::shared_ptr<T> >
{
typedef boost::weak_ptr<T> weak_type;
};
#ifndef BOOST_NO_CXX11_SMART_PTR
template<typename T> struct shared_ptr_traits<std::shared_ptr<T> >
{
typedef std::weak_ptr<T> weak_type;
};
#endif
namespace detail
{
struct foreign_shared_ptr_impl_base
{
virtual ~foreign_shared_ptr_impl_base() {}
virtual foreign_shared_ptr_impl_base * clone() const = 0;
};
template<typename FSP>
class foreign_shared_ptr_impl: public foreign_shared_ptr_impl_base
{
public:
foreign_shared_ptr_impl(const FSP &p): _p(p)
{}
virtual foreign_shared_ptr_impl * clone() const
{
return new foreign_shared_ptr_impl(*this);
}
private:
FSP _p;
};
class foreign_void_shared_ptr
{
public:
foreign_void_shared_ptr():
_p(0)
{}
foreign_void_shared_ptr(const foreign_void_shared_ptr &other):
_p(other._p->clone())
{}
template<typename FSP>
explicit foreign_void_shared_ptr(const FSP &fsp):
_p(new foreign_shared_ptr_impl<FSP>(fsp))
{}
~foreign_void_shared_ptr()
{
delete _p;
}
foreign_void_shared_ptr & operator=(const foreign_void_shared_ptr &other)
{
if(&other == this) return *this;
foreign_void_shared_ptr(other).swap(*this);
return *this;
}
void swap(foreign_void_shared_ptr &other)
{
boost::swap(_p, other._p);
}
private:
foreign_shared_ptr_impl_base *_p;
};
struct foreign_weak_ptr_impl_base
{
virtual ~foreign_weak_ptr_impl_base() {}
virtual foreign_void_shared_ptr lock() const = 0;
virtual bool expired() const = 0;
virtual foreign_weak_ptr_impl_base * clone() const = 0;
};
template<typename FWP>
class foreign_weak_ptr_impl: public foreign_weak_ptr_impl_base
{
public:
foreign_weak_ptr_impl(const FWP &p): _p(p)
{}
virtual foreign_void_shared_ptr lock() const
{
return foreign_void_shared_ptr(_p.lock());
}
virtual bool expired() const
{
return _p.expired();
}
virtual foreign_weak_ptr_impl * clone() const
{
return new foreign_weak_ptr_impl(*this);
}
private:
FWP _p;
};
class foreign_void_weak_ptr
{
public:
foreign_void_weak_ptr()
{}
foreign_void_weak_ptr(const foreign_void_weak_ptr &other):
_p(other._p->clone())
{}
template<typename FWP>
explicit foreign_void_weak_ptr(const FWP &fwp):
_p(new foreign_weak_ptr_impl<FWP>(fwp))
{}
foreign_void_weak_ptr & operator=(const foreign_void_weak_ptr &other)
{
if(&other == this) return *this;
foreign_void_weak_ptr(other).swap(*this);
return *this;
}
void swap(foreign_void_weak_ptr &other)
{
boost::swap(_p, other._p);
}
foreign_void_shared_ptr lock() const
{
return _p->lock();
}
bool expired() const
{
return _p->expired();
}
private:
boost::scoped_ptr<foreign_weak_ptr_impl_base> _p;
};
} // namespace detail
} // namespace signals2
} // namespace boost
#endif // BOOST_SIGNALS2_FOREIGN_PTR_HPP
@@ -0,0 +1,38 @@
//
// boost/signals2/detail/lwm_nop.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2008 Frank Mori Hess
//
// 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)
//
#ifndef BOOST_SIGNALS2_LWM_NOP_HPP
#define BOOST_SIGNALS2_LWM_NOP_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/signals2/dummy_mutex.hpp>
namespace boost
{
namespace signals2
{
class mutex: public dummy_mutex
{
};
} // namespace signals2
} // namespace boost
#endif // #ifndef BOOST_SIGNALS2_LWM_NOP_HPP
@@ -0,0 +1,78 @@
//
// boost/signals2/detail/lwm_pthreads.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2008 Frank Mori Hess
//
// 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)
//
#ifndef BOOST_SIGNALS2_LWM_PTHREADS_HPP
#define BOOST_SIGNALS2_LWM_PTHREADS_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/assert.hpp>
#include <pthread.h>
namespace boost
{
namespace signals2
{
class mutex
{
private:
pthread_mutex_t m_;
mutex(mutex const &);
mutex & operator=(mutex const &);
public:
mutex()
{
// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
#if defined(__hpux) && defined(_DECTHREADS_)
BOOST_VERIFY(pthread_mutex_init(&m_, pthread_mutexattr_default) == 0);
#else
BOOST_VERIFY(pthread_mutex_init(&m_, 0) == 0);
#endif
}
~mutex()
{
BOOST_VERIFY(pthread_mutex_destroy(&m_) == 0);
}
void lock()
{
BOOST_VERIFY(pthread_mutex_lock(&m_) == 0);
}
bool try_lock()
{
return pthread_mutex_trylock(&m_) == 0;
}
void unlock()
{
BOOST_VERIFY(pthread_mutex_unlock(&m_) == 0);
}
};
} // namespace signals2
} // namespace boost
#endif // #ifndef BOOST_SIGNALS2_LWM_PTHREADS_HPP
@@ -0,0 +1,120 @@
//
// boost/signals2/detail/lwm_win32_cs.hpp
//
// Copyright (c) 2002, 2003 Peter Dimov
// Copyright (c) 2008 Frank Mori Hess
// Copyright (c) Microsoft Corporation 2014
//
// 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)
//
#ifndef BOOST_SIGNALS2_LWM_WIN32_CS_HPP
#define BOOST_SIGNALS2_LWM_WIN32_CS_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/assert.hpp>
#ifdef BOOST_USE_WINDOWS_H
# include <windows.h>
#endif
#include <boost/predef/platform.h>
namespace boost
{
namespace signals2
{
#ifndef BOOST_USE_WINDOWS_H
struct critical_section
{
struct critical_section_debug * DebugInfo;
long LockCount;
long RecursionCount;
void * OwningThread;
void * LockSemaphore;
#if defined(_WIN64)
unsigned __int64 SpinCount;
#else
unsigned long SpinCount;
#endif
};
#if BOOST_PLAT_WINDOWS_RUNTIME
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(critical_section *, unsigned long, unsigned long);
#else
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *);
#endif
extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *);
extern "C" __declspec(dllimport) int __stdcall TryEnterCriticalSection(critical_section *);
extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *);
extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *);
#else
typedef ::CRITICAL_SECTION critical_section;
#endif // #ifndef BOOST_USE_WINDOWS_H
class mutex
{
private:
critical_section cs_;
mutex(mutex const &);
mutex & operator=(mutex const &);
public:
mutex()
{
#if BOOST_PLAT_WINDOWS_RUNTIME
InitializeCriticalSectionEx(&cs_, 4000, 0);
#else
InitializeCriticalSection(&cs_);
#endif
}
~mutex()
{
DeleteCriticalSection(&cs_);
}
void lock()
{
EnterCriticalSection(&cs_);
}
// TryEnterCriticalSection only exists on Windows NT 4.0 and later
#if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400))
bool try_lock()
{
return TryEnterCriticalSection(&cs_) != 0;
}
#else
bool try_lock()
{
BOOST_ASSERT(false);
return false;
}
#endif
void unlock()
{
LeaveCriticalSection(&cs_);
}
};
} // namespace signals2
} // namespace boost
#endif // #ifndef BOOST_SIGNALS2_LWM_WIN32_CS_HPP
@@ -0,0 +1,34 @@
/*
An output iterator which simply discards output.
*/
// Copyright Frank Mori Hess 2008.
// 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)
// See http://www.boost.org/libs/signals2 for library home page.
#ifndef BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP
#define BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP
#include <boost/function_output_iterator.hpp>
namespace boost
{
namespace signals2
{
namespace detail
{
class does_nothing
{
public:
template<typename T>
void operator()(const T&) const
{}
};
typedef boost::function_output_iterator<does_nothing> null_output_iterator;
} // namespace detail
} // namespace signals2
} // namespace boost
#endif // BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP
@@ -0,0 +1,34 @@
// Boost.Signals2 library
// Copyright Frank Mori Hess 2007-2009.
// Copyright Timmo Stange 2007.
// Copyright Douglas Gregor 2001-2004. Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_HPP
#define BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_HPP
#include <boost/preprocessor/repetition.hpp>
#include <boost/signals2/detail/signals_common_macros.hpp>
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_INC(BOOST_SIGNALS2_MAX_ARGS))
#define BOOST_PP_FILENAME_1 <boost/signals2/detail/preprocessed_arg_type_template.hpp>
#include BOOST_PP_ITERATE()
namespace boost
{
namespace signals2
{
namespace detail
{
struct std_functional_base
{};
} // namespace detail
} // namespace signals2
} // namespace boost
#endif // BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_HPP
@@ -0,0 +1,39 @@
// Copyright Frank Mori Hess 2009
//
// Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
// This file is included iteratively, and should not be protected from multiple inclusion
#define BOOST_SIGNALS2_NUM_ARGS BOOST_PP_ITERATION()
namespace boost
{
namespace signals2
{
namespace detail
{
template<unsigned n BOOST_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
class BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
// template<typename T1, typename T2, ... , typename TN> class preprocessed_arg_typeN<n, T1, T2, ..., TN>{...} ...
#define BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_CLASS_TEMPLATE_SPECIALIZATION(z, n, data) \
template<BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)> \
class BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)<n, \
BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS)> \
{ \
public: \
typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) type; \
};
BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_CLASS_TEMPLATE_SPECIALIZATION, ~)
} // namespace detail
} // namespace signals2
} // namespace boost
#undef BOOST_SIGNALS2_NUM_ARGS
@@ -0,0 +1,32 @@
// Copyright Frank Mori Hess 2007-2009
//
// Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS2_DETAIL_REPLACE_SLOT_FUNCTION_HPP
#define BOOST_SIGNALS2_DETAIL_REPLACE_SLOT_FUNCTION_HPP
#include <boost/signals2/slot_base.hpp>
namespace boost
{
namespace signals2
{
namespace detail
{
template<typename ResultSlot, typename SlotIn, typename SlotFunction>
ResultSlot replace_slot_function(const SlotIn &slot_in, const SlotFunction &fun)
{
ResultSlot slot(fun);
slot.track(slot_in);
return slot;
}
} // namespace detail
} // namespace signals2
} // namespace boost
#endif // BOOST_SIGNALS2_DETAIL_REPLACE_SLOT_FUNCTION_HPP
@@ -0,0 +1,72 @@
// Boost.Signals2 library
// Copyright Douglas Gregor 2001-2004.
// Copyright Frank Mori Hess 2007. Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS2_RESULT_TYPE_WRAPPER_HPP
#define BOOST_SIGNALS2_RESULT_TYPE_WRAPPER_HPP
#include <boost/config.hpp>
namespace boost {
namespace signals2 {
namespace detail {
// A placeholder for void on compilers that don't support void returns
struct void_type {};
// Replaces void with void_type
template<typename R>
struct nonvoid {
typedef R type;
};
template<>
struct nonvoid<void> {
typedef void_type type;
};
// Replaces void with void_type only if compiler doesn't support void returns
template<typename R>
struct result_type_wrapper {
typedef R type;
};
#ifdef BOOST_NO_VOID_RETURNS
template<>
struct result_type_wrapper<void> {
typedef void_type type;
};
#endif
// specialization deals with possible void return from combiners
template<typename R> class combiner_invoker
{
public:
typedef R result_type;
template<typename Combiner, typename InputIterator>
result_type operator()(Combiner &combiner,
InputIterator first, InputIterator last) const
{
return combiner(first, last);
}
};
template<> class combiner_invoker<void>
{
public:
typedef result_type_wrapper<void>::type result_type;
template<typename Combiner, typename InputIterator>
result_type operator()(Combiner &combiner,
InputIterator first, InputIterator last) const
{
combiner(first, last);
return result_type();
}
};
} // end namespace detail
} // end namespace signals2
} // end namespace boost
#endif // BOOST_SIGNALS2_RESULT_TYPE_WRAPPER_HPP
@@ -0,0 +1,861 @@
/*
Template for Signa1, Signal2, ... classes that support signals
with 1, 2, ... parameters
Begin: 2007-01-23
*/
// Copyright Frank Mori Hess 2007-2008
//
// Use, modification and
// distribution is subject to 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 file is included iteratively, and should not be protected from multiple inclusion
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
#define BOOST_SIGNALS2_NUM_ARGS BOOST_PP_ITERATION()
#else
#define BOOST_SIGNALS2_NUM_ARGS 1
#endif
// R, T1, T2, ..., TN, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION \
BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS), \
Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex
namespace boost
{
namespace signals2
{
namespace detail
{
// helper for bound_extended_slot_function that handles specialization for void return
template<typename R>
class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
{
public:
typedef R result_type;
template<typename ExtendedSlotFunction BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
result_type operator()(ExtendedSlotFunction &func, const connection &conn
BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
{
return func(conn BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
}
};
#ifdef BOOST_NO_VOID_RETURNS
template<>
class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)<void>
{
public:
typedef result_type_wrapper<void>::type result_type;
template<typename ExtendedSlotFunction BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
result_type operator()(ExtendedSlotFunction &func, const connection &conn
BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
{
func(conn BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
return result_type();
}
};
#endif
// wrapper around an signalN::extended_slot_function which binds the
// connection argument so it looks like a normal
// signalN::slot_function
template<typename ExtendedSlotFunction>
class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)
{
public:
typedef typename result_type_wrapper<typename ExtendedSlotFunction::result_type>::type result_type;
BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)(const ExtendedSlotFunction &fun):
_fun(fun), _connection(new connection)
{}
void set_connection(const connection &conn)
{
*_connection = conn;
}
#if BOOST_SIGNALS2_NUM_ARGS > 0
template<BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
#endif // BOOST_SIGNALS2_NUM_ARGS > 0
result_type operator()(BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS))
{
return BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
<typename ExtendedSlotFunction::result_type>()
(_fun, *_connection BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
}
// const overload
#if BOOST_SIGNALS2_NUM_ARGS > 0
template<BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
#endif // BOOST_SIGNALS2_NUM_ARGS > 0
result_type operator()(BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
{
return BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
<typename ExtendedSlotFunction::result_type>()
(_fun, *_connection BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
}
template<typename T>
bool operator==(const T &other) const
{
return _fun == other;
}
private:
BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)()
{}
ExtendedSlotFunction _fun;
boost::shared_ptr<connection> _connection;
};
template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
class BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
class BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
{
public:
typedef SlotFunction slot_function_type;
// typedef slotN<Signature, SlotFunction> slot_type;
typedef BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS),
slot_function_type> slot_type;
typedef ExtendedSlotFunction extended_slot_function_type;
// typedef slotN+1<R, const connection &, T1, T2, ..., TN, extended_slot_function_type> extended_slot_type;
typedef BOOST_SIGNALS2_EXTENDED_SLOT_TYPE(BOOST_SIGNALS2_NUM_ARGS) extended_slot_type;
typedef typename nonvoid<typename slot_function_type::result_type>::type nonvoid_slot_result_type;
private:
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
class slot_invoker;
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
typedef variadic_slot_invoker<nonvoid_slot_result_type, Args...> slot_invoker;
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
typedef slot_call_iterator_cache<nonvoid_slot_result_type, slot_invoker> slot_call_iterator_cache_type;
typedef typename group_key<Group>::type group_key_type;
typedef shared_ptr<connection_body<group_key_type, slot_type, Mutex> > connection_body_type;
typedef grouped_list<Group, GroupCompare, connection_body_type> connection_list_type;
typedef BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)<extended_slot_function_type>
bound_extended_slot_function_type;
public:
typedef Combiner combiner_type;
typedef typename result_type_wrapper<typename combiner_type::result_type>::type result_type;
typedef Group group_type;
typedef GroupCompare group_compare_type;
typedef typename detail::slot_call_iterator_t<slot_invoker,
typename connection_list_type::iterator, connection_body<group_key_type, slot_type, Mutex> > slot_call_iterator;
BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const combiner_type &combiner_arg,
const group_compare_type &group_compare):
_shared_state(new invocation_state(connection_list_type(group_compare), combiner_arg)),
_garbage_collector_it(_shared_state->connection_bodies().end()),
_mutex(new mutex_type())
{}
// connect slot
connection connect(const slot_type &slot, connect_position position = at_back)
{
garbage_collecting_lock<mutex_type> lock(*_mutex);
return nolock_connect(lock, slot, position);
}
connection connect(const group_type &group,
const slot_type &slot, connect_position position = at_back)
{
garbage_collecting_lock<mutex_type> lock(*_mutex);
return nolock_connect(lock, group, slot, position);
}
// connect extended slot
connection connect_extended(const extended_slot_type &ext_slot, connect_position position = at_back)
{
garbage_collecting_lock<mutex_type> lock(*_mutex);
bound_extended_slot_function_type bound_slot(ext_slot.slot_function());
slot_type slot = replace_slot_function<slot_type>(ext_slot, bound_slot);
connection conn = nolock_connect(lock, slot, position);
bound_slot.set_connection(conn);
return conn;
}
connection connect_extended(const group_type &group,
const extended_slot_type &ext_slot, connect_position position = at_back)
{
garbage_collecting_lock<Mutex> lock(*_mutex);
bound_extended_slot_function_type bound_slot(ext_slot.slot_function());
slot_type slot = replace_slot_function<slot_type>(ext_slot, bound_slot);
connection conn = nolock_connect(lock, group, slot, position);
bound_slot.set_connection(conn);
return conn;
}
// disconnect slot(s)
void disconnect_all_slots()
{
shared_ptr<invocation_state> local_state =
get_readable_state();
typename connection_list_type::iterator it;
for(it = local_state->connection_bodies().begin();
it != local_state->connection_bodies().end(); ++it)
{
(*it)->disconnect();
}
}
void disconnect(const group_type &group)
{
shared_ptr<invocation_state> local_state =
get_readable_state();
group_key_type group_key(grouped_slots, group);
typename connection_list_type::iterator it;
typename connection_list_type::iterator end_it =
local_state->connection_bodies().upper_bound(group_key);
for(it = local_state->connection_bodies().lower_bound(group_key);
it != end_it; ++it)
{
(*it)->disconnect();
}
}
template <typename T>
void disconnect(const T &slot)
{
typedef mpl::bool_<(is_convertible<T, group_type>::value)> is_group;
do_disconnect(slot, is_group());
}
// emit signal
result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
{
shared_ptr<invocation_state> local_state;
typename connection_list_type::iterator it;
{
garbage_collecting_lock<mutex_type> list_lock(*_mutex);
// only clean up if it is safe to do so
if(_shared_state.unique())
nolock_cleanup_connections(list_lock, false, 1);
/* Make a local copy of _shared_state while holding mutex, so we are
thread safe against the combiner or connection list getting modified
during invocation. */
local_state = _shared_state;
}
slot_invoker invoker = slot_invoker(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
slot_call_iterator_cache_type cache(invoker);
invocation_janitor janitor(cache, *this, &local_state->connection_bodies());
return detail::combiner_invoker<typename combiner_type::result_type>()
(
local_state->combiner(),
slot_call_iterator(local_state->connection_bodies().begin(), local_state->connection_bodies().end(), cache),
slot_call_iterator(local_state->connection_bodies().end(), local_state->connection_bodies().end(), cache)
);
}
result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
{
shared_ptr<invocation_state> local_state;
typename connection_list_type::iterator it;
{
garbage_collecting_lock<mutex_type> list_lock(*_mutex);
// only clean up if it is safe to do so
if(_shared_state.unique())
nolock_cleanup_connections(list_lock, false, 1);
/* Make a local copy of _shared_state while holding mutex, so we are
thread safe against the combiner or connection list getting modified
during invocation. */
local_state = _shared_state;
}
slot_invoker invoker = slot_invoker(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
slot_call_iterator_cache_type cache(invoker);
invocation_janitor janitor(cache, *this, &local_state->connection_bodies());
return detail::combiner_invoker<typename combiner_type::result_type>()
(
local_state->combiner(),
slot_call_iterator(local_state->connection_bodies().begin(), local_state->connection_bodies().end(), cache),
slot_call_iterator(local_state->connection_bodies().end(), local_state->connection_bodies().end(), cache)
);
}
std::size_t num_slots() const
{
shared_ptr<invocation_state> local_state =
get_readable_state();
typename connection_list_type::iterator it;
std::size_t count = 0;
for(it = local_state->connection_bodies().begin();
it != local_state->connection_bodies().end(); ++it)
{
if((*it)->connected()) ++count;
}
return count;
}
bool empty() const
{
shared_ptr<invocation_state> local_state =
get_readable_state();
typename connection_list_type::iterator it;
for(it = local_state->connection_bodies().begin();
it != local_state->connection_bodies().end(); ++it)
{
if((*it)->connected()) return false;
}
return true;
}
combiner_type combiner() const
{
unique_lock<mutex_type> lock(*_mutex);
return _shared_state->combiner();
}
void set_combiner(const combiner_type &combiner_arg)
{
unique_lock<mutex_type> lock(*_mutex);
if(_shared_state.unique())
_shared_state->combiner() = combiner_arg;
else
_shared_state.reset(new invocation_state(*_shared_state, combiner_arg));
}
private:
typedef Mutex mutex_type;
// slot_invoker is passed to slot_call_iterator_t to run slots
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
class slot_invoker
{
public:
typedef nonvoid_slot_result_type result_type;
// typename add_reference<Tn>::type
#define BOOST_SIGNALS2_ADD_REF_TYPE(z, n, data) \
typename add_reference<BOOST_PP_CAT(T, BOOST_PP_INC(n))>::type
// typename add_reference<Tn>::type argn
#define BOOST_SIGNALS2_ADD_REF_ARG(z, n, data) \
BOOST_SIGNALS2_ADD_REF_TYPE(~, n, ~) \
BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~)
// typename add_reference<T1>::type arg1, typename add_reference<T2>::type arg2, ..., typename add_reference<Tn>::type argn
#define BOOST_SIGNALS2_ADD_REF_ARGS(arity) \
BOOST_PP_ENUM(arity, BOOST_SIGNALS2_ADD_REF_ARG, ~)
slot_invoker(BOOST_SIGNALS2_ADD_REF_ARGS(BOOST_SIGNALS2_NUM_ARGS)) BOOST_PP_EXPR_IF(BOOST_SIGNALS2_NUM_ARGS, :)
#undef BOOST_SIGNALS2_ADD_REF_ARGS
// m_argn
#define BOOST_SIGNALS2_M_ARG_NAME(z, n, data) BOOST_PP_CAT(m_arg, BOOST_PP_INC(n))
// m_argn ( argn )
#define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \
BOOST_SIGNALS2_M_ARG_NAME(~, n, ~) ( BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~) )
// m_arg1(arg1), m_arg2(arg2), ..., m_argn(argn)
BOOST_PP_ENUM(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_MISC_STATEMENT, ~)
#undef BOOST_SIGNALS2_MISC_STATEMENT
{}
result_type operator ()(const connection_body_type &connectionBody) const
{
return m_invoke<typename slot_type::result_type>(connectionBody);
}
private:
// declare assignment operator private since this class might have reference or const members
slot_invoker & operator=(const slot_invoker &);
#define BOOST_SIGNALS2_ADD_REF_M_ARG_STATEMENT(z, n, data) \
BOOST_SIGNALS2_ADD_REF_TYPE(~, n, ~) BOOST_SIGNALS2_M_ARG_NAME(~, n, ~) ;
BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_ADD_REF_M_ARG_STATEMENT, ~)
#undef BOOST_SIGNALS2_ADD_REF_M_ARG_STATEMENT
#undef BOOST_SIGNALS2_ADD_REF_ARG
#undef BOOST_SIGNALS2_ADD_REF_TYPE
// m_arg1, m_arg2, ..., m_argn
#define BOOST_SIGNALS2_M_ARG_NAMES(arity) BOOST_PP_ENUM(arity, BOOST_SIGNALS2_M_ARG_NAME, ~)
template<typename SlotResultType>
result_type m_invoke(const connection_body_type &connectionBody,
typename boost::enable_if<boost::is_void<SlotResultType> >::type * = 0) const
{
connectionBody->slot().slot_function()(BOOST_SIGNALS2_M_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
return void_type();
}
template<typename SlotResultType>
result_type m_invoke(const connection_body_type &connectionBody,
typename boost::disable_if<boost::is_void<SlotResultType> >::type * = 0) const
{
return connectionBody->slot().slot_function()(BOOST_SIGNALS2_M_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
}
};
#undef BOOST_SIGNALS2_M_ARG_NAMES
#undef BOOST_SIGNALS2_M_ARG_NAME
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
// a struct used to optimize (minimize) the number of shared_ptrs that need to be created
// inside operator()
class invocation_state
{
public:
invocation_state(const connection_list_type &connections_in,
const combiner_type &combiner_in): _connection_bodies(new connection_list_type(connections_in)),
_combiner(new combiner_type(combiner_in))
{}
invocation_state(const invocation_state &other, const connection_list_type &connections_in):
_connection_bodies(new connection_list_type(connections_in)),
_combiner(other._combiner)
{}
invocation_state(const invocation_state &other, const combiner_type &combiner_in):
_connection_bodies(other._connection_bodies),
_combiner(new combiner_type(combiner_in))
{}
connection_list_type & connection_bodies() { return *_connection_bodies; }
const connection_list_type & connection_bodies() const { return *_connection_bodies; }
combiner_type & combiner() { return *_combiner; }
const combiner_type & combiner() const { return *_combiner; }
private:
invocation_state(const invocation_state &);
shared_ptr<connection_list_type> _connection_bodies;
shared_ptr<combiner_type> _combiner;
};
// Destructor of invocation_janitor does some cleanup when a signal invocation completes.
// Code can't be put directly in signal's operator() due to complications from void return types.
class invocation_janitor: noncopyable
{
public:
typedef BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) signal_type;
invocation_janitor
(
const slot_call_iterator_cache_type &cache,
const signal_type &sig,
const connection_list_type *connection_bodies
):_cache(cache), _sig(sig), _connection_bodies(connection_bodies)
{}
~invocation_janitor()
{
// force a full cleanup of disconnected slots if there are too many
if(_cache.disconnected_slot_count > _cache.connected_slot_count)
{
_sig.force_cleanup_connections(_connection_bodies);
}
}
private:
const slot_call_iterator_cache_type &_cache;
const signal_type &_sig;
const connection_list_type *_connection_bodies;
};
// clean up disconnected connections
void nolock_cleanup_connections_from(garbage_collecting_lock<mutex_type> &lock,
bool grab_tracked,
const typename connection_list_type::iterator &begin, unsigned count = 0) const
{
BOOST_ASSERT(_shared_state.unique());
typename connection_list_type::iterator it;
unsigned i;
for(it = begin, i = 0;
it != _shared_state->connection_bodies().end() && (count == 0 || i < count);
++i)
{
bool connected;
if(grab_tracked)
(*it)->disconnect_expired_slot(lock);
connected = (*it)->nolock_nograb_connected();
if(connected == false)
{
it = _shared_state->connection_bodies().erase((*it)->group_key(), it);
}else
{
++it;
}
}
_garbage_collector_it = it;
}
// clean up a few connections in constant time
void nolock_cleanup_connections(garbage_collecting_lock<mutex_type> &lock,
bool grab_tracked, unsigned count) const
{
BOOST_ASSERT(_shared_state.unique());
typename connection_list_type::iterator begin;
if(_garbage_collector_it == _shared_state->connection_bodies().end())
{
begin = _shared_state->connection_bodies().begin();
}else
{
begin = _garbage_collector_it;
}
nolock_cleanup_connections_from(lock, grab_tracked, begin, count);
}
/* Make a new copy of the slot list if it is currently being read somewhere else
*/
void nolock_force_unique_connection_list(garbage_collecting_lock<mutex_type> &lock)
{
if(_shared_state.unique() == false)
{
_shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
nolock_cleanup_connections_from(lock, true, _shared_state->connection_bodies().begin());
}else
{
/* We need to try and check more than just 1 connection here to avoid corner
cases where certain repeated connect/disconnect patterns cause the slot
list to grow without limit. */
nolock_cleanup_connections(lock, true, 2);
}
}
// force a full cleanup of the connection list
void force_cleanup_connections(const connection_list_type *connection_bodies) const
{
garbage_collecting_lock<mutex_type> list_lock(*_mutex);
// if the connection list passed in as a parameter is no longer in use,
// we don't need to do any cleanup.
if(&_shared_state->connection_bodies() != connection_bodies)
{
return;
}
if(_shared_state.unique() == false)
{
_shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
}
nolock_cleanup_connections_from(list_lock, false, _shared_state->connection_bodies().begin());
}
shared_ptr<invocation_state> get_readable_state() const
{
unique_lock<mutex_type> list_lock(*_mutex);
return _shared_state;
}
connection_body_type create_new_connection(garbage_collecting_lock<mutex_type> &lock,
const slot_type &slot)
{
nolock_force_unique_connection_list(lock);
return connection_body_type(new connection_body<group_key_type, slot_type, Mutex>(slot, _mutex));
}
void do_disconnect(const group_type &group, mpl::bool_<true> /* is_group */)
{
disconnect(group);
}
template<typename T>
void do_disconnect(const T &slot, mpl::bool_<false> /* is_group */)
{
shared_ptr<invocation_state> local_state =
get_readable_state();
typename connection_list_type::iterator it;
for(it = local_state->connection_bodies().begin();
it != local_state->connection_bodies().end(); ++it)
{
garbage_collecting_lock<connection_body_base> lock(**it);
if((*it)->nolock_nograb_connected() == false) continue;
if((*it)->slot().slot_function() == slot)
{
(*it)->nolock_disconnect(lock);
}else
{
// check for wrapped extended slot
bound_extended_slot_function_type *fp;
fp = (*it)->slot().slot_function().template target<bound_extended_slot_function_type>();
if(fp && *fp == slot)
{
(*it)->nolock_disconnect(lock);
}
}
}
}
// connect slot
connection nolock_connect(garbage_collecting_lock<mutex_type> &lock,
const slot_type &slot, connect_position position)
{
connection_body_type newConnectionBody =
create_new_connection(lock, slot);
group_key_type group_key;
if(position == at_back)
{
group_key.first = back_ungrouped_slots;
_shared_state->connection_bodies().push_back(group_key, newConnectionBody);
}else
{
group_key.first = front_ungrouped_slots;
_shared_state->connection_bodies().push_front(group_key, newConnectionBody);
}
newConnectionBody->set_group_key(group_key);
return connection(newConnectionBody);
}
connection nolock_connect(garbage_collecting_lock<mutex_type> &lock,
const group_type &group,
const slot_type &slot, connect_position position)
{
connection_body_type newConnectionBody =
create_new_connection(lock, slot);
// update map to first connection body in group if needed
group_key_type group_key(grouped_slots, group);
newConnectionBody->set_group_key(group_key);
if(position == at_back)
{
_shared_state->connection_bodies().push_back(group_key, newConnectionBody);
}else // at_front
{
_shared_state->connection_bodies().push_front(group_key, newConnectionBody);
}
return connection(newConnectionBody);
}
// _shared_state is mutable so we can do force_cleanup_connections during a const invocation
mutable shared_ptr<invocation_state> _shared_state;
mutable typename connection_list_type::iterator _garbage_collector_it;
// connection list mutex must never be locked when attempting a blocking lock on a slot,
// or you could deadlock.
const boost::shared_ptr<mutex_type> _mutex;
};
template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
}
template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DEFAULTED_DECL(BOOST_SIGNALS2_NUM_ARGS)>
class BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
class BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION: public signal_base,
public detail::BOOST_SIGNALS2_STD_FUNCTIONAL_BASE
{
typedef detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> impl_class;
public:
typedef detail::BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> weak_signal_type;
friend class detail::BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>;
typedef SlotFunction slot_function_type;
// typedef slotN<Signature, SlotFunction> slot_type;
typedef typename impl_class::slot_type slot_type;
typedef typename impl_class::extended_slot_function_type extended_slot_function_type;
typedef typename impl_class::extended_slot_type extended_slot_type;
typedef typename slot_function_type::result_type slot_result_type;
typedef Combiner combiner_type;
typedef typename impl_class::result_type result_type;
typedef Group group_type;
typedef GroupCompare group_compare_type;
typedef typename impl_class::slot_call_iterator
slot_call_iterator;
typedef typename mpl::identity<BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(BOOST_SIGNALS2_NUM_ARGS)>::type signature_type;
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
// typedef Tn argn_type;
#define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \
typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type);
BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_MISC_STATEMENT, ~)
#undef BOOST_SIGNALS2_MISC_STATEMENT
#if BOOST_SIGNALS2_NUM_ARGS == 1
typedef arg1_type argument_type;
#elif BOOST_SIGNALS2_NUM_ARGS == 2
typedef arg1_type first_argument_type;
typedef arg2_type second_argument_type;
#endif
template<unsigned n> class arg : public
detail::BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<n BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS)>
{};
BOOST_STATIC_CONSTANT(int, arity = BOOST_SIGNALS2_NUM_ARGS);
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<unsigned n> class arg
{
public:
typedef typename detail::variadic_arg_type<n, Args...>::type type;
};
BOOST_STATIC_CONSTANT(int, arity = sizeof...(Args));
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const combiner_type &combiner_arg = combiner_type(),
const group_compare_type &group_compare = group_compare_type()):
_pimpl(new impl_class(combiner_arg, group_compare))
{};
virtual ~BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)()
{
}
//move support
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(
BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) && other)
{
using std::swap;
swap(_pimpl, other._pimpl);
};
BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) &
operator=(BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) && rhs)
{
if(this == &rhs)
{
return *this;
}
_pimpl.reset();
using std::swap;
swap(_pimpl, rhs._pimpl);
return *this;
}
#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
connection connect(const slot_type &slot, connect_position position = at_back)
{
return (*_pimpl).connect(slot, position);
}
connection connect(const group_type &group,
const slot_type &slot, connect_position position = at_back)
{
return (*_pimpl).connect(group, slot, position);
}
connection connect_extended(const extended_slot_type &slot, connect_position position = at_back)
{
return (*_pimpl).connect_extended(slot, position);
}
connection connect_extended(const group_type &group,
const extended_slot_type &slot, connect_position position = at_back)
{
return (*_pimpl).connect_extended(group, slot, position);
}
void disconnect_all_slots()
{
(*_pimpl).disconnect_all_slots();
}
void disconnect(const group_type &group)
{
(*_pimpl).disconnect(group);
}
template <typename T>
void disconnect(const T &slot)
{
(*_pimpl).disconnect(slot);
}
result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
{
return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
}
result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
{
return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
}
std::size_t num_slots() const
{
return (*_pimpl).num_slots();
}
bool empty() const
{
return (*_pimpl).empty();
}
combiner_type combiner() const
{
return (*_pimpl).combiner();
}
void set_combiner(const combiner_type &combiner_arg)
{
return (*_pimpl).set_combiner(combiner_arg);
}
void swap(BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) & other)
{
using std::swap;
swap(_pimpl, other._pimpl);
}
protected:
virtual shared_ptr<void> lock_pimpl() const
{
return _pimpl;
}
private:
shared_ptr<impl_class>
_pimpl;
};
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
// free swap function for signalN classes, findable by ADL
template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
void swap(
BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> &sig1,
BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> &sig2 )
{
sig1.swap(sig2);
}
#endif
namespace detail
{
// wrapper class for storing other signals as slots with automatic lifetime tracking
template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
{
public:
typedef typename BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>::result_type
result_type;
BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
(const BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>
&signal):
_weak_pimpl(signal._pimpl)
{}
result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
{
shared_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> >
shared_pimpl(_weak_pimpl.lock());
return (*shared_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
}
result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
{
shared_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> >
shared_pimpl(_weak_pimpl.lock());
return (*shared_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
}
private:
boost::weak_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> > _weak_pimpl;
};
#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<int arity, typename Signature>
class extended_signature: public variadic_extended_signature<Signature>
{};
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<int arity, typename Signature>
class extended_signature;
// partial template specialization
template<typename Signature>
class extended_signature<BOOST_SIGNALS2_NUM_ARGS, Signature>
{
public:
// typename function_traits<Signature>::result_type (
// const boost::signals2::connection &,
// typename function_traits<Signature>::arg1_type,
// typename function_traits<Signature>::arg2_type,
// ...,
// typename function_traits<Signature>::argn_type)
#define BOOST_SIGNALS2_EXT_SIGNATURE(arity, Signature) \
typename function_traits<Signature>::result_type ( \
const boost::signals2::connection & BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS) \
BOOST_PP_ENUM(arity, BOOST_SIGNALS2_SIGNATURE_TO_ARGN_TYPE, Signature) )
typedef function<BOOST_SIGNALS2_EXT_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature)> function_type;
#undef BOOST_SIGNALS2_EXT_SIGNATURE
};
template<unsigned arity, typename Signature, typename Combiner,
typename Group, typename GroupCompare, typename SlotFunction,
typename ExtendedSlotFunction, typename Mutex>
class signalN;
// partial template specialization
template<typename Signature, typename Combiner, typename Group,
typename GroupCompare, typename SlotFunction,
typename ExtendedSlotFunction, typename Mutex>
class signalN<BOOST_SIGNALS2_NUM_ARGS, Signature, Combiner, Group,
GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex>
{
public:
typedef BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)<
BOOST_SIGNALS2_PORTABLE_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature),
Combiner, Group,
GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex> type;
};
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
} // namespace detail
} // namespace signals2
} // namespace boost
#undef BOOST_SIGNALS2_NUM_ARGS
#undef BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION
@@ -0,0 +1,77 @@
// Boost.Signals library
// Copyright Douglas Gregor 2001-2004.
// Copyright Frank Mori Hess 2007. Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS2_SIGNALS_COMMON_HPP
#define BOOST_SIGNALS2_SIGNALS_COMMON_HPP
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/ref.hpp>
#include <boost/signals2/signal_base.hpp>
#include <boost/type_traits/is_base_of.hpp>
namespace boost {
namespace signals2 {
namespace detail {
// Determine if the given type T is a signal
template<typename T>
class is_signal: public mpl::bool_<is_base_of<signal_base, T>::value>
{};
// A slot can be a signal, a reference to a function object, or a
// function object.
struct signal_tag {};
struct reference_tag {};
struct value_tag {};
// Classify the given slot as a signal, a reference-to-slot, or a
// standard slot
template<typename S>
class get_slot_tag {
typedef typename mpl::if_<is_signal<S>,
signal_tag, value_tag>::type signal_or_value;
public:
typedef typename mpl::if_<is_reference_wrapper<S>,
reference_tag,
signal_or_value>::type type;
};
// Get the slot so that it can be copied
template<typename F>
typename F::weak_signal_type
get_invocable_slot(const F &signal, signal_tag)
{ return typename F::weak_signal_type(signal); }
template<typename F>
const F&
get_invocable_slot(const F& f, reference_tag)
{ return f; }
template<typename F>
const F&
get_invocable_slot(const F& f, value_tag)
{ return f; }
// Determines the type of the slot - is it a signal, a reference to a
// slot or just a normal slot.
template<typename F>
typename get_slot_tag<F>::type
tag_type(const F&)
{
typedef typename get_slot_tag<F>::type
the_tag_type;
the_tag_type tag = the_tag_type();
return tag;
}
} // end namespace detail
} // end namespace signals2
} // end namespace boost
#endif // BOOST_SIGNALS2_SIGNALS_COMMON_HPP
@@ -0,0 +1,215 @@
/*
Author: Frank Mori Hess <fmhess@users.sourceforge.net>
Begin: 2007-01-23
*/
// Copyright Frank Mori Hess 2007-2008
// Use, modification and
// distribution is subject to 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)
#ifndef BOOST_SIGNALS2_SIGNALS_COMMON_MACROS_HPP
#define BOOST_SIGNALS2_SIGNALS_COMMON_MACROS_HPP
#include <boost/config.hpp>
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
#ifndef BOOST_SIGNALS2_MAX_ARGS
#define BOOST_SIGNALS2_MAX_ARGS 9
#endif
// signaln
#define BOOST_SIGNALS2_SIGNAL_CLASS_NAME(arity) BOOST_PP_CAT(signal, arity)
// weak_signaln
#define BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(arity) BOOST_PP_CAT(weak_, BOOST_SIGNALS2_SIGNAL_CLASS_NAME(arity))
// signaln_impl
#define BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(arity) BOOST_PP_CAT(BOOST_SIGNALS2_SIGNAL_CLASS_NAME(arity), _impl)
// argn
#define BOOST_SIGNALS2_SIGNATURE_ARG_NAME(z, n, data) BOOST_PP_CAT(arg, BOOST_PP_INC(n))
// Tn argn
#define BOOST_SIGNALS2_SIGNATURE_FULL_ARG(z, n, data) \
BOOST_PP_CAT(T, BOOST_PP_INC(n)) BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~)
// T1 arg1, T2 arg2, ..., Tn argn
#define BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(arity) \
BOOST_PP_ENUM(arity, BOOST_SIGNALS2_SIGNATURE_FULL_ARG, ~)
// arg1, arg2, ..., argn
#define BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(arity) BOOST_PP_ENUM(arity, BOOST_SIGNALS2_SIGNATURE_ARG_NAME, ~)
// T1, T2, ..., TN
#define BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(arity) \
BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), T)
// R (T1, T2, ..., TN)
#define BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(arity) \
R ( BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(arity) )
// typename prefixR, typename prefixT1, typename prefixT2, ..., typename prefixTN
#define BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(arity, prefix) \
typename BOOST_PP_CAT(prefix, R) BOOST_PP_COMMA_IF(arity) \
BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), typename BOOST_PP_CAT(prefix, T))
// typename R, typename T1, typename T2, ..., typename TN
#define BOOST_SIGNALS2_SIGNATURE_TEMPLATE_DECL(arity) \
typename R BOOST_PP_COMMA_IF(arity) \
BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), typename T)
// typename prefixT1, typename prefixT2, ..., typename prefixTN
#define BOOST_SIGNALS2_PREFIXED_ARGS_TEMPLATE_DECL(arity, prefix) \
BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), typename BOOST_PP_CAT(prefix, T))
// typename T1, typename T2, ..., typename TN
#define BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(arity) \
BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), typename T)
// prefixR, prefixT1, prefixT2, ..., prefixTN
#define BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_INSTANTIATION(arity, prefix) \
BOOST_PP_CAT(prefix, R) BOOST_PP_COMMA_IF(arity) BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), BOOST_PP_CAT(prefix, T))
// R, T1, T2, ..., TN
#define BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(arity) \
R BOOST_PP_COMMA_IF(arity) BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), T)
// boost::functionN<R, T1, T2, ..., TN>
#define BOOST_SIGNALS2_FUNCTION_N_DECL(arity) BOOST_PP_CAT(boost::function, arity)<\
BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(arity) >
// R, const boost::signals2::connection&, T1, T2, ..., TN
#define BOOST_SIGNALS2_EXT_SLOT_TEMPLATE_INSTANTIATION(arity) \
R, const boost::signals2::connection& BOOST_PP_COMMA_IF(arity) \
BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), T)
// boost::functionN<R, const boost::signals2::connection &, T1, T2, ..., TN>
#define BOOST_SIGNALS2_EXT_FUNCTION_N_DECL(arity) BOOST_PP_CAT(boost::function, BOOST_PP_INC(arity))<\
BOOST_SIGNALS2_EXT_SLOT_TEMPLATE_INSTANTIATION(arity) >
// slotN
#define BOOST_SIGNALS2_SLOT_CLASS_NAME(arity) BOOST_PP_CAT(slot, arity)
// slotN+1<R, const connection &, T1, T2, ..., TN, extended_slot_function_type>
#define BOOST_SIGNALS2_EXTENDED_SLOT_TYPE(arity) \
BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_PP_INC(arity))< \
BOOST_SIGNALS2_EXT_SLOT_TEMPLATE_INSTANTIATION(arity), \
extended_slot_function_type>
// bound_extended_slot_functionN
#define BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(arity) BOOST_PP_CAT(bound_extended_slot_function, arity)
// bound_extended_slot_function_helperN
#define BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(arity) BOOST_PP_CAT(bound_extended_slot_function_invoker, arity)
// typename function_traits<Signature>::argn_type
#define BOOST_SIGNALS2_SIGNATURE_TO_ARGN_TYPE(z, n, Signature) \
BOOST_PP_CAT(BOOST_PP_CAT(typename function_traits<Signature>::arg, BOOST_PP_INC(n)), _type)
// typename function_traits<Signature>::result_type,
// typename function_traits<Signature>::arg1_type,
// typename function_traits<Signature>::arg2_type,
// ...,
// typename function_traits<Signature>::argn_type
#define BOOST_SIGNALS2_PORTABLE_SIGNATURE(arity, Signature) \
typename function_traits<Signature>::result_type \
BOOST_PP_COMMA_IF(arity) BOOST_PP_ENUM(arity, BOOST_SIGNALS2_SIGNATURE_TO_ARGN_TYPE, Signature)
// prefixTn & argn
#define BOOST_SIGNALS2_PREFIXED_FULL_REF_ARG(z, n, prefix) \
BOOST_PP_CAT(BOOST_PP_CAT(prefix, T), BOOST_PP_INC(n)) & BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~)
// prefixT1 & arg1, prefixT2 & arg2, ..., prefixTn & argn
#define BOOST_SIGNALS2_PREFIXED_FULL_REF_ARGS(arity, prefix) \
BOOST_PP_ENUM(arity, BOOST_SIGNALS2_PREFIXED_FULL_REF_ARG, prefix)
// Tn & argn
#define BOOST_SIGNALS2_FULL_CREF_ARG(z, n, data) \
const BOOST_PP_CAT(T, BOOST_PP_INC(n)) & BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~)
// const T1 & arg1, const T2 & arg2, ..., const Tn & argn
#define BOOST_SIGNALS2_FULL_FORWARD_ARGS(arity) \
BOOST_PP_ENUM(arity, BOOST_SIGNALS2_FULL_CREF_ARG, ~)
#define BOOST_SIGNALS2_FORWARDED_ARGS(arity) \
BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(arity)
// preprocessed_arg_typeN
#define BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(arity) BOOST_PP_CAT(preprocessed_arg_type, arity)
// typename R, typename T1, typename T2, ..., typename TN, typename SlotFunction
#define BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION_DECL(arity) \
BOOST_SIGNALS2_SIGNATURE_TEMPLATE_DECL(arity), \
typename SlotFunction
#define BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION
// typename R, typename T1, typename T2, ..., typename TN, typename Combiner, ...
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(arity) \
BOOST_SIGNALS2_SIGNATURE_TEMPLATE_DECL(arity), \
typename Combiner, \
typename Group, \
typename GroupCompare, \
typename SlotFunction, \
typename ExtendedSlotFunction, \
typename Mutex
// typename R, typename T1, typename T2, ..., typename TN, typename Combiner = optional_last_value<R>, ...
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_DEFAULTED_DECL(arity) \
BOOST_SIGNALS2_SIGNATURE_TEMPLATE_DECL(arity), \
typename Combiner = optional_last_value<R>, \
typename Group = int, \
typename GroupCompare = std::less<Group>, \
typename SlotFunction = BOOST_SIGNALS2_FUNCTION_N_DECL(arity), \
typename ExtendedSlotFunction = BOOST_SIGNALS2_EXT_FUNCTION_N_DECL(arity), \
typename Mutex = signals2::mutex
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(arity) BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(arity)
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
#define BOOST_SIGNALS2_STD_FUNCTIONAL_BASE std_functional_base
#define BOOST_SIGNALS2_PP_COMMA_IF(arity) BOOST_PP_COMMA_IF(arity)
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
#define BOOST_SIGNALS2_SIGNAL_CLASS_NAME(arity) signal
#define BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(arity) weak_signal
#define BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(arity) signal_impl
#define BOOST_SIGNALS2_SIGNATURE_TEMPLATE_DECL(arity) typename Signature
#define BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(arity) Args...
#define BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(arity) R (Args...)
#define BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(arity) R (Args...)
#define BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(arity) typename ... Args
#define BOOST_SIGNALS2_FULL_FORWARD_ARGS(arity) Args && ... args
#define BOOST_SIGNALS2_FORWARDED_ARGS(arity) std::forward<Args>(args)...
#define BOOST_SIGNALS2_SLOT_CLASS_NAME(arity) slot
#define BOOST_SIGNALS2_EXTENDED_SLOT_TYPE(arity) slot<R (const connection &, Args...), extended_slot_function_type>
#define BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(arity) bound_extended_slot_function
#define BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(arity) bound_extended_slot_function_invoker
#define BOOST_SIGNALS2_FUNCTION_N_DECL(arity) boost::function<Signature>
#define BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(arity, prefix) typename prefixSignature
#define BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_INSTANTIATION(arity, prefix) prefixSignature
#define BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(arity) Args ... args
#define BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(arity) args...
#define BOOST_SIGNALS2_PORTABLE_SIGNATURE(arity, Signature) Signature
#define BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION_DECL(arity) \
typename SlotFunction, \
typename R, \
typename ... Args
#define BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION \
<R (Args...), SlotFunction>
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(arity) \
typename Signature, \
typename Combiner, \
typename Group, \
typename GroupCompare, \
typename SlotFunction, \
typename ExtendedSlotFunction, \
typename Mutex
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_DEFAULTED_DECL(arity) \
typename Signature, \
typename Combiner = optional_last_value<typename boost::function_traits<Signature>::result_type>, \
typename Group = int, \
typename GroupCompare = std::less<Group>, \
typename SlotFunction = boost::function<Signature>, \
typename ExtendedSlotFunction = typename detail::variadic_extended_signature<Signature>::function_type, \
typename Mutex = signals2::mutex
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(arity) \
typename Combiner, \
typename Group, \
typename GroupCompare, \
typename SlotFunction, \
typename ExtendedSlotFunction, \
typename Mutex, \
typename R, \
typename ... Args
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION <\
R (Args...), \
Combiner, \
Group, \
GroupCompare, \
SlotFunction, \
ExtendedSlotFunction, \
Mutex>
#define BOOST_SIGNALS2_STD_FUNCTIONAL_BASE \
std_functional_base<Args...>
#define BOOST_SIGNALS2_PP_COMMA_IF(arity) ,
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif // BOOST_SIGNALS2_SIGNALS_COMMON_MACROS_HPP
@@ -0,0 +1,196 @@
// Boost.Signals2 library
// Copyright Douglas Gregor 2001-2004.
// Copyright Frank Mori Hess 2007-2008.
// Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP
#define BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP
#include <boost/assert.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/optional.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/signals2/connection.hpp>
#include <boost/signals2/slot_base.hpp>
#include <boost/signals2/detail/auto_buffer.hpp>
#include <boost/signals2/detail/unique_lock.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/weak_ptr.hpp>
namespace boost {
namespace signals2 {
namespace detail {
template<typename ResultType, typename Function>
class slot_call_iterator_cache
{
public:
slot_call_iterator_cache(const Function &f_arg):
f(f_arg),
connected_slot_count(0),
disconnected_slot_count(0),
m_active_slot(0)
{}
~slot_call_iterator_cache()
{
if(m_active_slot)
{
garbage_collecting_lock<connection_body_base> lock(*m_active_slot);
m_active_slot->dec_slot_refcount(lock);
}
}
template<typename M>
void set_active_slot(garbage_collecting_lock<M> &lock,
connection_body_base *active_slot)
{
if(m_active_slot)
m_active_slot->dec_slot_refcount(lock);
m_active_slot = active_slot;
if(m_active_slot)
m_active_slot->inc_slot_refcount(lock);
}
optional<ResultType> result;
typedef auto_buffer<void_shared_ptr_variant, store_n_objects<10> > tracked_ptrs_type;
tracked_ptrs_type tracked_ptrs;
Function f;
unsigned connected_slot_count;
unsigned disconnected_slot_count;
connection_body_base *m_active_slot;
};
// Generates a slot call iterator. Essentially, this is an iterator that:
// - skips over disconnected slots in the underlying list
// - calls the connected slots when dereferenced
// - caches the result of calling the slots
template<typename Function, typename Iterator, typename ConnectionBody>
class slot_call_iterator_t
: public boost::iterator_facade<slot_call_iterator_t<Function, Iterator, ConnectionBody>,
typename Function::result_type,
boost::single_pass_traversal_tag,
typename boost::add_const<typename boost::add_reference<typename Function::result_type>::type>::type >
{
typedef boost::iterator_facade<slot_call_iterator_t<Function, Iterator, ConnectionBody>,
typename Function::result_type,
boost::single_pass_traversal_tag,
typename boost::add_const<typename boost::add_reference<typename Function::result_type>::type>::type >
inherited;
typedef typename Function::result_type result_type;
typedef slot_call_iterator_cache<result_type, Function> cache_type;
friend class boost::iterator_core_access;
public:
slot_call_iterator_t(Iterator iter_in, Iterator end_in,
cache_type &c):
iter(iter_in), end(end_in),
cache(&c), callable_iter(end_in)
{
lock_next_callable();
}
typename inherited::reference
dereference() const
{
if (!cache->result) {
BOOST_TRY
{
cache->result.reset(cache->f(*iter));
}
BOOST_CATCH(expired_slot &)
{
(*iter)->disconnect();
BOOST_RETHROW
}
BOOST_CATCH_END
}
return cache->result.get();
}
void increment()
{
++iter;
lock_next_callable();
cache->result.reset();
}
bool equal(const slot_call_iterator_t& other) const
{
return iter == other.iter;
}
private:
typedef garbage_collecting_lock<connection_body_base> lock_type;
void set_callable_iter(lock_type &lock, Iterator newValue) const
{
callable_iter = newValue;
if(callable_iter == end)
cache->set_active_slot(lock, 0);
else
cache->set_active_slot(lock, (*callable_iter).get());
}
void lock_next_callable() const
{
if(iter == callable_iter)
{
return;
}
if(iter == end)
{
if(callable_iter != end)
{
lock_type lock(**callable_iter);
set_callable_iter(lock, end);
return;
}
}
// we're only locking the first connection body,
// but it doesn't matter they all use the same mutex
lock_type lock(**iter);
for(;iter != end; ++iter)
{
cache->tracked_ptrs.clear();
(*iter)->nolock_grab_tracked_objects(lock, std::back_inserter(cache->tracked_ptrs));
if((*iter)->nolock_nograb_connected())
{
++cache->connected_slot_count;
}else
{
++cache->disconnected_slot_count;
}
if((*iter)->nolock_nograb_blocked() == false)
{
set_callable_iter(lock, iter);
break;
}
}
if(iter == end)
{
set_callable_iter(lock, end);
}
}
mutable Iterator iter;
Iterator end;
cache_type *cache;
mutable Iterator callable_iter;
};
} // end namespace detail
} // end namespace BOOST_SIGNALS_NAMESPACE
} // end namespace boost
#endif // BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP
@@ -0,0 +1,235 @@
// Boost.Signals2 library
// Copyright Frank Mori Hess 2007-2008.
// Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS2_SLOT_GROUPS_HPP
#define BOOST_SIGNALS2_SLOT_GROUPS_HPP
#include <boost/signals2/connection.hpp>
#include <boost/optional.hpp>
#include <list>
#include <map>
#include <utility>
namespace boost {
namespace signals2 {
namespace detail {
enum slot_meta_group {front_ungrouped_slots, grouped_slots, back_ungrouped_slots};
template<typename Group>
struct group_key
{
typedef std::pair<enum slot_meta_group, boost::optional<Group> > type;
};
template<typename Group, typename GroupCompare>
class group_key_less
{
public:
group_key_less()
{}
group_key_less(const GroupCompare &group_compare): _group_compare(group_compare)
{}
bool operator ()(const typename group_key<Group>::type &key1, const typename group_key<Group>::type &key2) const
{
if(key1.first != key2.first) return key1.first < key2.first;
if(key1.first != grouped_slots) return false;
return _group_compare(key1.second.get(), key2.second.get());
}
private:
GroupCompare _group_compare;
};
template<typename Group, typename GroupCompare, typename ValueType>
class grouped_list
{
public:
typedef group_key_less<Group, GroupCompare> group_key_compare_type;
private:
typedef std::list<ValueType> list_type;
typedef std::map
<
typename group_key<Group>::type,
typename list_type::iterator,
group_key_compare_type
> map_type;
typedef typename map_type::iterator map_iterator;
typedef typename map_type::const_iterator const_map_iterator;
public:
typedef typename list_type::iterator iterator;
typedef typename list_type::const_iterator const_iterator;
typedef typename group_key<Group>::type group_key_type;
grouped_list(const group_key_compare_type &group_key_compare):
_group_key_compare(group_key_compare)
{}
grouped_list(const grouped_list &other): _list(other._list),
_group_map(other._group_map), _group_key_compare(other._group_key_compare)
{
// fix up _group_map
typename map_type::const_iterator other_map_it;
typename list_type::iterator this_list_it = _list.begin();
typename map_type::iterator this_map_it = _group_map.begin();
for(other_map_it = other._group_map.begin();
other_map_it != other._group_map.end();
++other_map_it, ++this_map_it)
{
BOOST_ASSERT(this_map_it != _group_map.end());
this_map_it->second = this_list_it;
typename list_type::const_iterator other_list_it = other.get_list_iterator(other_map_it);
typename map_type::const_iterator other_next_map_it = other_map_it;
++other_next_map_it;
typename list_type::const_iterator other_next_list_it = other.get_list_iterator(other_next_map_it);
while(other_list_it != other_next_list_it)
{
++other_list_it;
++this_list_it;
}
}
}
iterator begin()
{
return _list.begin();
}
iterator end()
{
return _list.end();
}
iterator lower_bound(const group_key_type &key)
{
map_iterator map_it = _group_map.lower_bound(key);
return get_list_iterator(map_it);
}
iterator upper_bound(const group_key_type &key)
{
map_iterator map_it = _group_map.upper_bound(key);
return get_list_iterator(map_it);
}
void push_front(const group_key_type &key, const ValueType &value)
{
map_iterator map_it;
if(key.first == front_ungrouped_slots)
{// optimization
map_it = _group_map.begin();
}else
{
map_it = _group_map.lower_bound(key);
}
m_insert(map_it, key, value);
}
void push_back(const group_key_type &key, const ValueType &value)
{
map_iterator map_it;
if(key.first == back_ungrouped_slots)
{// optimization
map_it = _group_map.end();
}else
{
map_it = _group_map.upper_bound(key);
}
m_insert(map_it, key, value);
}
void erase(const group_key_type &key)
{
map_iterator map_it = _group_map.lower_bound(key);
iterator begin_list_it = get_list_iterator(map_it);
iterator end_list_it = upper_bound(key);
if(begin_list_it != end_list_it)
{
_list.erase(begin_list_it, end_list_it);
_group_map.erase(map_it);
}
}
iterator erase(const group_key_type &key, const iterator &it)
{
BOOST_ASSERT(it != _list.end());
map_iterator map_it = _group_map.lower_bound(key);
BOOST_ASSERT(map_it != _group_map.end());
BOOST_ASSERT(weakly_equivalent(map_it->first, key));
if(map_it->second == it)
{
iterator next = it;
++next;
// if next is in same group
if(next != upper_bound(key))
{
_group_map[key] = next;
}else
{
_group_map.erase(map_it);
}
}
return _list.erase(it);
}
void clear()
{
_list.clear();
_group_map.clear();
}
private:
/* Suppress default assignment operator, since it has the wrong semantics. */
grouped_list& operator=(const grouped_list &other);
bool weakly_equivalent(const group_key_type &arg1, const group_key_type &arg2)
{
if(_group_key_compare(arg1, arg2)) return false;
if(_group_key_compare(arg2, arg1)) return false;
return true;
}
void m_insert(const map_iterator &map_it, const group_key_type &key, const ValueType &value)
{
iterator list_it = get_list_iterator(map_it);
iterator new_it = _list.insert(list_it, value);
if(map_it != _group_map.end() && weakly_equivalent(key, map_it->first))
{
_group_map.erase(map_it);
}
map_iterator lower_bound_it = _group_map.lower_bound(key);
if(lower_bound_it == _group_map.end() ||
weakly_equivalent(lower_bound_it->first, key) == false)
{
/* doing the following instead of just
_group_map[key] = new_it;
to avoid bogus error when enabling checked iterators with g++ */
_group_map.insert(typename map_type::value_type(key, new_it));
}
}
iterator get_list_iterator(const const_map_iterator &map_it)
{
iterator list_it;
if(map_it == _group_map.end())
{
list_it = _list.end();
}else
{
list_it = map_it->second;
}
return list_it;
}
const_iterator get_list_iterator(const const_map_iterator &map_it) const
{
const_iterator list_it;
if(map_it == _group_map.end())
{
list_it = _list.end();
}else
{
list_it = map_it->second;
}
return list_it;
}
list_type _list;
// holds iterators to first list item in each group
map_type _group_map;
group_key_compare_type _group_key_compare;
};
} // end namespace detail
enum connect_position { at_back, at_front };
} // end namespace signals2
} // end namespace boost
#endif // BOOST_SIGNALS2_SLOT_GROUPS_HPP
@@ -0,0 +1,187 @@
// Boost.Signals2 library
// Copyright Frank Mori Hess 2007-2008.
// Copyright Timmo Stange 2007.
// Copyright Douglas Gregor 2001-2004. Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
// This file is included iteratively, and should not be protected from multiple inclusion
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
#define BOOST_SIGNALS2_NUM_ARGS BOOST_PP_ITERATION()
#else
#define BOOST_SIGNALS2_NUM_ARGS 1
#endif
namespace boost
{
namespace signals2
{
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<typename Signature, typename SlotFunction> class slot;
#else
template<typename Signature, typename SlotFunction = boost::function<Signature> >
class slot;
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1900)
template<typename Signature, typename SlotFunction> class slot{};
#endif
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
class BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION
: public slot_base, public detail::BOOST_SIGNALS2_STD_FUNCTIONAL_BASE
{
public:
template<BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS, Other), typename OtherSlotFunction>
friend class BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
typedef SlotFunction slot_function_type;
typedef R result_type;
typedef typename mpl::identity<BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(BOOST_SIGNALS2_NUM_ARGS)>::type signature_type;
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
// typedef Tn argn_type;
#define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \
typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type);
BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_MISC_STATEMENT, ~)
#undef BOOST_SIGNALS2_MISC_STATEMENT
#if BOOST_SIGNALS2_NUM_ARGS == 1
typedef arg1_type argument_type;
#elif BOOST_SIGNALS2_NUM_ARGS == 2
typedef arg1_type first_argument_type;
typedef arg2_type second_argument_type;
#endif
template<unsigned n> class arg : public
detail::BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<n BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS)>
{};
BOOST_STATIC_CONSTANT(int, arity = BOOST_SIGNALS2_NUM_ARGS);
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<unsigned n> class arg
{
public:
typedef typename detail::variadic_arg_type<n, Args...>::type type;
};
BOOST_STATIC_CONSTANT(int, arity = sizeof...(Args));
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<typename F>
BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const F& f)
{
init_slot_function(f);
}
// copy constructors
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS, Other), typename OtherSlotFunction>
BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS, Other), OtherSlotFunction> &other_slot):
slot_base(other_slot), _slot_function(other_slot._slot_function)
{
}
#endif
template<typename Signature, typename OtherSlotFunction>
BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const slot<Signature, OtherSlotFunction> &other_slot):
slot_base(other_slot), _slot_function(other_slot._slot_function)
{
}
// bind syntactic sugar
BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTORS
// invocation
R operator()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
{
locked_container_type locked_objects = lock();
return _slot_function(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
}
R operator()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
{
locked_container_type locked_objects = lock();
return _slot_function(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
}
// tracking
BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track(const weak_ptr<void> &tracked) {
_tracked_objects.push_back(tracked);
return *this;
}
BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track(const signal_base &signal)
{
track_signal(signal);
return *this;
}
BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track(const slot_base &slot)
{
tracked_container_type::const_iterator it;
for(it = slot.tracked_objects().begin(); it != slot.tracked_objects().end(); ++it)
{
_tracked_objects.push_back(*it);
}
return *this;
}
template<typename ForeignWeakPtr>
BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track_foreign(const ForeignWeakPtr &tracked,
typename weak_ptr_traits<ForeignWeakPtr>::shared_type * /*SFINAE*/ = 0)
{
_tracked_objects.push_back(detail::foreign_void_weak_ptr(tracked));
return *this;
}
template<typename ForeignSharedPtr>
BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track_foreign(const ForeignSharedPtr &tracked,
typename shared_ptr_traits<ForeignSharedPtr>::weak_type * /*SFINAE*/ = 0)
{
_tracked_objects.push_back
(
detail::foreign_void_weak_ptr
(
typename shared_ptr_traits<ForeignSharedPtr>::weak_type(tracked)
)
);
return *this;
}
const slot_function_type& slot_function() const {return _slot_function;}
slot_function_type& slot_function() {return _slot_function;}
private:
template<typename F>
void init_slot_function(const F& f)
{
_slot_function = detail::get_invocable_slot(f, detail::tag_type(f));
signals2::detail::tracked_objects_visitor visitor(this);
boost::visit_each(visitor, f);
}
SlotFunction _slot_function;
};
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
namespace detail
{
template<unsigned arity, typename Signature, typename SlotFunction>
class slotN;
// partial template specialization
template<typename Signature, typename SlotFunction>
class slotN<BOOST_SIGNALS2_NUM_ARGS, Signature, SlotFunction>
{
public:
typedef BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)<
BOOST_SIGNALS2_PORTABLE_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature),
SlotFunction> type;
};
}
#endif
} // end namespace signals2
} // end namespace boost
#undef BOOST_SIGNALS2_NUM_ARGS
@@ -0,0 +1,98 @@
// Boost.Signals2 library
// Copyright Frank Mori Hess 2007-2008.
// Copyright Timmo Stange 2007.
// Copyright Douglas Gregor 2001-2004. Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP
#define BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP
#include <boost/mpl/bool.hpp>
#include <boost/ref.hpp>
#include <boost/signals2/detail/signals_common.hpp>
#include <boost/signals2/slot_base.hpp>
#include <boost/signals2/trackable.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/utility/addressof.hpp>
namespace boost
{
namespace signals2
{
namespace detail
{
// Visitor to collect tracked objects from a bound function.
class tracked_objects_visitor
{
public:
tracked_objects_visitor(slot_base *slot) : slot_(slot)
{}
template<typename T>
void operator()(const T& t) const
{
m_visit_reference_wrapper(t, mpl::bool_<is_reference_wrapper<T>::value>());
}
private:
template<typename T>
void m_visit_reference_wrapper(const reference_wrapper<T> &t, const mpl::bool_<true> &) const
{
m_visit_pointer(t.get_pointer(), mpl::bool_<true>());
}
template<typename T>
void m_visit_reference_wrapper(const T &t, const mpl::bool_<false> &) const
{
m_visit_pointer(t, mpl::bool_<is_pointer<T>::value>());
}
template<typename T>
void m_visit_pointer(const T &t, const mpl::bool_<true> &) const
{
m_visit_not_function_pointer(t, mpl::bool_<!is_function<typename remove_pointer<T>::type>::value>());
}
template<typename T>
void m_visit_pointer(const T &t, const mpl::bool_<false> &) const
{
m_visit_pointer(boost::addressof(t), mpl::bool_<true>());
}
template<typename T>
void m_visit_not_function_pointer(const T *t, const mpl::bool_<true> &) const
{
m_visit_signal(t, mpl::bool_<is_signal<T>::value>());
}
template<typename T>
void m_visit_not_function_pointer(const T &, const mpl::bool_<false> &) const
{}
template<typename T>
void m_visit_signal(const T *signal, const mpl::bool_<true> &) const
{
if(signal)
slot_->track_signal(*signal);
}
template<typename T>
void m_visit_signal(const T &t, const mpl::bool_<false> &) const
{
add_if_trackable(t);
}
void add_if_trackable(const trackable *trackable) const
{
if(trackable)
slot_->_tracked_objects.push_back(trackable->get_weak_ptr());
}
void add_if_trackable(const void *) const {}
mutable slot_base * slot_;
};
} // end namespace detail
} // end namespace signals2
} // end namespace boost
#endif // BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP
@@ -0,0 +1,42 @@
/*
Provides a basic subset of boost::unique_lock functionality. Provided only because
including boost/thread/locks.hpp requires linking to thread library
*/
// Copyright Frank Mori Hess 2008.
// 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)
// See http://www.boost.org/libs/signals2 for library home page.
#ifndef BOOST_SIGNALS2_UNIQUE_LOCK_HPP
#define BOOST_SIGNALS2_UNIQUE_LOCK_HPP
#include <boost/noncopyable.hpp>
namespace boost
{
namespace signals2
{
namespace detail
{
template<typename Mutex>
class unique_lock: public noncopyable
{
public:
unique_lock(Mutex &m): _mutex(m)
{
_mutex.lock();
}
~unique_lock()
{
_mutex.unlock();
}
private:
Mutex &_mutex;
};
} // namespace detail
} // namespace signals2
} // namespace boost
#endif // BOOST_SIGNALS2_UNIQUE_LOCK_HPP
@@ -0,0 +1,54 @@
// Copyright Frank Mori Hess 2009
//
// Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS2_DETAIL_VARIADIC_ARG_TYPE_HPP
#define BOOST_SIGNALS2_DETAIL_VARIADIC_ARG_TYPE_HPP
#include <functional>
namespace boost
{
namespace signals2
{
namespace detail
{
template<unsigned, typename ... Args> class variadic_arg_type;
template<typename T, typename ... Args> class variadic_arg_type<0, T, Args...>
{
public:
typedef T type;
};
template<unsigned n, typename T, typename ... Args> class variadic_arg_type<n, T, Args...>
{
public:
typedef typename variadic_arg_type<n - 1, Args...>::type type;
};
template <typename ... Args>
struct std_functional_base
{};
template <typename T1>
struct std_functional_base<T1>
{
typedef T1 argument_type;
};
template <typename T1, typename T2>
struct std_functional_base<T1, T2>
{
typedef T1 first_argument_type;
typedef T2 second_argument_type;
};
} // namespace detail
} // namespace signals2
} // namespace boost
#endif // BOOST_SIGNALS2_DETAIL_VARIADIC_ARG_TYPE_HPP
@@ -0,0 +1,148 @@
/*
Helper class used by variadic implementation of variadic boost::signals2::signal.
Author: Frank Mori Hess <fmhess@users.sourceforge.net>
Begin: 2009-05-27
*/
// Copyright Frank Mori Hess 2009
// Use, modification and
// distribution is subject to 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)
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS2_DETAIL_VARIADIC_SLOT_INVOKER_HPP
#define BOOST_SIGNALS2_DETAIL_VARIADIC_SLOT_INVOKER_HPP
#include <boost/mpl/size_t.hpp>
#include <boost/signals2/detail/variadic_arg_type.hpp>
// if compiler has std::tuple use it instead of boost::tuple
// because boost::tuple does not have variadic template support at present.
#ifdef BOOST_NO_CXX11_HDR_TUPLE
#include <boost/tuple/tuple.hpp>
#define BOOST_SIGNALS2_TUPLE boost::tuple
#define BOOST_SIGNALS2_GET boost::get
#else
#include <tuple>
#define BOOST_SIGNALS2_TUPLE std::tuple
#define BOOST_SIGNALS2_GET std::get
#endif
// vc12 seems to erroneously report formal parameters as unreferenced (warning C4100)
// if parameters of variadic template functions are only referenced by calling
// other varadic template functions. silence these warnings:
#if defined(BOOST_MSVC)
#pragma warning(push)
#if BOOST_MSVC >= 1800
#pragma warning(disable:4100)
#endif
#endif
namespace boost
{
namespace signals2
{
namespace detail
{
template<unsigned ... values> class unsigned_meta_array {};
template<typename UnsignedMetaArray, unsigned n> class unsigned_meta_array_appender;
template<unsigned n, unsigned ... Args>
class unsigned_meta_array_appender<unsigned_meta_array<Args...>, n>
{
public:
typedef unsigned_meta_array<Args..., n> type;
};
template<unsigned n> class make_unsigned_meta_array;
template<> class make_unsigned_meta_array<0>
{
public:
typedef unsigned_meta_array<> type;
};
template<> class make_unsigned_meta_array<1>
{
public:
typedef unsigned_meta_array<0> type;
};
template<unsigned n> class make_unsigned_meta_array
{
public:
typedef typename unsigned_meta_array_appender<typename make_unsigned_meta_array<n-1>::type, n - 1>::type type;
};
template<typename R>
class call_with_tuple_args
{
public:
typedef R result_type;
template<typename Func, typename ... Args, std::size_t N>
R operator()(Func &func, const BOOST_SIGNALS2_TUPLE<Args...> & args, mpl::size_t<N>) const
{
typedef typename make_unsigned_meta_array<N>::type indices_type;
return m_invoke<Func>(func, indices_type(), args);
}
private:
template<typename Func, unsigned ... indices, typename ... Args>
R m_invoke(Func &func, unsigned_meta_array<indices...>, const BOOST_SIGNALS2_TUPLE<Args...> & args,
typename boost::disable_if<boost::is_void<typename Func::result_type> >::type * = 0
) const
{
return func(BOOST_SIGNALS2_GET<indices>(args)...);
}
template<typename Func, unsigned ... indices, typename ... Args>
R m_invoke(Func &func, unsigned_meta_array<indices...>, const BOOST_SIGNALS2_TUPLE<Args...> & args,
typename boost::enable_if<boost::is_void<typename Func::result_type> >::type * = 0
) const
{
func(BOOST_SIGNALS2_GET<indices>(args)...);
return R();
}
// This overload is redundant, as it is the same as the previous variadic method when
// it has zero "indices" or "Args" variadic template parameters. This overload
// only exists to quiet some unused parameter warnings
// on certain compilers (some versions of gcc and msvc)
template<typename Func>
R m_invoke(Func &func, unsigned_meta_array<>, const BOOST_SIGNALS2_TUPLE<> &,
typename boost::enable_if<boost::is_void<typename Func::result_type> >::type * = 0
) const
{
func();
return R();
}
};
template<typename R, typename ... Args>
class variadic_slot_invoker
{
public:
typedef R result_type;
variadic_slot_invoker(Args & ... args): _args(args...)
{}
template<typename ConnectionBodyType>
result_type operator ()(const ConnectionBodyType &connectionBody) const
{
return call_with_tuple_args<result_type>()(connectionBody->slot().slot_function(),
_args, mpl::size_t<sizeof...(Args)>());
}
private:
BOOST_SIGNALS2_TUPLE<Args& ...> _args;
};
} // namespace detail
} // namespace signals2
} // namespace boost
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif // BOOST_SIGNALS2_DETAIL_VARIADIC_SLOT_INVOKER_HPP