summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/signals2/test
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/boost/libs/signals2/test/Jamfile.v251
-rw-r--r--src/boost/libs/signals2/test/connection_test.cpp130
-rw-r--r--src/boost/libs/signals2/test/dead_slot_test.cpp47
-rw-r--r--src/boost/libs/signals2/test/deadlock_regression_test.cpp109
-rw-r--r--src/boost/libs/signals2/test/deconstruct_test.cpp174
-rw-r--r--src/boost/libs/signals2/test/deletion_test.cpp297
-rw-r--r--src/boost/libs/signals2/test/invocation_benchmark.cpp60
-rw-r--r--src/boost/libs/signals2/test/mutex_test.cpp292
-rw-r--r--src/boost/libs/signals2/test/ordering_test.cpp128
-rw-r--r--src/boost/libs/signals2/test/regression_test.cpp109
-rw-r--r--src/boost/libs/signals2/test/shared_connection_block_test.cpp112
-rw-r--r--src/boost/libs/signals2/test/signal_n_test.cpp352
-rw-r--r--src/boost/libs/signals2/test/signal_test.cpp348
-rw-r--r--src/boost/libs/signals2/test/signal_type_test.cpp43
-rw-r--r--src/boost/libs/signals2/test/slot_compile_test.cpp27
-rw-r--r--src/boost/libs/signals2/test/threading_models_test.cpp86
-rw-r--r--src/boost/libs/signals2/test/track_test.cpp167
-rw-r--r--src/boost/libs/signals2/test/trackable_test.cpp112
18 files changed, 2644 insertions, 0 deletions
diff --git a/src/boost/libs/signals2/test/Jamfile.v2 b/src/boost/libs/signals2/test/Jamfile.v2
new file mode 100644
index 000000000..aacb3a4ce
--- /dev/null
+++ b/src/boost/libs/signals2/test/Jamfile.v2
@@ -0,0 +1,51 @@
+# Boost.Signals2 Library
+
+# Copyright Douglas Gregor 2001-2003.
+# 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
+
+# bring in rules for testing
+import testing ;
+
+project
+ : source-location .
+ : requirements
+ <hardcode-dll-paths>true
+# <library>/boost/test//boost_unit_test_framework
+# <link>static
+ ;
+
+rule thread-run ( sources )
+{
+ return
+ [ run $(sources) : : : <library>/boost/thread//boost_thread/
+ <threading>multi ]
+ ;
+}
+
+{
+ test-suite signals2
+ :
+ [ run connection_test.cpp ]
+ [ run dead_slot_test.cpp ]
+ [ run deadlock_regression_test.cpp ]
+ [ run deconstruct_test.cpp ]
+ [ run deletion_test.cpp ]
+ [ thread-run mutex_test.cpp ]
+ [ run ordering_test.cpp ]
+ [ run regression_test.cpp ]
+ [ run shared_connection_block_test.cpp ]
+ [ run signal_n_test.cpp ]
+ [ run signal_test.cpp ]
+ [ run signal_type_test.cpp ]
+ [ run slot_compile_test.cpp ]
+ [ thread-run threading_models_test.cpp ]
+ [ run trackable_test.cpp ]
+ [ run track_test.cpp ]
+ ;
+}
diff --git a/src/boost/libs/signals2/test/connection_test.cpp b/src/boost/libs/signals2/test/connection_test.cpp
new file mode 100644
index 000000000..bfe0894bc
--- /dev/null
+++ b/src/boost/libs/signals2/test/connection_test.cpp
@@ -0,0 +1,130 @@
+// Signals2 library
+// tests for connection class
+
+// Copyright Frank Mori Hess 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
+#include <boost/signals2.hpp>
+#define BOOST_TEST_MODULE connection_test
+#include <boost/test/included/unit_test.hpp>
+
+namespace bs2 = boost::signals2;
+
+typedef bs2::signal<void ()> sig_type;
+
+void myslot()
+{}
+
+void swap_test()
+{
+ sig_type sig;
+
+ {
+ bs2::connection conn1 = sig.connect(&myslot);
+ BOOST_CHECK(conn1.connected());
+ bs2::connection conn2;
+ BOOST_CHECK(conn2.connected() == false);
+
+ conn1.swap(conn2);
+ BOOST_CHECK(conn2.connected());
+ BOOST_CHECK(conn1.connected() == false);
+
+ swap(conn1, conn2);
+ BOOST_CHECK(conn1.connected());
+ BOOST_CHECK(conn2.connected() == false);
+ }
+
+ {
+ bs2::scoped_connection conn1;
+ conn1 = sig.connect(&myslot);
+ BOOST_CHECK(conn1.connected());
+ bs2::scoped_connection conn2;
+ BOOST_CHECK(conn2.connected() == false);
+
+ conn1.swap(conn2);
+ BOOST_CHECK(conn2.connected());
+ BOOST_CHECK(conn1.connected() == false);
+
+ swap(conn1, conn2);
+ BOOST_CHECK(conn1.connected());
+ BOOST_CHECK(conn2.connected() == false);
+ }
+}
+
+void release_test()
+{
+ sig_type sig;
+ bs2::connection conn;
+ {
+ bs2::scoped_connection scoped(sig.connect(&myslot));
+ BOOST_CHECK(scoped.connected());
+ conn = scoped.release();
+ }
+ BOOST_CHECK(conn.connected());
+
+ bs2::connection conn2;
+ {
+ bs2::scoped_connection scoped(conn);
+ BOOST_CHECK(scoped.connected());
+ conn = scoped.release();
+ BOOST_CHECK(conn.connected());
+ BOOST_CHECK(scoped.connected() == false);
+ conn.disconnect();
+
+ // earlier release shouldn't affect new connection
+ conn2 = sig.connect(&myslot);
+ scoped = conn2;
+ }
+ BOOST_CHECK(conn2.connected() == false);
+}
+
+void move_test()
+{
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ sig_type sig;
+ bs2::connection conn;
+ // test move assignment from scoped_connection to connection
+ {
+ bs2::scoped_connection scoped(sig.connect(&myslot));
+ BOOST_CHECK(scoped.connected());
+ conn = std::move(scoped);
+ BOOST_CHECK(scoped.connected() == false);
+ }
+ BOOST_CHECK(conn.connected());
+
+ // test move construction from scoped to scoped
+ {
+ bs2::scoped_connection scoped2(conn);
+ BOOST_CHECK(scoped2.connected());
+ bs2::scoped_connection scoped3(std::move(scoped2));
+ BOOST_CHECK(scoped2.connected() == false);
+ BOOST_CHECK(scoped3.connected() == true);
+ BOOST_CHECK(conn.connected() == true);
+ }
+ BOOST_CHECK(conn.connected() == false);
+
+ // test move assignment from scoped to scoped
+ conn = sig.connect(&myslot);
+ {
+ bs2::scoped_connection scoped3;
+ bs2::scoped_connection scoped2(conn);
+ BOOST_CHECK(scoped2.connected());
+ scoped3 = std::move(scoped2);
+ BOOST_CHECK(scoped2.connected() == false);
+ BOOST_CHECK(scoped3.connected() == true);
+ BOOST_CHECK(conn.connected() == true);
+ }
+ BOOST_CHECK(conn.connected() == false);
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ release_test();
+ swap_test();
+ move_test();
+}
diff --git a/src/boost/libs/signals2/test/dead_slot_test.cpp b/src/boost/libs/signals2/test/dead_slot_test.cpp
new file mode 100644
index 000000000..b1ec1d5a0
--- /dev/null
+++ b/src/boost/libs/signals2/test/dead_slot_test.cpp
@@ -0,0 +1,47 @@
+// Boost.Signals library
+
+// Copyright (C) Douglas Gregor 2001-2006. 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
+
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/signals2.hpp>
+#define BOOST_TEST_MODULE dead_slot_test
+#include <boost/test/included/unit_test.hpp>
+
+using namespace boost::placeholders;
+
+typedef boost::signals2::signal<int (int)> sig_type;
+
+class with_constant {
+public:
+ with_constant(int c) : constant(c) {}
+
+ int add(int i) { return i + constant; }
+
+private:
+ int constant;
+};
+
+void do_delayed_connect(boost::shared_ptr<with_constant> &wc,
+ sig_type& sig,
+ sig_type::slot_type slot)
+{
+ // Should invalidate the slot, so that we cannot connect to it
+ wc.reset();
+
+ boost::signals2::connection c = sig.connect(slot);
+ BOOST_CHECK(!c.connected());
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ sig_type s1;
+ boost::shared_ptr<with_constant> wc1(new with_constant(7));
+
+ do_delayed_connect(wc1, s1, sig_type::slot_type(&with_constant::add, wc1.get(), _1).track(wc1));
+}
diff --git a/src/boost/libs/signals2/test/deadlock_regression_test.cpp b/src/boost/libs/signals2/test/deadlock_regression_test.cpp
new file mode 100644
index 000000000..ac9d89190
--- /dev/null
+++ b/src/boost/libs/signals2/test/deadlock_regression_test.cpp
@@ -0,0 +1,109 @@
+// Signals2 library
+//
+// Regression test based on bug report from Arian Alin Radu.
+// The problem was that tracked objects could be released
+// while holding the signal mutex during signal invocation.
+// This could result in a recursive
+// lock attempt if the tracked object manipulates the signal
+// in its destructor.
+
+// Copyright Frank Mori Hess 2019
+// 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
+
+#define BOOST_TEST_MODULE signals2 deadlock regression test
+#include <boost/test/included/unit_test.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/signals2/signal.hpp>
+#include <boost/signals2/signal_type.hpp>
+
+namespace bs2 = boost::signals2;
+
+
+// dummy mutex that detects attempts to recursively lock
+class test_mutex
+{
+public:
+ test_mutex(): m_locked(false) {}
+ void lock()
+ {
+ BOOST_CHECK(m_locked == false);
+ m_locked = true;
+ }
+ bool try_lock()
+ {
+ if(m_locked) return false;
+ lock();
+ return true;
+ }
+ void unlock()
+ {
+ m_locked = false;
+ }
+private:
+ bool m_locked;
+};
+
+using namespace bs2::keywords;
+typedef bs2::signal_type<void(), mutex_type<test_mutex> >::type Signal;
+
+class SelfReference: private boost::noncopyable
+{
+public:
+ boost::shared_ptr<SelfReference> m_self;
+ boost::shared_ptr<Signal> m_signal;
+
+ boost::signals2::connection m_conReleaseSelf;
+ boost::signals2::connection m_conDoNothing;
+
+ SelfReference()
+ {
+ m_signal = boost::make_shared<Signal>();
+ }
+
+ ~SelfReference()
+ {
+ // the first slot (ReleaseSelf) has been called; now the trackable object (this)
+ // was released, while the second slot is locked
+ BOOST_CHECK(!m_conReleaseSelf.connected());
+ // the second slot is locked, and we enter a recursive (pthread: dead) lock
+ BOOST_CHECK(m_conDoNothing.connected());
+ m_conReleaseSelf.disconnect();
+ m_conDoNothing.disconnect();
+ // enter recursive (pthread: dead) lock again:
+ BOOST_CHECK(m_signal->empty());
+ }
+
+ void ReleaseSelf()
+ {
+ m_self.reset();
+ }
+
+ static void DoNothing()
+ {
+ }
+
+ static void Run()
+ {
+ boost::shared_ptr<Signal> signal;
+ {
+ boost::shared_ptr<SelfReference> obj = boost::make_shared<SelfReference>();
+ obj->m_self = obj;
+ signal = obj->m_signal;
+
+ obj->m_conReleaseSelf = signal->connect(Signal::slot_type(&SelfReference::ReleaseSelf, obj.get()).track(obj));
+ obj->m_conDoNothing = signal->connect(Signal::slot_type(&SelfReference::DoNothing));
+ }
+ (*signal)();
+ }
+};
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ SelfReference::Run();
+}
diff --git a/src/boost/libs/signals2/test/deconstruct_test.cpp b/src/boost/libs/signals2/test/deconstruct_test.cpp
new file mode 100644
index 000000000..96d9949e4
--- /dev/null
+++ b/src/boost/libs/signals2/test/deconstruct_test.cpp
@@ -0,0 +1,174 @@
+// Tests for boost::signals2::deconstruct_ptr and friends
+
+// Copyright Frank Mori Hess 2007-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.
+
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/signals2/deconstruct.hpp>
+#include <boost/signals2/deconstruct_ptr.hpp>
+#define BOOST_TEST_MODULE deconstruct_test
+#include <boost/test/included/unit_test.hpp>
+
+class X: public boost::signals2::postconstructible {
+public:
+ X(): _postconstructed(false)
+ {}
+ ~X()
+ {
+ BOOST_CHECK(_postconstructed);
+ }
+protected:
+ virtual void postconstruct()
+ {
+ BOOST_CHECK(!_postconstructed);
+ _postconstructed = true;
+ }
+ bool _postconstructed;
+};
+
+class Y: public boost::signals2::predestructible {
+public:
+ Y(): _predestructed(false)
+ {}
+ ~Y()
+ {
+ BOOST_CHECK(_predestructed);
+ }
+protected:
+ virtual void predestruct()
+ {
+ _predestructed = true;
+ }
+ bool _predestructed;
+};
+
+class Z: public X, public Y
+{};
+
+class by_deconstruct_only: public boost::signals2::postconstructible {
+public:
+ ~by_deconstruct_only()
+ {
+ BOOST_CHECK(_postconstructed);
+ }
+ int value;
+protected:
+ virtual void postconstruct()
+ {
+ BOOST_CHECK(!_postconstructed);
+ _postconstructed = true;
+ }
+ bool _postconstructed;
+private:
+ friend class boost::signals2::deconstruct_access;
+ by_deconstruct_only(int value_in):
+ value(value_in), _postconstructed(false)
+ {}
+};
+
+namespace mytest
+{
+ class A
+ {
+ public:
+ template<typename T> friend
+ void adl_postconstruct(const boost::shared_ptr<T> &sp, A *p)
+ {
+ BOOST_CHECK(!p->_postconstructed);
+ p->_postconstructed = true;
+ }
+ template<typename T> friend
+ void adl_postconstruct(const boost::shared_ptr<T> &sp, A *p, int val)
+ {
+ p->value = val;
+ BOOST_CHECK(!p->_postconstructed);
+ p->_postconstructed = true;
+ }
+ friend void adl_predestruct(A *p)
+ {
+ p->_predestructed = true;
+ }
+ ~A()
+ {
+ BOOST_CHECK(_postconstructed);
+ BOOST_CHECK(_predestructed);
+ }
+ int value;
+ private:
+ friend class boost::signals2::deconstruct_access;
+ A(int value_in = 0):
+ value(value_in),
+ _postconstructed(false),
+ _predestructed(false)
+ {}
+ bool _postconstructed;
+ bool _predestructed;
+ };
+}
+
+void deconstruct_ptr_test()
+{
+ {
+ boost::shared_ptr<X> x = boost::signals2::deconstruct_ptr(new X);
+ }
+ {
+ boost::shared_ptr<Y> x = boost::signals2::deconstruct_ptr(new Y);
+ }
+ {
+ boost::shared_ptr<Z> z = boost::signals2::deconstruct_ptr(new Z);
+ }
+}
+
+class deconstructed_esft : public boost::enable_shared_from_this<deconstructed_esft>
+{
+public:
+ deconstructed_esft() : x(0) {}
+
+private:
+ friend void adl_postconstruct(boost::shared_ptr<void>, deconstructed_esft *) {}
+ int x;
+};
+
+void deconstruct_test()
+{
+ {
+ boost::shared_ptr<X> x = boost::signals2::deconstruct<X>();
+ }
+ {
+ boost::shared_ptr<Y> x = boost::signals2::deconstruct<Y>();
+ }
+ {
+ boost::shared_ptr<Z> z = boost::signals2::deconstruct<Z>();
+ }
+ {
+ boost::shared_ptr<by_deconstruct_only> a = boost::signals2::deconstruct<by_deconstruct_only>(1);
+ BOOST_CHECK(a->value == 1);
+ }
+ {
+ boost::shared_ptr<mytest::A> a = boost::signals2::deconstruct<mytest::A>(1);
+ BOOST_CHECK(a->value == 1);
+ }
+ {// deconstruct const type
+ boost::shared_ptr<const mytest::A> a = boost::signals2::deconstruct<const mytest::A>(3);
+ BOOST_CHECK(a->value == 3);
+ }
+ {// passing arguments to postconstructor
+ boost::shared_ptr<mytest::A> a = boost::signals2::deconstruct<mytest::A>().postconstruct(2);
+ BOOST_CHECK(a->value == 2);
+ }
+ {// enable_shared_from_this with deconstruct
+ boost::shared_ptr<deconstructed_esft> a = boost::signals2::deconstruct<deconstructed_esft>();
+ BOOST_CHECK(!(a->shared_from_this() < a || a < a->shared_from_this()));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ deconstruct_ptr_test();
+ deconstruct_test();
+}
diff --git a/src/boost/libs/signals2/test/deletion_test.cpp b/src/boost/libs/signals2/test/deletion_test.cpp
new file mode 100644
index 000000000..577c8512a
--- /dev/null
+++ b/src/boost/libs/signals2/test/deletion_test.cpp
@@ -0,0 +1,297 @@
+// Boost.Signals2 library
+
+// Copyright Douglas Gregor 2001-2003.
+// 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
+
+#include <boost/signals2.hpp>
+#define BOOST_TEST_MODULE deletion_test
+#include <boost/test/included/unit_test.hpp>
+#include <iostream>
+#include <string>
+
+static boost::signals2::connection connections[5];
+
+static std::string test_output;
+
+struct remove_connection {
+ explicit remove_connection(int v = 0, int i = -1) : value(v), idx(i) {}
+
+ void operator()() const {
+ if (idx >= 0)
+ connections[idx].disconnect();
+
+ //return value;
+ std::cout << value << " ";
+
+ test_output += static_cast<char>(value + '0');
+ }
+
+ int value;
+ int idx;
+};
+
+bool operator==(const remove_connection& x, const remove_connection& y)
+{ return x.value == y.value && x.idx == y.idx; }
+
+static void
+test_remove_self()
+{
+ boost::signals2::signal<void ()> s0;
+
+ connections[0] = s0.connect(remove_connection(0));
+ connections[1] = s0.connect(remove_connection(1));
+ connections[2] = s0.connect(remove_connection(2, 2));
+ connections[3] = s0.connect(remove_connection(3));
+
+ std::cout << "Deleting 2" << std::endl;
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "0123");
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "013");
+
+ s0.disconnect_all_slots();
+ BOOST_CHECK(s0.empty());
+
+ connections[0] = s0.connect(remove_connection(0));
+ connections[1] = s0.connect(remove_connection(1));
+ connections[2] = s0.connect(remove_connection(2));
+ connections[3] = s0.connect(remove_connection(3, 3));
+
+ std::cout << "Deleting 3" << std::endl;
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "0123");
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "012");
+
+ s0.disconnect_all_slots();
+ BOOST_CHECK(s0.num_slots() == 0);
+
+ connections[0] = s0.connect(remove_connection(0, 0));
+ connections[1] = s0.connect(remove_connection(1));
+ connections[2] = s0.connect(remove_connection(2));
+ connections[3] = s0.connect(remove_connection(3));
+
+ std::cout << "Deleting 0" << std::endl;
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "0123");
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "123");
+
+ s0.disconnect_all_slots();
+ BOOST_CHECK(s0.empty());
+
+ connections[0] = s0.connect(remove_connection(0, 0));
+ connections[1] = s0.connect(remove_connection(1, 1));
+ connections[2] = s0.connect(remove_connection(2, 2));
+ connections[3] = s0.connect(remove_connection(3, 3));
+
+ std::cout << "Mass suicide" << std::endl;
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "0123");
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "");
+}
+
+static void
+test_remove_prior()
+{
+ boost::signals2::signal<void ()> s0;
+
+ connections[0] = s0.connect(remove_connection(0));
+ connections[1] = s0.connect(remove_connection(1, 0));
+ connections[2] = s0.connect(remove_connection(2));
+ connections[3] = s0.connect(remove_connection(3));
+
+ std::cout << "1 removes 0" << std::endl;
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "0123");
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "123");
+
+ s0.disconnect_all_slots();
+ BOOST_CHECK(s0.empty());
+
+ connections[0] = s0.connect(remove_connection(0));
+ connections[1] = s0.connect(remove_connection(1));
+ connections[2] = s0.connect(remove_connection(2));
+ connections[3] = s0.connect(remove_connection(3, 2));
+
+ std::cout << "3 removes 2" << std::endl;
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "0123");
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "013");
+}
+
+static void
+test_remove_after()
+{
+ boost::signals2::signal<void ()> s0;
+
+ connections[0] = s0.connect(remove_connection(0, 1));
+ connections[1] = s0.connect(remove_connection(1));
+ connections[2] = s0.connect(remove_connection(2));
+ connections[3] = s0.connect(remove_connection(3));
+
+ std::cout << "0 removes 1" << std::endl;
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "023");
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "023");
+
+ s0.disconnect_all_slots();
+ BOOST_CHECK(s0.empty());
+
+ connections[0] = s0.connect(remove_connection(0));
+ connections[1] = s0.connect(remove_connection(1, 3));
+ connections[2] = s0.connect(remove_connection(2));
+ connections[3] = s0.connect(remove_connection(3));
+
+ std::cout << "1 removes 3" << std::endl;
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "012");
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "012");
+}
+
+static void
+test_bloodbath()
+{
+ boost::signals2::signal<void ()> s0;
+
+ connections[0] = s0.connect(remove_connection(0, 1));
+ connections[1] = s0.connect(remove_connection(1, 1));
+ connections[2] = s0.connect(remove_connection(2, 0));
+ connections[3] = s0.connect(remove_connection(3, 2));
+
+ std::cout << "0 removes 1, 2 removes 0, 3 removes 2" << std::endl;
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "023");
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "3");
+}
+
+static void
+test_disconnect_equal()
+{
+ boost::signals2::signal<void ()> s0;
+
+ connections[0] = s0.connect(remove_connection(0));
+ connections[1] = s0.connect(remove_connection(1));
+ connections[2] = s0.connect(remove_connection(2));
+ connections[3] = s0.connect(remove_connection(3));
+
+ std::cout << "Deleting 2" << std::endl;
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "0123");
+
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+ connections[2].disconnect();
+#else
+ s0.disconnect(remove_connection(2));
+#endif
+
+ test_output = "";
+ s0(); std::cout << std::endl;
+ BOOST_CHECK(test_output == "013");
+}
+
+struct signal_deletion_tester
+{
+public:
+ signal_deletion_tester() {
+ b_has_run = false;
+ sig = new boost::signals2::signal<void(void)>();
+ connection0 = sig->connect(0, boost::bind(&signal_deletion_tester::a, this));
+ connection1 = sig->connect(1, boost::bind(&signal_deletion_tester::b, this));
+ }
+
+ ~signal_deletion_tester()
+ {
+ if(sig != 0)
+ delete sig;
+ }
+
+ void a()
+ {
+ if(sig != 0)
+ delete sig;
+ sig = 0;
+ }
+
+ void b()
+ {
+ b_has_run = true;
+ }
+
+ boost::signals2::signal<void(void)> *sig;
+ bool b_has_run;
+ boost::signals2::connection connection0;
+ boost::signals2::connection connection1;
+};
+
+// If a signal is deleted mid-invocation, the invocation in progress
+// should complete normally. Once all invocations complete, all
+// slots which were connected to the deleted signal should be in the
+// disconnected state.
+static void test_signal_deletion()
+{
+ signal_deletion_tester tester;
+ (*tester.sig)();
+ BOOST_CHECK(tester.b_has_run);
+ BOOST_CHECK(tester.connection0.connected() == false);
+ BOOST_CHECK(tester.connection1.connected() == false);
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ test_remove_self();
+ test_remove_prior();
+ test_remove_after();
+ test_bloodbath();
+ test_disconnect_equal();
+ test_signal_deletion();
+}
diff --git a/src/boost/libs/signals2/test/invocation_benchmark.cpp b/src/boost/libs/signals2/test/invocation_benchmark.cpp
new file mode 100644
index 000000000..6a464fc52
--- /dev/null
+++ b/src/boost/libs/signals2/test/invocation_benchmark.cpp
@@ -0,0 +1,60 @@
+/* multi-threaded signal invocation benchmark */
+
+// Copyright Frank Mori Hess 2007-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)
+
+#include <cstdlib>
+#include <iostream>
+#include <boost/bind/bind.hpp>
+#include <boost/signals2.hpp>
+#include <boost/thread/thread.hpp>
+
+using namespace boost::placeholders;
+
+typedef boost::signals2::signal<void ()> signal_type;
+
+void myslot()
+{
+/* std::cout << __FUNCTION__ << std::endl;
+ sleep(1);*/
+}
+
+void thread_initial(signal_type *signal, unsigned num_invocations)
+{
+ unsigned i;
+ for(i = 0; i < num_invocations; ++i)
+ {
+ (*signal)();
+ }
+}
+
+int main(int argc, const char **argv)
+{
+ if(argc < 3)
+ {
+ std::cerr << "usage: " << argv[0] << " <num threads> <num connections>" << std::endl;
+ return -1;
+ }
+ static const unsigned num_threads = std::strtol(argv[1], 0, 0);
+ static const unsigned num_connections = std::strtol(argv[2], 0, 0);
+ boost::thread_group threads;
+ signal_type sig;
+
+ std::cout << "Connecting " << num_connections << " connections to signal.\n";
+ unsigned i;
+ for(i = 0; i < num_connections; ++i)
+ {
+ sig.connect(&myslot);
+ }
+ const unsigned num_slot_invocations = 1000000;
+ const unsigned signal_invocations_per_thread = num_slot_invocations / (num_threads * num_connections);
+ std::cout << "Launching " << num_threads << " thread(s) to invoke signal " << signal_invocations_per_thread << " times per thread.\n";
+ for(i = 0; i < num_threads; ++i)
+ {
+ threads.create_thread(boost::bind(&thread_initial, &sig, signal_invocations_per_thread));
+ }
+ threads.join_all();
+ return 0;
+}
diff --git a/src/boost/libs/signals2/test/mutex_test.cpp b/src/boost/libs/signals2/test/mutex_test.cpp
new file mode 100644
index 000000000..8da2972a5
--- /dev/null
+++ b/src/boost/libs/signals2/test/mutex_test.cpp
@@ -0,0 +1,292 @@
+// Copyright (C) 2001-2003
+// William E. Kempf
+//
+// 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)
+
+// This is a simplified/modified version of libs/thread/test/test_mutex.cpp
+// added to test boost::signals2::mutex.
+// For more information, see http://www.boost.org
+
+// Note boost/test/minimal.hpp can cause windows.h to get included, which
+// can screw up our checks of _WIN32_WINNT if it is included
+// after boost/signals2/mutex.hpp. Frank Hess 2009-03-07.
+// We now use boost/test/included/unit_test.hpp, not sure if above still
+// applies, but might as well leave the include where it is.
+#define BOOST_TEST_MODULE mutex_test
+#include <boost/test/included/unit_test.hpp>
+
+#include <boost/bind/bind.hpp>
+#include <boost/signals2/dummy_mutex.hpp>
+#include <boost/signals2/mutex.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/thread/condition.hpp>
+
+using namespace boost::placeholders;
+
+class execution_monitor
+{
+public:
+ execution_monitor(int secs)
+ : done(false), m_secs(secs) { }
+ void start()
+ {
+ boost::mutex::scoped_lock lock(mutex);
+ done = false;
+ }
+ void finish()
+ {
+ boost::mutex::scoped_lock lock(mutex);
+ done = true;
+ cond.notify_one();
+ }
+ bool wait()
+ {
+ boost::posix_time::time_duration timeout = boost::posix_time::seconds(m_secs);
+ boost::mutex::scoped_lock lock(mutex);
+ while (!done) {
+ if (!cond.timed_wait(lock, timeout))
+ break;
+ }
+ return done;
+ }
+
+private:
+ boost::mutex mutex;
+ boost::condition cond;
+ bool done;
+ int m_secs;
+};
+
+template <typename F>
+class indirect_adapter
+{
+public:
+ indirect_adapter(F func, execution_monitor& monitor)
+ : m_func(func), m_monitor(monitor) { }
+ void operator()() const
+ {
+ try
+ {
+ boost::thread thrd(m_func);
+ thrd.join();
+ }
+ catch (...)
+ {
+ m_monitor.finish();
+ throw;
+ }
+ m_monitor.finish();
+ }
+
+private:
+ F m_func;
+ execution_monitor& m_monitor;
+ void operator=(indirect_adapter&);
+};
+
+template <typename F>
+void timed_test(F func, int secs)
+{
+ execution_monitor monitor(secs);
+ indirect_adapter<F> ifunc(func, monitor);
+ monitor.start();
+ boost::thread thrd(ifunc);
+ BOOST_REQUIRE(monitor.wait()); // Timed test didn't complete in time, possible deadlock
+}
+
+template <typename M>
+struct test_lock
+{
+ typedef M mutex_type;
+ typedef typename boost::unique_lock<M> lock_type;
+
+ void operator()()
+ {
+ mutex_type mutex;
+ boost::condition condition;
+
+ // Test the lock's constructors.
+ {
+ lock_type lock(mutex, boost::defer_lock);
+ BOOST_CHECK(!lock);
+ }
+ lock_type lock(mutex);
+ BOOST_CHECK(lock ? true : false);
+
+ // Construct a fast time out.
+ boost::posix_time::time_duration timeout = boost::posix_time::milliseconds(100);
+
+ // Test the lock and the mutex with condition variables.
+ // No one is going to notify this condition variable. We expect to
+ // time out.
+ BOOST_CHECK(!condition.timed_wait(lock, timeout));
+ BOOST_CHECK(lock ? true : false);
+
+ // Test the lock and unlock methods.
+ lock.unlock();
+ BOOST_CHECK(!lock);
+ lock.lock();
+ BOOST_CHECK(lock ? true : false);
+ }
+};
+
+template <typename M>
+struct test_trylock
+{
+ typedef M mutex_type;
+ typedef typename boost::unique_lock<M> lock_type;
+
+ void operator()()
+ {
+ mutex_type mutex;
+ boost::condition condition;
+
+ // Test the lock's constructors.
+ {
+ lock_type lock(mutex, boost::try_to_lock);
+ BOOST_CHECK(lock ? true : false);
+ }
+ {
+ lock_type lock(mutex, boost::defer_lock);
+ BOOST_CHECK(!lock);
+ }
+ lock_type lock(mutex, boost::try_to_lock);
+ BOOST_CHECK(lock ? true : false);
+
+ // Construct a fast time out.
+ boost::posix_time::time_duration timeout = boost::posix_time::milliseconds(100);
+
+ // Test the lock and the mutex with condition variables.
+ // No one is going to notify this condition variable. We expect to
+ // time out.
+ BOOST_CHECK(!condition.timed_wait(lock, timeout));
+ BOOST_CHECK(lock ? true : false);
+
+ // Test the lock, unlock and trylock methods.
+ lock.unlock();
+ BOOST_CHECK(!lock);
+ lock.lock();
+ BOOST_CHECK(lock ? true : false);
+ lock.unlock();
+ BOOST_CHECK(!lock);
+ BOOST_CHECK(lock.try_lock());
+ BOOST_CHECK(lock ? true : false);
+ }
+};
+
+template<typename Mutex>
+struct test_lock_exclusion
+{
+ typedef boost::unique_lock<Mutex> Lock;
+
+ Mutex m;
+ boost::mutex done_mutex;
+ bool done;
+ bool locked;
+ boost::condition_variable done_cond;
+
+ test_lock_exclusion():
+ done(false),locked(false)
+ {}
+
+ void locking_thread()
+ {
+ Lock lock(m);
+
+ boost::lock_guard<boost::mutex> lk(done_mutex);
+ locked=lock.owns_lock();
+ done=true;
+ done_cond.notify_one();
+ }
+
+ bool is_done() const
+ {
+ return done;
+ }
+
+ typedef test_lock_exclusion<Mutex> this_type;
+
+ void do_test(void (this_type::*test_func)())
+ {
+ Lock lock(m);
+
+ {
+ boost::lock_guard<boost::mutex> lk(done_mutex);
+ locked=false;
+ }
+
+ done=false;
+
+ boost::thread t(test_func,this);
+
+ try
+ {
+ {
+ boost::mutex::scoped_lock lk(done_mutex);
+ BOOST_CHECK(!done_cond.timed_wait(lk, boost::posix_time::seconds(1),
+ boost::bind(&this_type::is_done,this)));
+ }
+ lock.unlock();
+ {
+ boost::mutex::scoped_lock lk(done_mutex);
+ BOOST_CHECK(done_cond.timed_wait(lk, boost::posix_time::seconds(1),
+ boost::bind(&this_type::is_done,this)));
+ }
+ t.join();
+ BOOST_CHECK(locked);
+ }
+ catch(...)
+ {
+ lock.unlock();
+ t.join();
+ throw;
+ }
+ }
+
+
+ void operator()()
+ {
+ do_test(&this_type::locking_thread);
+ }
+};
+
+
+void do_test_mutex()
+{
+ test_lock<boost::signals2::mutex>()();
+// try_lock not supported on old versions of windows
+#if !defined(BOOST_HAS_WINTHREADS) || (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400))
+ test_trylock<boost::signals2::mutex>()();
+#endif
+ test_lock_exclusion<boost::signals2::mutex>()();
+}
+
+void test_mutex()
+{
+ timed_test(&do_test_mutex, 3);
+}
+
+void do_test_dummy_mutex()
+{
+ test_lock<boost::signals2::dummy_mutex>()();
+ test_trylock<boost::signals2::dummy_mutex>()();
+}
+
+void test_dummy_mutex()
+{
+ timed_test(&do_test_dummy_mutex, 2);
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ test_mutex();
+ test_dummy_mutex();
+}
diff --git a/src/boost/libs/signals2/test/ordering_test.cpp b/src/boost/libs/signals2/test/ordering_test.cpp
new file mode 100644
index 000000000..9636fb016
--- /dev/null
+++ b/src/boost/libs/signals2/test/ordering_test.cpp
@@ -0,0 +1,128 @@
+// Boost.Signals2 library
+
+// Copyright Douglas Gregor 2002-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
+
+#include <boost/signals2.hpp>
+#define BOOST_TEST_MODULE ordering_test
+#include <boost/test/included/unit_test.hpp>
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <cstdlib>
+#include <ctime>
+#include <functional>
+
+std::vector<int> valuesOutput;
+bool ungrouped1 = false;
+bool ungrouped2 = false;
+bool ungrouped3 = false;
+
+struct emit_int {
+ emit_int(int v) : value(v) {}
+
+ void operator()() const
+ {
+ BOOST_CHECK(value == 42 || (!ungrouped1 && !ungrouped2 && !ungrouped3));
+ valuesOutput.push_back(value);
+ std::cout << value << ' ';
+ }
+
+private:
+ int value;
+};
+
+struct write_ungrouped1 {
+ void operator()() const
+ {
+ BOOST_CHECK(!ungrouped1);
+ ungrouped1 = true;
+ std::cout << "(Ungrouped #1)" << ' ';
+ }
+};
+
+struct write_ungrouped2 {
+ void operator()() const
+ {
+ BOOST_CHECK(!ungrouped2);
+ ungrouped2 = true;
+ std::cout << "(Ungrouped #2)" << ' ';
+ }
+};
+
+struct write_ungrouped3 {
+ void operator()() const
+ {
+ BOOST_CHECK(!ungrouped3);
+ ungrouped3 = true;
+ std::cout << "(Ungrouped #3)" << ' ';
+ }
+};
+
+int return_argument(int x)
+{
+ return x;
+}
+
+void test_group_compare()
+{
+ boost::signals2::signal
+ <
+ int (),
+ boost::signals2::last_value<int>,
+ int,
+ std::greater< int >
+ > sig;
+
+ sig.connect( 1, boost::bind( &return_argument, 1) );
+ sig.connect( 2, boost::bind( &return_argument, 2) );
+
+ BOOST_CHECK(sig() == 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ using namespace std;
+ srand(time(0));
+
+ std::vector<int> sortedValues;
+
+ boost::signals2::signal<void ()> sig;
+ sig.connect(write_ungrouped1());
+ for (int i = 0; i < 100; ++i) {
+#ifdef BOOST_NO_STDC_NAMESPACE
+ int v = rand() % 100;
+#else
+ int v = std::rand() % 100;
+#endif
+ sortedValues.push_back(v);
+ sig.connect(v, emit_int(v));
+
+ if (i == 50) {
+ sig.connect(write_ungrouped2());
+ }
+ }
+ sig.connect(write_ungrouped3());
+
+ std::sort(sortedValues.begin(), sortedValues.end());
+
+ // 17 at beginning, 42 at end
+ sortedValues.insert(sortedValues.begin(), 17);
+ sig.connect(emit_int(17), boost::signals2::at_front);
+ sortedValues.push_back(42);
+ sig.connect(emit_int(42));
+
+ sig();
+ std::cout << std::endl;
+
+ BOOST_CHECK(valuesOutput == sortedValues);
+ BOOST_CHECK(ungrouped1);
+ BOOST_CHECK(ungrouped2);
+ BOOST_CHECK(ungrouped3);
+
+ test_group_compare();
+}
diff --git a/src/boost/libs/signals2/test/regression_test.cpp b/src/boost/libs/signals2/test/regression_test.cpp
new file mode 100644
index 000000000..59187353c
--- /dev/null
+++ b/src/boost/libs/signals2/test/regression_test.cpp
@@ -0,0 +1,109 @@
+// thread_safe_signals library
+// Some assorted tests to expose various bugs that existed at some point,
+// to make sure they stay fixed
+
+// Copyright Frank Mori Hess 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
+
+#include <boost/signals2.hpp>
+#define BOOST_TEST_MODULE regression_test
+#include <boost/test/included/unit_test.hpp>
+
+typedef boost::signals2::signal<void ()> sig0_type;
+
+// combiner that returns the number of slots invoked
+struct slot_counter {
+ typedef unsigned result_type;
+ template<typename InputIterator>
+ unsigned operator()(InputIterator first, InputIterator last) const
+ {
+ unsigned count = 0;
+ for (; first != last; ++first)
+ {
+ try
+ {
+ *first;
+ ++count;
+ }
+ catch(const boost::bad_weak_ptr &)
+ {}
+ }
+ return count;
+ }
+};
+
+void my_slot()
+{
+}
+
+void my_connecting_slot(sig0_type &sig)
+{
+ sig.connect(&my_slot);
+}
+
+void slot_connect_test()
+{
+ sig0_type sig;
+ sig.connect(sig0_type::slot_type(&my_connecting_slot, boost::ref(sig)).track(sig));
+ /* 2008-02-28: the following signal invocation triggered a (bogus) failed assertion of _shared_state.unique()
+ at detail/signal_template.hpp:285 */
+ sig();
+ BOOST_CHECK(sig.num_slots() == 2);
+ sig.disconnect(&my_slot);
+ BOOST_CHECK(sig.num_slots() == 1);
+ /* 2008-03-11: checked iterator barfed on next line, due to bad semantics of copy construction
+ for boost::signals2::detail::grouped_list */
+ sig();
+ BOOST_CHECK(sig.num_slots() == 2);
+}
+
+/* 2008-03-10: we weren't disconnecting old connection in scoped_connection assignment operator */
+void scoped_connection_test()
+{
+ typedef boost::signals2::signal<void (), slot_counter> signal_type;
+ signal_type sig;
+ {
+ boost::signals2::scoped_connection conn(sig.connect(&my_slot));
+ BOOST_CHECK(sig() == 1);
+ conn = sig.connect(&my_slot);
+ BOOST_CHECK(sig() == 1);
+ }
+ BOOST_CHECK(sig() == 0);
+}
+
+// testsignal that returns a reference type
+
+struct ref_returner
+{
+ static int i;
+
+ int& ref_return_slot()
+ {
+ return i;
+ }
+};
+
+int ref_returner::i = 0;
+
+void reference_return_test()
+{
+ boost::signals2::signal<int& ()> rTest;
+ ref_returner rr;
+ rTest.connect(boost::bind(&ref_returner::ref_return_slot, &rr));
+ int& r = *rTest();
+ BOOST_CHECK(ref_returner::i == 0);
+ r = 1;
+ BOOST_CHECK(ref_returner::i == 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ slot_connect_test();
+ scoped_connection_test();
+ reference_return_test();
+}
diff --git a/src/boost/libs/signals2/test/shared_connection_block_test.cpp b/src/boost/libs/signals2/test/shared_connection_block_test.cpp
new file mode 100644
index 000000000..4ad5bdf33
--- /dev/null
+++ b/src/boost/libs/signals2/test/shared_connection_block_test.cpp
@@ -0,0 +1,112 @@
+// Boost.Signals2 library
+
+// Copyright Douglas Gregor 2001-2003.
+// 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
+
+#include <boost/array.hpp>
+#include <boost/signals2/shared_connection_block.hpp>
+#include <boost/signals2/signal.hpp>
+#define BOOST_TEST_MODULE shared_connection_block_test
+#include <boost/test/included/unit_test.hpp>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+static boost::array<boost::signals2::connection, 4> connections;
+
+static std::ostringstream test_output;
+
+struct test_slot {
+ explicit test_slot(int v = 0) : value(v)
+ {}
+
+ void operator()() const {
+ test_output << value;
+ }
+
+ int value;
+};
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ boost::signals2::signal<void ()> s0;
+
+ for(unsigned i = 0; i < connections.size(); ++i)
+ {
+ connections.at(i) = s0.connect(test_slot(i));
+ }
+
+
+ {
+ // Blocking 2
+ boost::signals2::shared_connection_block block(connections.at(2));
+ BOOST_CHECK(block.blocking());
+ test_output.str("");
+ s0();
+ BOOST_CHECK(test_output.str() == "013");
+ }
+
+ // Unblocking 2
+ test_output.str("");
+ s0();
+ BOOST_CHECK(test_output.str() == "0123");
+
+ {
+ // Blocking 1 through const connection
+ const boost::signals2::connection conn = connections.at(1);
+ boost::signals2::shared_connection_block block(conn);
+ test_output.str("");
+ s0();
+ std::cout << test_output.str() << std::endl;
+ BOOST_CHECK(test_output.str() == "023");
+ // Unblocking 1
+ block.unblock();
+ BOOST_CHECK(block.blocking() == false);
+ test_output.str("");
+ s0();
+ BOOST_CHECK(test_output.str() == "0123");
+ }
+
+ {
+ // initially unblocked
+ boost::signals2::shared_connection_block block(connections.at(3), false);
+ BOOST_CHECK(block.blocking() == false);
+ test_output.str("");
+ s0();
+ BOOST_CHECK(test_output.str() == "0123");
+ // block
+ block.block();
+ test_output.str("");
+ s0();
+ BOOST_CHECK(test_output.str() == "012");
+ }
+
+ {
+ // test default constructed block
+ boost::signals2::shared_connection_block block;
+ BOOST_CHECK(block.blocking() == true);
+ block.unblock();
+ BOOST_CHECK(block.blocking() == false);
+ block.block();
+ BOOST_CHECK(block.blocking() == true);
+
+ // test assignment
+ {
+ block.unblock();
+ boost::signals2::shared_connection_block block2(connections.at(0));
+ BOOST_CHECK(block.connection() != block2.connection());
+ BOOST_CHECK(block.blocking() != block2.blocking());
+ block = block2;
+ BOOST_CHECK(block.connection() == block2.connection());
+ BOOST_CHECK(block.blocking() == block2.blocking());
+ }
+ test_output.str("");
+ s0();
+ BOOST_CHECK(test_output.str() == "123");
+ }
+}
diff --git a/src/boost/libs/signals2/test/signal_n_test.cpp b/src/boost/libs/signals2/test/signal_n_test.cpp
new file mode 100644
index 000000000..c1c2b4027
--- /dev/null
+++ b/src/boost/libs/signals2/test/signal_n_test.cpp
@@ -0,0 +1,352 @@
+// Boost.Signals library
+
+// Copyright Douglas Gregor 2001-2003. 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
+
+#include <boost/bind/bind.hpp>
+#include <boost/config.hpp>
+#define BOOST_TEST_MODULE signal_n_test
+#include <boost/test/included/unit_test.hpp>
+
+using namespace boost::placeholders;
+
+#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+BOOST_AUTO_TEST_CASE(test_main)
+{
+}
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+#include <boost/optional.hpp>
+#include <boost/ref.hpp>
+#include <boost/signals2.hpp>
+#include <functional>
+
+template<typename T>
+struct max_or_default {
+ typedef T result_type;
+ template<typename InputIterator>
+ typename InputIterator::value_type
+ operator()(InputIterator first, InputIterator last) const
+ {
+ boost::optional<T> max;
+ for (; first != last; ++first)
+ {
+ try
+ {
+ if(!max) max = *first;
+ else max = (*first > max.get())? *first : max;
+ }
+ catch(const boost::bad_weak_ptr &)
+ {}
+ }
+ if(max) return max.get();
+ return T();
+ }
+};
+
+struct make_int {
+ make_int(int n, int cn) : N(n), CN(n) {}
+ int operator()() { return N; }
+ int operator()() const { return CN; }
+
+ int N;
+ int CN;
+};
+
+template<int N>
+struct make_increasing_int {
+ make_increasing_int() : n(N) {}
+
+ int operator()() const { return n++; }
+
+ mutable int n;
+};
+
+int get_37() { return 37; }
+
+static void
+test_zero_args()
+{
+ make_int i42(42, 41);
+ make_int i2(2, 1);
+ make_int i72(72, 71);
+ make_int i63(63, 63);
+ make_int i62(62, 61);
+
+ {
+ boost::signals2::signal0<int, max_or_default<int>, std::string> s0;
+ boost::signals2::connection c2 = s0.connect(i2);
+ boost::signals2::connection c72 = s0.connect("72", i72);
+ boost::signals2::connection c62 = s0.connect("6x", i62);
+ boost::signals2::connection c42 = s0.connect(i42);
+ boost::signals2::connection c37 = s0.connect(&get_37);
+
+ BOOST_CHECK(s0() == 72);
+
+ s0.disconnect("72");
+ BOOST_CHECK(s0() == 62);
+
+ c72.disconnect(); // Double-disconnect should be safe
+ BOOST_CHECK(s0() == 62);
+
+ s0.disconnect("72"); // Triple-disconect should be safe
+ BOOST_CHECK(s0() == 62);
+
+ // Also connect 63 in the same group as 62
+ s0.connect("6x", i63);
+ BOOST_CHECK(s0() == 63);
+
+ // Disconnect all of the 60's
+ s0.disconnect("6x");
+ BOOST_CHECK(s0() == 42);
+
+ c42.disconnect();
+ BOOST_CHECK(s0() == 37);
+
+ c37.disconnect();
+ BOOST_CHECK(s0() == 2);
+
+ c2.disconnect();
+ BOOST_CHECK(s0() == 0);
+ }
+
+ {
+ boost::signals2::signal0<int, max_or_default<int> > s0;
+ boost::signals2::connection c2 = s0.connect(i2);
+ boost::signals2::connection c72 = s0.connect(i72);
+ boost::signals2::connection c62 = s0.connect(i62);
+ boost::signals2::connection c42 = s0.connect(i42);
+
+ const boost::signals2::signal0<int, max_or_default<int> >& cs0 = s0;
+ BOOST_CHECK(cs0() == 72);
+ }
+
+ {
+ make_increasing_int<7> i7;
+ make_increasing_int<10> i10;
+
+ boost::signals2::signal0<int, max_or_default<int> > s0;
+ boost::signals2::connection c7 = s0.connect(i7);
+ boost::signals2::connection c10 = s0.connect(i10);
+
+ BOOST_CHECK(s0() == 10);
+ BOOST_CHECK(s0() == 11);
+ }
+}
+
+static void
+test_one_arg()
+{
+ boost::signals2::signal1<int, int, max_or_default<int> > s1;
+
+ s1.connect(std::negate<int>());
+ s1.connect(boost::bind(std::multiplies<int>(), 2, _1));
+
+ BOOST_CHECK(s1(1) == 2);
+ BOOST_CHECK(s1(-1) == 1);
+}
+
+static void
+test_signal_signal_connect()
+{
+ typedef boost::signals2::signal1<int, int, max_or_default<int> > signal_type;
+ signal_type s1;
+
+ s1.connect(std::negate<int>());
+
+ BOOST_CHECK(s1(3) == -3);
+
+ {
+ signal_type s2;
+ s1.connect(s2);
+ s2.connect(boost::bind(std::multiplies<int>(), 2, _1));
+ s2.connect(boost::bind(std::multiplies<int>(), -3, _1));
+
+ BOOST_CHECK(s2(-3) == 9);
+ BOOST_CHECK(s1(3) == 6);
+ } // s2 goes out of scope and disconnects
+
+ BOOST_CHECK(s1(3) == -3);
+
+ // test auto-track of signal wrapped in a reference_wrapper
+ {
+ signal_type s2;
+ s1.connect(boost::cref(s2));
+ s2.connect(boost::bind(std::multiplies<int>(), 2, _1));
+ s2.connect(boost::bind(std::multiplies<int>(), -3, _1));
+
+ BOOST_CHECK(s2(-3) == 9);
+ BOOST_CHECK(s1(3) == 6);
+ } // s2 goes out of scope and disconnects
+
+ BOOST_CHECK(s1(3) == -3);
+}
+
+struct EventCounter
+{
+ EventCounter() : count(0) {}
+
+ void operator()()
+ {
+ ++count;
+ }
+
+ int count;
+};
+
+static void
+test_ref()
+{
+ EventCounter ec;
+ boost::signals2::signal0<void> s;
+
+ {
+ boost::signals2::scoped_connection c(s.connect(boost::ref(ec)));
+ BOOST_CHECK(ec.count == 0);
+ s();
+ BOOST_CHECK(ec.count == 1);
+ }
+ s();
+ BOOST_CHECK(ec.count == 1);
+}
+
+static void test_default_combiner()
+{
+ boost::signals2::signal0<int> sig;
+ boost::optional<int> result;
+ result = sig();
+ BOOST_CHECK(!result);
+
+ sig.connect(make_int(0, 0));
+ result = sig();
+ BOOST_CHECK(result);
+ BOOST_CHECK(*result == 0);
+
+ sig.connect(make_int(1, 1));
+ result = sig();
+ BOOST_CHECK(result);
+ BOOST_CHECK(*result == 1);
+}
+
+template<typename ResultType>
+ ResultType disconnecting_slot(const boost::signals2::connection &conn, int)
+{
+ conn.disconnect();
+ return ResultType();
+}
+
+#ifdef BOOST_NO_VOID_RETURNS
+template<>
+ void disconnecting_slot<void>(const boost::signals2::connection &conn, int)
+{
+ conn.disconnect();
+ return;
+}
+#endif
+
+template<typename ResultType>
+ void test_extended_slot()
+{
+ {
+ typedef boost::signals2::signal1<ResultType, int> signal_type;
+ typedef typename signal_type::extended_slot_type slot_type;
+ signal_type sig;
+ // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
+ ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
+ slot_type myslot(fp);
+ sig.connect_extended(myslot);
+ BOOST_CHECK(sig.num_slots() == 1);
+ sig(0);
+ BOOST_CHECK(sig.num_slots() == 0);
+ }
+ { // test 0 arg signal
+ typedef boost::signals2::signal0<ResultType> signal_type;
+ typedef typename signal_type::extended_slot_type slot_type;
+ signal_type sig;
+ // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
+ ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
+ slot_type myslot(fp, _1, 0);
+ sig.connect_extended(myslot);
+ BOOST_CHECK(sig.num_slots() == 1);
+ sig();
+ BOOST_CHECK(sig.num_slots() == 0);
+ }
+ // test disconnection by slot
+ {
+ typedef boost::signals2::signal1<ResultType, int> signal_type;
+ typedef typename signal_type::extended_slot_type slot_type;
+ signal_type sig;
+ // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
+ ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
+ slot_type myslot(fp);
+ sig.connect_extended(myslot);
+ BOOST_CHECK(sig.num_slots() == 1);
+ sig.disconnect(fp);
+ BOOST_CHECK(sig.num_slots() == 0);
+ }
+}
+class dummy_combiner
+{
+public:
+ typedef int result_type;
+
+ dummy_combiner(result_type return_value): _return_value(return_value)
+ {}
+ template<typename SlotIterator>
+ result_type operator()(SlotIterator, SlotIterator)
+ {
+ return _return_value;
+ }
+private:
+ result_type _return_value;
+};
+
+static void
+test_set_combiner()
+{
+ typedef boost::signals2::signal0<int, dummy_combiner> signal_type;
+ signal_type sig(dummy_combiner(0));
+ BOOST_CHECK(sig() == 0);
+ BOOST_CHECK(sig.combiner()(0,0) == 0);
+ sig.set_combiner(dummy_combiner(1));
+ BOOST_CHECK(sig() == 1);
+ BOOST_CHECK(sig.combiner()(0,0) == 1);
+}
+
+static void
+test_swap()
+{
+ typedef boost::signals2::signal0<int, dummy_combiner> signal_type;
+ signal_type sig1(dummy_combiner(1));
+ BOOST_CHECK(sig1() == 1);
+ signal_type sig2(dummy_combiner(2));
+ BOOST_CHECK(sig2() == 2);
+
+ sig1.swap(sig2);
+ BOOST_CHECK(sig1() == 2);
+ BOOST_CHECK(sig2() == 1);
+
+ using std::swap;
+ swap(sig1, sig2);
+ BOOST_CHECK(sig1() == 1);
+ BOOST_CHECK(sig2() == 2);
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ test_zero_args();
+ test_one_arg();
+ test_signal_signal_connect();
+ test_ref();
+ test_default_combiner();
+ test_extended_slot<void>();
+ test_extended_slot<int>();
+ test_set_combiner();
+ test_swap();
+}
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
diff --git a/src/boost/libs/signals2/test/signal_test.cpp b/src/boost/libs/signals2/test/signal_test.cpp
new file mode 100644
index 000000000..3ae2817f7
--- /dev/null
+++ b/src/boost/libs/signals2/test/signal_test.cpp
@@ -0,0 +1,348 @@
+// Boost.Signals library
+
+// Copyright Frank Mori Hess 2008-2009.
+// Copyright Douglas Gregor 2001-2003.
+//
+// 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
+
+#include <boost/bind/bind.hpp>
+#include <boost/optional.hpp>
+#include <boost/signals2.hpp>
+#define BOOST_TEST_MODULE signal_test
+#include <boost/test/included/unit_test.hpp>
+#include <functional>
+#include <iostream>
+#include <typeinfo>
+
+using namespace boost::placeholders;
+
+template<typename T>
+struct max_or_default {
+ typedef T result_type;
+ template<typename InputIterator>
+ typename InputIterator::value_type
+ operator()(InputIterator first, InputIterator last) const
+ {
+ boost::optional<T> max;
+ for (; first != last; ++first)
+ {
+ try
+ {
+ if(!max) max = *first;
+ else max = (*first > max.get())? *first : max;
+ }
+ catch(const boost::bad_weak_ptr &)
+ {}
+ }
+ if(max) return max.get();
+ return T();
+ }
+};
+
+struct make_int {
+ make_int(int n, int cn) : N(n), CN(cn) {}
+
+ int operator()() { return N; }
+ int operator()() const { return CN; }
+
+ int N;
+ int CN;
+};
+
+template<int N>
+struct make_increasing_int {
+ make_increasing_int() : n(N) {}
+
+ int operator()() const { return n++; }
+
+ mutable int n;
+};
+
+static void
+test_zero_args()
+{
+ make_int i42(42, 41);
+ make_int i2(2, 1);
+ make_int i72(72, 71);
+ make_int i63(63, 63);
+ make_int i62(62, 61);
+
+ {
+ boost::signals2::signal<int (), max_or_default<int> > s0;
+
+ std::cout << "sizeof(signal) = " << sizeof(s0) << std::endl;
+ boost::signals2::connection c2 = s0.connect(i2);
+ boost::signals2::connection c72 = s0.connect(72, i72);
+ boost::signals2::connection c62 = s0.connect(60, i62);
+ boost::signals2::connection c42 = s0.connect(i42);
+
+ BOOST_CHECK(s0() == 72);
+
+ s0.disconnect(72);
+ BOOST_CHECK(s0() == 62);
+
+ c72.disconnect(); // Double-disconnect should be safe
+ BOOST_CHECK(s0() == 62);
+
+ s0.disconnect(72); // Triple-disconect should be safe
+ BOOST_CHECK(s0() == 62);
+
+ // Also connect 63 in the same group as 62
+ s0.connect(60, i63);
+ BOOST_CHECK(s0() == 63);
+
+ // Disconnect all of the 60's
+ s0.disconnect(60);
+ BOOST_CHECK(s0() == 42);
+
+ c42.disconnect();
+ BOOST_CHECK(s0() == 2);
+
+ c2.disconnect();
+ BOOST_CHECK(s0() == 0);
+ }
+
+ {
+ boost::signals2::signal<int (), max_or_default<int> > s0;
+ boost::signals2::connection c2 = s0.connect(i2);
+ boost::signals2::connection c72 = s0.connect(i72);
+ boost::signals2::connection c62 = s0.connect(i62);
+ boost::signals2::connection c42 = s0.connect(i42);
+
+ const boost::signals2::signal<int (), max_or_default<int> >& cs0 = s0;
+ BOOST_CHECK(cs0() == 72);
+ }
+
+ {
+ make_increasing_int<7> i7;
+ make_increasing_int<10> i10;
+
+ boost::signals2::signal<int (), max_or_default<int> > s0;
+ boost::signals2::connection c7 = s0.connect(i7);
+ boost::signals2::connection c10 = s0.connect(i10);
+
+ BOOST_CHECK(s0() == 10);
+ BOOST_CHECK(s0() == 11);
+ }
+}
+
+static void
+test_one_arg()
+{
+ boost::signals2::signal<int (int value), max_or_default<int> > s1;
+
+ s1.connect(std::negate<int>());
+ s1.connect(boost::bind(std::multiplies<int>(), 2, _1));
+
+ BOOST_CHECK(s1(1) == 2);
+ BOOST_CHECK(s1(-1) == 1);
+}
+
+static void
+test_signal_signal_connect()
+{
+ typedef boost::signals2::signal<int (int value), max_or_default<int> > signal_type;
+ signal_type s1;
+
+ s1.connect(std::negate<int>());
+
+ BOOST_CHECK(s1(3) == -3);
+
+ {
+ signal_type s2;
+ s1.connect(s2);
+ s2.connect(boost::bind(std::multiplies<int>(), 2, _1));
+ s2.connect(boost::bind(std::multiplies<int>(), -3, _1));
+
+ BOOST_CHECK(s2(-3) == 9);
+ BOOST_CHECK(s1(3) == 6);
+ } // s2 goes out of scope and disconnects
+ BOOST_CHECK(s1(3) == -3);
+}
+
+template<typename ResultType>
+ ResultType disconnecting_slot(const boost::signals2::connection &conn, int)
+{
+ conn.disconnect();
+ return ResultType();
+}
+
+#ifdef BOOST_NO_VOID_RETURNS
+template<>
+ void disconnecting_slot<void>(const boost::signals2::connection &conn, int)
+{
+ conn.disconnect();
+ return;
+}
+#endif
+
+template<typename ResultType>
+ void test_extended_slot()
+{
+ {
+ typedef boost::signals2::signal<ResultType (int)> signal_type;
+ typedef typename signal_type::extended_slot_type slot_type;
+ signal_type sig;
+ // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
+ ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
+ slot_type myslot(fp);
+ sig.connect_extended(myslot);
+ BOOST_CHECK(sig.num_slots() == 1);
+ sig(0);
+ BOOST_CHECK(sig.num_slots() == 0);
+ }
+ { // test 0 arg signal
+ typedef boost::signals2::signal<ResultType ()> signal_type;
+ typedef typename signal_type::extended_slot_type slot_type;
+ signal_type sig;
+ // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
+ ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
+ slot_type myslot(fp, _1, 0);
+ sig.connect_extended(myslot);
+ BOOST_CHECK(sig.num_slots() == 1);
+ sig();
+ BOOST_CHECK(sig.num_slots() == 0);
+ }
+ // test disconnection by slot
+ {
+ typedef boost::signals2::signal<ResultType (int)> signal_type;
+ typedef typename signal_type::extended_slot_type slot_type;
+ signal_type sig;
+ // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
+ ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
+ slot_type myslot(fp);
+ sig.connect_extended(myslot);
+ BOOST_CHECK(sig.num_slots() == 1);
+ sig.disconnect(fp);
+ BOOST_CHECK(sig.num_slots() == 0);
+ }
+}
+
+void increment_arg(int &value)
+{
+ ++value;
+}
+
+static void
+test_reference_args()
+{
+ typedef boost::signals2::signal<void (int &)> signal_type;
+ signal_type s1;
+
+ s1.connect(&increment_arg);
+ int value = 0;
+ s1(value);
+ BOOST_CHECK(value == 1);
+}
+
+static void
+test_typedefs_etc()
+{
+ typedef boost::signals2::signal<int (double, long)> signal_type;
+ typedef signal_type::slot_type slot_type;
+
+ BOOST_CHECK(typeid(signal_type::slot_result_type) == typeid(int));
+ BOOST_CHECK(typeid(signal_type::result_type) == typeid(boost::optional<int>));
+ BOOST_CHECK(typeid(signal_type::arg<0>::type) == typeid(double));
+ BOOST_CHECK(typeid(signal_type::arg<1>::type) == typeid(long));
+ BOOST_CHECK(typeid(signal_type::arg<0>::type) == typeid(signal_type::first_argument_type));
+ BOOST_CHECK(typeid(signal_type::arg<1>::type) == typeid(signal_type::second_argument_type));
+ BOOST_CHECK(typeid(signal_type::signature_type) == typeid(int (double, long)));
+ BOOST_CHECK(signal_type::arity == 2);
+
+ BOOST_CHECK(typeid(slot_type::result_type) == typeid(signal_type::slot_result_type));
+ BOOST_CHECK(typeid(slot_type::arg<0>::type) == typeid(signal_type::arg<0>::type));
+ BOOST_CHECK(typeid(slot_type::arg<1>::type) == typeid(signal_type::arg<1>::type));
+ BOOST_CHECK(typeid(slot_type::arg<0>::type) == typeid(slot_type::first_argument_type));
+ BOOST_CHECK(typeid(slot_type::arg<1>::type) == typeid(slot_type::second_argument_type));
+ BOOST_CHECK(typeid(slot_type::signature_type) == typeid(signal_type::signature_type));
+ BOOST_CHECK(slot_type::arity == signal_type::arity);
+
+ typedef boost::signals2::signal<void (short)> unary_signal_type;
+ BOOST_CHECK(typeid(unary_signal_type::slot_result_type) == typeid(void));
+ BOOST_CHECK(typeid(unary_signal_type::argument_type) == typeid(short));
+ BOOST_CHECK(typeid(unary_signal_type::slot_type::argument_type) == typeid(short));
+}
+
+class dummy_combiner
+{
+public:
+ typedef int result_type;
+
+ dummy_combiner(result_type return_value): _return_value(return_value)
+ {}
+ template<typename SlotIterator>
+ result_type operator()(SlotIterator, SlotIterator)
+ {
+ return _return_value;
+ }
+private:
+ result_type _return_value;
+};
+
+static void
+test_set_combiner()
+{
+ typedef boost::signals2::signal<int (), dummy_combiner> signal_type;
+ signal_type sig(dummy_combiner(0));
+ BOOST_CHECK(sig() == 0);
+ BOOST_CHECK(sig.combiner()(0,0) == 0);
+ sig.set_combiner(dummy_combiner(1));
+ BOOST_CHECK(sig() == 1);
+ BOOST_CHECK(sig.combiner()(0,0) == 1);
+}
+
+static void
+test_swap()
+{
+ typedef boost::signals2::signal<int (), dummy_combiner> signal_type;
+ signal_type sig1(dummy_combiner(1));
+ BOOST_CHECK(sig1() == 1);
+ signal_type sig2(dummy_combiner(2));
+ BOOST_CHECK(sig2() == 2);
+
+ sig1.swap(sig2);
+ BOOST_CHECK(sig1() == 2);
+ BOOST_CHECK(sig2() == 1);
+
+ using std::swap;
+ swap(sig1, sig2);
+ BOOST_CHECK(sig1() == 1);
+ BOOST_CHECK(sig2() == 2);
+}
+
+void test_move()
+{
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ typedef boost::signals2::signal<int (), dummy_combiner> signal_type;
+ signal_type sig1(dummy_combiner(1));
+ BOOST_CHECK(sig1() == 1);
+ signal_type sig2(dummy_combiner(2));
+ BOOST_CHECK(sig2() == 2);
+
+ sig1 = std::move(sig2);
+ BOOST_CHECK(sig1() == 2);
+
+ signal_type sig3(std::move(sig1));
+ BOOST_CHECK(sig3() == 2);
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ test_zero_args();
+ test_one_arg();
+ test_signal_signal_connect();
+ test_extended_slot<void>();
+ test_extended_slot<int>();
+ test_reference_args();
+ test_typedefs_etc();
+ test_set_combiner();
+ test_swap();
+ test_move();
+}
diff --git a/src/boost/libs/signals2/test/signal_type_test.cpp b/src/boost/libs/signals2/test/signal_type_test.cpp
new file mode 100644
index 000000000..94c746429
--- /dev/null
+++ b/src/boost/libs/signals2/test/signal_type_test.cpp
@@ -0,0 +1,43 @@
+// Tests for boost::signals2::signal_type
+
+// 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.
+
+#include <boost/signals2.hpp>
+#define BOOST_TEST_MODULE signal_type_test
+#include <boost/test/included/unit_test.hpp>
+
+namespace bs2 = boost::signals2;
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ {
+ bs2::signal_type<void ()>::type mysig;
+ bs2::signal<void ()> mysig2;
+ BOOST_CHECK(typeid(mysig) == typeid(mysig2));
+ }
+
+ {
+ bs2::signal_type<double (int), bs2::last_value<double> >::type mysig;
+ bs2::signal<double (int), bs2::last_value<double> > mysig2;
+ BOOST_CHECK(typeid(mysig) == typeid(mysig2));
+ }
+
+ {
+ using namespace bs2::keywords;
+ bs2::signal_type<double (int), group_compare_type<std::less<float> >, group_type<float> >::type mysig;
+ bs2::signal<double (int), bs2::optional_last_value<double>, float, std::less<float> > mysig2;
+ BOOST_CHECK(typeid(mysig) == typeid(mysig2));
+ }
+
+ {
+ using namespace bs2::keywords;
+ bs2::signal_type<signature_type<float (long*)> >::type mysig;
+ bs2::signal<float (long*)> mysig2;
+ BOOST_CHECK(typeid(mysig) == typeid(mysig2));
+ }
+}
diff --git a/src/boost/libs/signals2/test/slot_compile_test.cpp b/src/boost/libs/signals2/test/slot_compile_test.cpp
new file mode 100644
index 000000000..6ce6c3715
--- /dev/null
+++ b/src/boost/libs/signals2/test/slot_compile_test.cpp
@@ -0,0 +1,27 @@
+// Signals2 library
+// test for compilation of boost/signals2/slot.hpp
+
+// Copyright Frank Mori Hess 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
+
+#include <boost/signals2/slot.hpp>
+#define BOOST_TEST_MODULE slot_compile_test
+#include <boost/test/included/unit_test.hpp>
+
+void myslot()
+{}
+
+int myslot2(int)
+{
+ return 0;
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ boost::signals2::slot<void (void)> sl0(&myslot);
+}
diff --git a/src/boost/libs/signals2/test/threading_models_test.cpp b/src/boost/libs/signals2/test/threading_models_test.cpp
new file mode 100644
index 000000000..bddae17c0
--- /dev/null
+++ b/src/boost/libs/signals2/test/threading_models_test.cpp
@@ -0,0 +1,86 @@
+// thread_safe_signals library
+// basic test for alternate threading models
+
+// Copyright Frank Mori Hess 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
+
+#include <boost/signals2.hpp>
+#define BOOST_TEST_MODULE threading_models_test
+#include <boost/test/included/unit_test.hpp>
+#include <boost/thread/mutex.hpp>
+
+// combiner that returns the number of slots invoked
+struct slot_counter {
+ typedef unsigned result_type;
+ template<typename InputIterator>
+ unsigned operator()(InputIterator first, InputIterator last) const
+ {
+ unsigned count = 0;
+ for (; first != last; ++first)
+ {
+ try
+ {
+ *first;
+ ++count;
+ }
+ catch(const boost::bad_weak_ptr &)
+ {}
+ }
+ return count;
+ }
+};
+
+void myslot()
+{
+}
+
+template<typename signal_type>
+void simple_test()
+{
+ signal_type sig;
+ sig.connect(typename signal_type::slot_type(&myslot));
+ BOOST_CHECK(sig() == 1);
+ sig.disconnect(&myslot);
+ BOOST_CHECK(sig() == 0);
+}
+
+class recursion_checking_dummy_mutex
+{
+ int recursion_count;
+public:
+ recursion_checking_dummy_mutex(): recursion_count(0)
+ {}
+ void lock()
+ {
+ BOOST_REQUIRE(recursion_count == 0);
+ ++recursion_count;
+ }
+ bool try_lock()
+ {
+ lock();
+ return true;
+ }
+ void unlock()
+ {
+ --recursion_count;
+ BOOST_REQUIRE(recursion_count == 0);
+ }
+};
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ typedef boost::signals2::signal<void (), slot_counter, int, std::less<int>, boost::function<void ()>,
+ boost::function<void (const boost::signals2::connection &)>, recursion_checking_dummy_mutex> sig0_rc_type;
+ simple_test<sig0_rc_type>();
+ typedef boost::signals2::signal<void (), slot_counter, int, std::less<int>, boost::function<void ()>,
+ boost::function<void (const boost::signals2::connection &)>, boost::mutex> sig0_mt_type;
+ simple_test<sig0_mt_type>();
+ typedef boost::signals2::signal<void (), slot_counter, int, std::less<int>, boost::function<void ()>,
+ boost::function<void (const boost::signals2::connection &)>, boost::signals2::dummy_mutex> sig0_st_type;
+ simple_test<sig0_st_type>();
+}
diff --git a/src/boost/libs/signals2/test/track_test.cpp b/src/boost/libs/signals2/test/track_test.cpp
new file mode 100644
index 000000000..405aa11b6
--- /dev/null
+++ b/src/boost/libs/signals2/test/track_test.cpp
@@ -0,0 +1,167 @@
+// Boost.Signals library
+
+// Copyright Douglas Gregor 2001-2006
+// 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
+
+#include <memory>
+#include <boost/optional.hpp>
+#include <boost/ref.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/signals2.hpp>
+#define BOOST_TEST_MODULE track_test
+#include <boost/test/included/unit_test.hpp>
+#include <boost/bind/bind.hpp>
+
+using namespace boost::placeholders;
+
+struct swallow {
+ typedef int result_type;
+ template<typename T> result_type operator()(const T*, int i) { return i; }
+};
+
+template<typename T>
+struct max_or_default {
+ typedef T result_type;
+
+ template<typename InputIterator>
+ T operator()(InputIterator first, InputIterator last) const
+ {
+ boost::optional<T> max;
+ for(; first != last; ++first)
+ {
+ T value = *first;
+ if(!max)
+ {
+ max = value;
+ }else if(value > *max)
+ {
+ max = value;
+ }
+ }
+ if(max) return *max;
+ else return T();
+ }
+};
+
+static int myfunc(int i, double z)
+{
+ return i;
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ typedef boost::signals2::signal<int (int), max_or_default<int> > sig_type;
+ sig_type s1;
+ boost::signals2::connection connection;
+
+ // Test auto-disconnection
+ BOOST_CHECK(s1(5) == 0);
+ {
+ boost::shared_ptr<int> shorty(new int());
+ s1.connect(sig_type::slot_type(swallow(), shorty.get(), _1).track(shorty));
+ BOOST_CHECK(s1(5) == 5);
+ }
+ BOOST_CHECK(s1(5) == 0);
+
+ // Test auto-disconnection of slot before signal connection
+ {
+ boost::shared_ptr<int> shorty(new int(1));
+// doesn't work on gcc 3.3.5, it says: error: type specifier omitted for parameter `shorty'
+// does work on gcc 4.1.2
+// sig_type::slot_type slot(swallow(), shorty.get(), _1);
+ swallow myswallow;
+ sig_type::slot_type slot(myswallow, shorty.get(), _1);
+
+ slot.track(shorty);
+ shorty.reset();
+ s1.connect(slot);
+ BOOST_CHECK(s1(5) == 0);
+ }
+
+ // Test binding of a slot to another slot
+ {
+ boost::shared_ptr<int> shorty(new int(2));
+ boost::signals2::slot<int (double)> other_slot(&myfunc, boost::cref(*shorty.get()), _1);
+ other_slot.track(shorty);
+ connection = s1.connect(sig_type::slot_type(other_slot, 0.5).track(other_slot));
+ BOOST_CHECK(s1(3) == 2);
+ }
+ BOOST_CHECK(connection.connected() == false);
+ BOOST_CHECK(s1(3) == 0);
+
+ // Test binding of a signal as a slot
+ {
+ sig_type s2;
+ s1.connect(s2);
+ s2.connect(sig_type::slot_type(&myfunc, _1, 0.7));
+ BOOST_CHECK(s1(4) == 4);
+ }
+ BOOST_CHECK(s1(4) == 0);
+
+ // Test tracking of null but not empty shared_ptr
+ BOOST_CHECK(s1(2) == 0);
+ {
+ boost::shared_ptr<int> shorty((int*)(0));
+ s1.connect(sig_type::slot_type(swallow(), shorty.get(), _1).track(shorty));
+ BOOST_CHECK(s1(2) == 2);
+ }
+ BOOST_CHECK(s1(2) == 0);
+
+#ifndef BOOST_NO_CXX11_SMART_PTR
+ // Test tracking through std::shared_ptr/weak_ptr
+ BOOST_CHECK(s1(5) == 0);
+ {
+ std::shared_ptr<int> shorty(new int());
+ s1.connect(sig_type::slot_type(swallow(), shorty.get(), _1).track_foreign(shorty));
+ BOOST_CHECK(s1(5) == 5);
+ }
+ BOOST_CHECK(s1(5) == 0);
+ {
+ std::shared_ptr<int> shorty(new int());
+ s1.connect
+ (
+ sig_type::slot_type
+ (
+ swallow(),
+ shorty.get(),
+ _1
+ ).track_foreign
+ (
+ std::weak_ptr<int>(shorty)
+ )
+ );
+ BOOST_CHECK(s1(5) == 5);
+ }
+ BOOST_CHECK(s1(5) == 0);
+ // make sure tracking foreign shared_ptr<const void> works
+ {
+ std::shared_ptr<const void> shorty(new int());
+ s1.connect(sig_type::slot_type(swallow(), shorty.get(), _1).track_foreign(shorty));
+ BOOST_CHECK(s1(5) == 5);
+ }
+ {
+ std::shared_ptr<int> shorty(new int());
+ s1.connect
+ (
+ sig_type::slot_type
+ (
+ swallow(),
+ shorty.get(),
+ _1
+ ).track_foreign
+ (
+ std::weak_ptr<const void>(shorty)
+ )
+ );
+ BOOST_CHECK(s1(5) == 5);
+ }
+ BOOST_CHECK(s1(5) == 0);
+ BOOST_CHECK(s1(5) == 0);
+#endif
+}
diff --git a/src/boost/libs/signals2/test/trackable_test.cpp b/src/boost/libs/signals2/test/trackable_test.cpp
new file mode 100644
index 000000000..b3049cdfd
--- /dev/null
+++ b/src/boost/libs/signals2/test/trackable_test.cpp
@@ -0,0 +1,112 @@
+// Boost.Signals2 library
+
+// Copyright Douglas Gregor 2001-2006.
+// 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
+
+#include <boost/signals2/signal.hpp>
+#include <boost/signals2/trackable.hpp>
+#define BOOST_TEST_MODULE trackable_test
+#include <boost/test/included/unit_test.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/ref.hpp>
+#include <boost/weak_ptr.hpp>
+
+using namespace boost::placeholders;
+
+struct short_lived : public boost::signals2::trackable {
+ ~short_lived() {}
+};
+
+struct swallow {
+ typedef int result_type;
+ template<typename T> int operator()(const T*, int i) { return i; }
+ template<typename T> int operator()(T &, int i) { return i; }
+ template<typename T> int operator()(boost::weak_ptr<T>, int i) { return i; }
+};
+
+template<typename T>
+struct max_or_default {
+ typedef T result_type;
+
+ template<typename InputIterator>
+ T operator()(InputIterator first, InputIterator last) const
+ {
+ if (first == last)
+ return T();
+
+ T max = *first++;
+ for (; first != last; ++first)
+ max = (*first > max)? *first : max;
+
+ return max;
+ }
+};
+
+struct self_deleting : public boost::signals2::trackable {
+ void delete_myself(boost::signals2::connection connection)
+ {
+ BOOST_CHECK(connection.connected());
+ delete this;
+ BOOST_CHECK(connection.connected() == false);
+ }
+};
+
+// test that slot assocated with signals2::trackable
+// gets disconnected immediately upon deletion of the
+// signals2::trackable, even when a signal invocation
+// is in progress.
+void test_immediate_disconnect_on_delete()
+{
+ boost::signals2::signal<void () > sig;
+ self_deleting *obj = new self_deleting();
+ sig.connect_extended(boost::bind(&self_deleting::delete_myself, obj, _1));
+ sig();
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ typedef boost::signals2::signal<int (int), max_or_default<int> > sig_type;
+ sig_type s1;
+
+ // Test auto-disconnection
+ BOOST_CHECK(s1(5) == 0);
+ {
+ short_lived shorty;
+ s1.connect(boost::bind<int>(swallow(), &shorty, _1));
+ BOOST_CHECK(s1(5) == 5);
+ }
+ BOOST_CHECK(s1(5) == 0);
+ // Test auto-disconnection of trackable inside reference_wrapper
+ {
+ short_lived shorty;
+ s1.connect(boost::bind<int>(swallow(), boost::ref(shorty), _1));
+ BOOST_CHECK(s1(5) == 5);
+ }
+ BOOST_CHECK(s1(5) == 0);
+
+ // Test multiple arg slot constructor
+ {
+ short_lived shorty;
+ s1.connect(sig_type::slot_type(swallow(), &shorty, _1));
+ BOOST_CHECK(s1(5) == 5);
+ }
+ BOOST_CHECK(s1(5) == 0);
+
+ // Test auto-disconnection of slot before signal connection
+ {
+ short_lived* shorty = new short_lived();
+
+ sig_type::slot_type slot(boost::bind<int>(swallow(), shorty, _1));
+ delete shorty;
+
+ BOOST_CHECK(s1(5) == 0);
+ }
+
+ test_immediate_disconnect_on_delete();
+}