├── .drone ├── after-success.sh ├── before-install.sh ├── before-script.sh ├── boost.sh ├── b5847f804b-db180b7bd2.sh ├── b5847f804b-bbb3de2b00.sh ├── b5847f804b-cce9827eb5.sh └── b5847f804b-a16f359ef1.sh ├── index.html ├── .codecov.yml ├── test ├── cmake_subdir_test │ ├── main.cpp │ └── CMakeLists.txt ├── cmake_install_test │ ├── main.cpp │ └── CMakeLists.txt ├── slot_compile_test.cpp ├── CMakeLists.txt ├── dead_slot_test.cpp ├── signal_type_test.cpp ├── Jamfile.v2 ├── invocation_benchmark.cpp ├── threading_models_test.cpp ├── deadlock_regression_test.cpp ├── ordering_test.cpp ├── shared_connection_block_test.cpp ├── trackable_test.cpp ├── connection_test.cpp ├── regression_test.cpp ├── deconstruct_test.cpp └── track_test.cpp ├── meta └── libraries.json ├── doc ├── snippet-extractor.jam ├── reference │ ├── signal_base.xml │ ├── reference.xml │ ├── dummy_mutex.xml │ ├── slot_base.xml │ ├── visit_each.xml │ ├── mutex.xml │ ├── trackable.xml │ ├── last_value.xml │ └── optional_last_value.xml ├── Jamfile.v2 ├── signals.xml ├── introduction.xml ├── faq.xml ├── snippet_extractor.cpp └── tests.xml ├── example ├── CMakeLists.txt ├── hello_world_slot.cpp ├── hello_world_multi_slot.cpp ├── Jamfile.v2 ├── signal_return_value.cpp ├── extended_slot.cpp ├── postconstructor_ex1.cpp ├── passing_slots.cpp ├── slot_arguments.cpp ├── ordering_slots.cpp ├── predestructor_example.cpp ├── postconstructor_ex2.cpp ├── doc_view.cpp ├── disconnect_and_block.cpp ├── custom_combiners.cpp ├── doc_view_acm.cpp └── doc_view_acm_deconstruct.cpp ├── include └── boost │ ├── signals2.hpp │ └── signals2 │ ├── detail │ ├── lwm_nop.hpp │ ├── null_output_iterator.hpp │ ├── replace_slot_function.hpp │ ├── preprocessed_arg_type.hpp │ ├── unique_lock.hpp │ ├── preprocessed_arg_type_template.hpp │ ├── variadic_arg_type.hpp │ ├── lwm_pthreads.hpp │ ├── result_type_wrapper.hpp │ ├── signals_common.hpp │ ├── scope_guard.hpp │ ├── tracked_objects_visitor.hpp │ ├── lwm_win32_cs.hpp │ └── variadic_slot_invoker.hpp │ ├── expired_slot.hpp │ ├── variadic_slot.hpp │ ├── dummy_mutex.hpp │ ├── signal_base.hpp │ ├── slot.hpp │ ├── mutex.hpp │ ├── predestructible.hpp │ ├── variadic_signal.hpp │ ├── postconstructible.hpp │ ├── optional_last_value.hpp │ ├── shared_connection_block.hpp │ ├── trackable.hpp │ ├── signal.hpp │ ├── last_value.hpp │ ├── deconstruct_ptr.hpp │ ├── preprocessed_signal.hpp │ ├── preprocessed_slot.hpp │ ├── slot_base.hpp │ └── signal_type.hpp ├── CMakeLists.txt ├── LICENSE ├── README.md ├── .gitattributes └── appveyor.yml /.drone/after-success.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | -------------------------------------------------------------------------------- /.drone/before-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | -------------------------------------------------------------------------------- /.drone/before-script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostorg/signals2/HEAD/index.html -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | fixes: 2 | - home/travis/build/*/boost-root/boost/::include/boost/ 3 | - home/travis/build/*/boost-root/libs/*/src/::src/ 4 | -------------------------------------------------------------------------------- /test/cmake_subdir_test/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Peter Dimov. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | 7 | int f() 8 | { 9 | return 4; 10 | } 11 | 12 | int main() 13 | { 14 | boost::signals2::signal sig; 15 | 16 | sig.connect( f ); 17 | 18 | return sig() == 4? 0: 1; 19 | } 20 | -------------------------------------------------------------------------------- /test/cmake_install_test/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Peter Dimov. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | 7 | int f() 8 | { 9 | return 4; 10 | } 11 | 12 | int main() 13 | { 14 | boost::signals2::signal sig; 15 | 16 | sig.connect( f ); 17 | 18 | return sig() == 4? 0: 1; 19 | } 20 | -------------------------------------------------------------------------------- /meta/libraries.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "signals2", 3 | "name": "Signals2", 4 | "authors": [ 5 | "Frank Mori Hess" 6 | ], 7 | "description": "Managed signals & slots callback implementation (thread-safe version 2).", 8 | "category": [ 9 | "Function-objects", 10 | "Patterns" 11 | ], 12 | "maintainers": [ 13 | "Frank Mori Hess " 14 | ], 15 | "cxxstd": "03" 16 | } 17 | -------------------------------------------------------------------------------- /test/cmake_install_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018, 2019 Peter Dimov 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 4 | 5 | cmake_minimum_required(VERSION 3.5...3.16) 6 | 7 | project(cmake_install_test LANGUAGES CXX) 8 | 9 | find_package(boost_signals2 REQUIRED) 10 | 11 | add_executable(main main.cpp) 12 | target_link_libraries(main Boost::signals2) 13 | 14 | enable_testing() 15 | add_test(main main) 16 | 17 | add_custom_target(check VERBATIM COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) 18 | -------------------------------------------------------------------------------- /test/slot_compile_test.cpp: -------------------------------------------------------------------------------- 1 | // Signals2 library 2 | // test for compilation of boost/signals2/slot.hpp 3 | 4 | // Copyright Frank Mori Hess 2008 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // For more information, see http://www.boost.org 11 | 12 | #include 13 | #define BOOST_TEST_MODULE slot_compile_test 14 | #include 15 | 16 | void myslot() 17 | {} 18 | 19 | int myslot2(int) 20 | { 21 | return 0; 22 | } 23 | 24 | BOOST_AUTO_TEST_CASE(test_main) 25 | { 26 | boost::signals2::slot sl0(&myslot); 27 | } 28 | -------------------------------------------------------------------------------- /doc/snippet-extractor.jam: -------------------------------------------------------------------------------- 1 | # Boost.Signals2 Library 2 | 3 | # Copyright Frank Mori Hess 2009. 4 | 5 | # Use, modification and 6 | # distribution is subject to the Boost Software License, Version 7 | # 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | # http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | # For more information, see http://www.boost.org 11 | 12 | import feature ; 13 | import toolset ; 14 | 15 | feature.feature extractor-command : : free dependency ; 16 | toolset.flags snippet-extractor.extract-snippets EXTRACTOR-COMMAND ; 17 | 18 | rule extract-snippets ( target : sources * : properties * ) 19 | { 20 | DEPENDS $(target) : [ on $(target) return $(EXTRACTOR-COMMAND) ] ; 21 | } 22 | actions extract-snippets bind EXTRACTOR-COMMAND 23 | { 24 | $(EXTRACTOR-COMMAND[1]) "$(<:D)" $(>) 25 | } 26 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Mike Dev 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt 4 | # 5 | # NOTE: CMake support for Boost.Signals2 is currently experimental at best 6 | # and the interface is likely to change in the future 7 | 8 | file( GLOB example_src_files *.cpp ) 9 | 10 | find_package(Threads REQUIRED) 11 | 12 | foreach( file IN LISTS example_src_files ) 13 | 14 | get_filename_component( example_name ${file} NAME_WE ) 15 | 16 | add_executable( boost_signals2_example_${example_name} ${file} ) 17 | target_link_libraries( boost_signals2_example_${example_name} 18 | PUBLIC 19 | Boost::signals2 20 | Boost::io 21 | Threads::Threads 22 | ) 23 | 24 | endforeach() 25 | -------------------------------------------------------------------------------- /include/boost/signals2.hpp: -------------------------------------------------------------------------------- 1 | // A convenience header for Boost.Signals2, should pull in everying in the library. 2 | 3 | // Copyright (c) 2008-2009 Frank Mori Hess 4 | 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | #ifndef BOOST_SIGNALS2_HPP 11 | #define BOOST_SIGNALS2_HPP 12 | 13 | // For documentation, see http://www.boost.org/libs/signals2/ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/lwm_nop.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // boost/signals2/detail/lwm_nop.hpp 3 | // 4 | // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. 5 | // Copyright (c) 2008 Frank Mori Hess 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See 8 | // accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // 11 | 12 | #ifndef BOOST_SIGNALS2_LWM_NOP_HPP 13 | #define BOOST_SIGNALS2_LWM_NOP_HPP 14 | 15 | // MS compatible compilers support #pragma once 16 | 17 | #if defined(_MSC_VER) 18 | # pragma once 19 | #endif 20 | 21 | 22 | #include 23 | 24 | namespace boost 25 | { 26 | 27 | namespace signals2 28 | { 29 | 30 | class mutex: public dummy_mutex 31 | { 32 | }; 33 | 34 | } // namespace signals2 35 | 36 | } // namespace boost 37 | 38 | #endif // #ifndef BOOST_SIGNALS2_LWM_NOP_HPP 39 | -------------------------------------------------------------------------------- /include/boost/signals2/expired_slot.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Frank Mori Hess 2007-2010. 4 | // Use, modification and 5 | // distribution is subject to the Boost Software License, Version 6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // For more information, see http://www.boost.org 10 | 11 | #ifndef BOOST_SIGNALS2_EXPIRED_SLOT_HPP 12 | #define BOOST_SIGNALS2_EXPIRED_SLOT_HPP 13 | 14 | #include 15 | 16 | namespace boost 17 | { 18 | namespace signals2 19 | { 20 | class expired_slot: public bad_weak_ptr 21 | { 22 | public: 23 | virtual char const * what() const throw() 24 | { 25 | return "boost::signals2::expired_slot"; 26 | } 27 | }; 28 | } 29 | } // end namespace boost 30 | 31 | #endif // BOOST_SIGNALS2_EXPIRED_SLOT_HPP 32 | -------------------------------------------------------------------------------- /include/boost/signals2/variadic_slot.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Frank Mori Hess 2009. 4 | // 5 | // distribution is subject to the Boost Software License, Version 6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // For more information, see http://www.boost.org 10 | 11 | #ifndef BOOST_SIGNALS2_VARIADIC_SLOT_HPP 12 | #define BOOST_SIGNALS2_VARIADIC_SLOT_HPP 13 | 14 | #include 15 | 16 | #define BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTORS \ 17 | template \ 18 | slot(const A1 &arg1, const A2 &arg2, const BindArgs & ... args) \ 19 | { \ 20 | init_slot_function(boost::bind(arg1, arg2, args...)); \ 21 | } 22 | 23 | 24 | #include 25 | #endif // BOOST_SIGNALS2_VARIADIC_SLOT_HPP 26 | -------------------------------------------------------------------------------- /include/boost/signals2/dummy_mutex.hpp: -------------------------------------------------------------------------------- 1 | // A model of the Lockable concept from Boost.Thread which 2 | // does nothing. It can be passed as the Mutex template parameter 3 | // for a signal, if the user wishes to disable thread-safety 4 | // (presumably for performance reasons). 5 | 6 | // Copyright Frank Mori Hess 2008. 7 | // Distributed under the Boost Software License, Version 8 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | 11 | // See http://www.boost.org/libs/signals2 for library home page. 12 | 13 | #ifndef BOOST_SIGNALS2_DUMMY_MUTEX_HPP 14 | #define BOOST_SIGNALS2_DUMMY_MUTEX_HPP 15 | 16 | namespace boost { 17 | namespace signals2 { 18 | class dummy_mutex 19 | { 20 | public: 21 | void lock() {} 22 | bool try_lock() {return true;} 23 | void unlock() {} 24 | }; 25 | } // end namespace signals2 26 | } // end namespace boost 27 | 28 | #endif // BOOST_SIGNALS2_DUMMY_MUTEX_HPP 29 | -------------------------------------------------------------------------------- /include/boost/signals2/signal_base.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Frank Mori Hess 2007-2008. 4 | // Use, modification and 5 | // distribution is subject to the Boost Software License, Version 6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // For more information, see http://www.boost.org 10 | 11 | #ifndef BOOST_SIGNALS2_SIGNAL_BASE_HPP 12 | #define BOOST_SIGNALS2_SIGNAL_BASE_HPP 13 | 14 | #include 15 | #include 16 | 17 | namespace boost { 18 | namespace signals2 { 19 | class slot_base; 20 | 21 | class signal_base : public noncopyable 22 | { 23 | public: 24 | friend class slot_base; 25 | 26 | virtual ~signal_base() {} 27 | protected: 28 | virtual shared_ptr lock_pimpl() const = 0; 29 | }; 30 | } // end namespace signals2 31 | } // end namespace boost 32 | 33 | #endif // BOOST_SIGNALS2_SIGNAL_BASE_HPP 34 | -------------------------------------------------------------------------------- /doc/reference/signal_base.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | noncopyable 17 | 18 | Base class for signals. 19 | 20 | Virtual destructor. 21 | 22 | 23 | 24 | 25 |
26 | -------------------------------------------------------------------------------- /example/hello_world_slot.cpp: -------------------------------------------------------------------------------- 1 | // Beginner hello world example for Boost.Signals2 2 | // Copyright Douglas Gregor 2001-2004. 3 | // Copyright Frank Mori Hess 2009. 4 | // 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // For more information, see http://www.boost.org 10 | 11 | #include 12 | #include 13 | 14 | //[ hello_world_def_code_snippet 15 | struct HelloWorld 16 | { 17 | void operator()() const 18 | { 19 | std::cout << "Hello, World!" << std::endl; 20 | } 21 | }; 22 | //] 23 | 24 | int main() 25 | { 26 | //[ hello_world_single_code_snippet 27 | // Signal with no arguments and a void return value 28 | boost::signals2::signal sig; 29 | 30 | // Connect a HelloWorld slot 31 | HelloWorld hello; 32 | sig.connect(hello); 33 | 34 | // Call all of the slots 35 | sig(); 36 | //] 37 | 38 | return 0; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /example/hello_world_multi_slot.cpp: -------------------------------------------------------------------------------- 1 | // Multiple slot hello world example for Boost.Signals2 2 | // Copyright Douglas Gregor 2001-2004. 3 | // Copyright Frank Mori Hess 2009. 4 | // 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // For more information, see http://www.boost.org 10 | 11 | #include 12 | #include 13 | 14 | //[ hello_def_code_snippet 15 | struct Hello 16 | { 17 | void operator()() const 18 | { 19 | std::cout << "Hello"; 20 | } 21 | }; 22 | //] 23 | 24 | //[ world_def_code_snippet 25 | struct World 26 | { 27 | void operator()() const 28 | { 29 | std::cout << ", World!" << std::endl; 30 | } 31 | }; 32 | //] 33 | 34 | int main() 35 | { 36 | //[ hello_world_multi_code_snippet 37 | boost::signals2::signal sig; 38 | 39 | sig.connect(Hello()); 40 | sig.connect(World()); 41 | 42 | sig(); 43 | //] 44 | 45 | return 0; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/null_output_iterator.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | An output iterator which simply discards output. 3 | */ 4 | // Copyright Frank Mori Hess 2008. 5 | // Distributed under the Boost Software License, Version 6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/signals2 for library home page. 10 | 11 | #ifndef BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP 12 | #define BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP 13 | 14 | #include 15 | 16 | namespace boost 17 | { 18 | namespace signals2 19 | { 20 | namespace detail 21 | { 22 | class does_nothing 23 | { 24 | public: 25 | template 26 | void operator()(const T&) const 27 | {} 28 | }; 29 | typedef boost::function_output_iterator null_output_iterator; 30 | } // namespace detail 31 | } // namespace signals2 32 | } // namespace boost 33 | 34 | #endif // BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP 35 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/replace_slot_function.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Frank Mori Hess 2007-2009 2 | // 3 | // Use, modification and 4 | // distribution is subject to the Boost Software License, Version 5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | // For more information, see http://www.boost.org 9 | 10 | #ifndef BOOST_SIGNALS2_DETAIL_REPLACE_SLOT_FUNCTION_HPP 11 | #define BOOST_SIGNALS2_DETAIL_REPLACE_SLOT_FUNCTION_HPP 12 | 13 | #include 14 | 15 | namespace boost 16 | { 17 | namespace signals2 18 | { 19 | namespace detail 20 | { 21 | template 22 | ResultSlot replace_slot_function(const SlotIn &slot_in, const SlotFunction &fun) 23 | { 24 | ResultSlot slot(fun); 25 | slot.track(slot_in); 26 | return slot; 27 | } 28 | } // namespace detail 29 | } // namespace signals2 30 | } // namespace boost 31 | 32 | #endif // BOOST_SIGNALS2_DETAIL_REPLACE_SLOT_FUNCTION_HPP 33 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated by `boostdep --cmake signals2` 2 | # Copyright 2020, 2021 Peter Dimov 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # https://www.boost.org/LICENSE_1_0.txt 5 | 6 | cmake_minimum_required(VERSION 3.5...3.20) 7 | 8 | project(boost_signals2 VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) 9 | 10 | add_library(boost_signals2 INTERFACE) 11 | add_library(Boost::signals2 ALIAS boost_signals2) 12 | 13 | target_include_directories(boost_signals2 INTERFACE include) 14 | 15 | target_link_libraries(boost_signals2 16 | INTERFACE 17 | Boost::assert 18 | Boost::bind 19 | Boost::config 20 | Boost::core 21 | Boost::function 22 | Boost::iterator 23 | Boost::move 24 | Boost::mpl 25 | Boost::optional 26 | Boost::parameter 27 | Boost::preprocessor 28 | Boost::smart_ptr 29 | Boost::throw_exception 30 | Boost::tuple 31 | Boost::type_traits 32 | Boost::variant 33 | ) 34 | 35 | if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") 36 | 37 | add_subdirectory(test) 38 | 39 | endif() 40 | -------------------------------------------------------------------------------- /include/boost/signals2/slot.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Frank Mori Hess 2009. 4 | // 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // For more information, see http://www.boost.org 11 | 12 | #ifndef BOOST_SIGNALS2_SLOT_HPP 13 | #define BOOST_SIGNALS2_SLOT_HPP 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES 28 | #include 29 | #else 30 | #include 31 | #endif 32 | 33 | #endif // BOOST_SIGNALS2_SLOT_HPP 34 | -------------------------------------------------------------------------------- /.drone/boost.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | export TRAVIS_BUILD_DIR=$(pwd) 5 | export DRONE_BUILD_DIR=$(pwd) 6 | export TRAVIS_BRANCH=$DRONE_BRANCH 7 | export VCS_COMMIT_ID=$DRONE_COMMIT 8 | export GIT_COMMIT=$DRONE_COMMIT 9 | export REPO_NAME=$DRONE_REPO 10 | export PATH=~/.local/bin:/usr/local/bin:$PATH 11 | 12 | echo '==================================> BEFORE_INSTALL' 13 | 14 | . .drone/before-install.sh 15 | 16 | echo '==================================> INSTALL' 17 | 18 | git clone https://github.com/boostorg/boost-ci.git boost-ci 19 | cp -pr boost-ci/ci boost-ci/.codecov.yml . 20 | 21 | if [ "$TRAVIS_OS_NAME" == "osx" ]; then 22 | unset -f cd 23 | fi 24 | 25 | export SELF=`basename $REPO_NAME` 26 | export BOOST_CI_TARGET_BRANCH="$TRAVIS_BRANCH" 27 | export BOOST_CI_SRC_FOLDER=$(pwd) 28 | 29 | . ./ci/common_install.sh 30 | 31 | echo '==================================> BEFORE_SCRIPT' 32 | 33 | . $DRONE_BUILD_DIR/.drone/before-script.sh 34 | 35 | echo '==================================> SCRIPT' 36 | 37 | cd $BOOST_ROOT/libs/$SELF 38 | ci/travis/build.sh 39 | 40 | echo '==================================> AFTER_SUCCESS' 41 | 42 | . $DRONE_BUILD_DIR/.drone/after-success.sh 43 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/preprocessed_arg_type.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Frank Mori Hess 2007-2009. 4 | // Copyright Timmo Stange 2007. 5 | // Copyright Douglas Gregor 2001-2004. Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // For more information, see http://www.boost.org 11 | 12 | #ifndef BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_HPP 13 | #define BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_HPP 14 | 15 | #include 16 | #include 17 | 18 | #define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_INC(BOOST_SIGNALS2_MAX_ARGS)) 19 | #define BOOST_PP_FILENAME_1 20 | #include BOOST_PP_ITERATE() 21 | 22 | namespace boost 23 | { 24 | namespace signals2 25 | { 26 | namespace detail 27 | { 28 | struct std_functional_base 29 | {}; 30 | } // namespace detail 31 | } // namespace signals2 32 | } // namespace boost 33 | 34 | #endif // BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_HPP 35 | -------------------------------------------------------------------------------- /.drone/b5847f804b-db180b7bd2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | export TRAVIS_BUILD_DIR=$(pwd) 5 | export DRONE_BUILD_DIR=$(pwd) 6 | export TRAVIS_BRANCH=$DRONE_BRANCH 7 | export VCS_COMMIT_ID=$DRONE_COMMIT 8 | export GIT_COMMIT=$DRONE_COMMIT 9 | export REPO_NAME=$DRONE_REPO 10 | export PATH=~/.local/bin:/usr/local/bin:$PATH 11 | 12 | echo '==================================> BEFORE_INSTALL' 13 | 14 | . .drone/before-install.sh 15 | 16 | echo '==================================> INSTALL' 17 | 18 | git clone https://github.com/boostorg/boost-ci.git boost-ci 19 | cp -pr boost-ci/ci boost-ci/.codecov.yml . 20 | 21 | if [ "$TRAVIS_OS_NAME" == "osx" ]; then 22 | unset -f cd 23 | fi 24 | 25 | export SELF=`basename $REPO_NAME` 26 | export BOOST_CI_TARGET_BRANCH="$TRAVIS_BRANCH" 27 | export BOOST_CI_SRC_FOLDER=$(pwd) 28 | 29 | . ./ci/common_install.sh 30 | 31 | echo '==================================> BEFORE_SCRIPT' 32 | 33 | . $DRONE_BUILD_DIR/.drone/before-script.sh 34 | 35 | echo '==================================> SCRIPT' 36 | 37 | cd $BOOST_ROOT/libs/$SELF 38 | ci/travis/valgrind.sh 39 | 40 | echo '==================================> AFTER_SUCCESS' 41 | 42 | . $DRONE_BUILD_DIR/.drone/after-success.sh 43 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/unique_lock.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Provides a basic subset of boost::unique_lock functionality. Provided only because 3 | including boost/thread/locks.hpp requires linking to thread library 4 | */ 5 | // Copyright Frank Mori Hess 2008. 6 | // Distributed under the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // See http://www.boost.org/libs/signals2 for library home page. 11 | 12 | #ifndef BOOST_SIGNALS2_UNIQUE_LOCK_HPP 13 | #define BOOST_SIGNALS2_UNIQUE_LOCK_HPP 14 | 15 | #include 16 | 17 | namespace boost 18 | { 19 | namespace signals2 20 | { 21 | namespace detail 22 | { 23 | template 24 | class unique_lock: public noncopyable 25 | { 26 | public: 27 | unique_lock(Mutex &m): _mutex(m) 28 | { 29 | _mutex.lock(); 30 | } 31 | ~unique_lock() 32 | { 33 | _mutex.unlock(); 34 | } 35 | private: 36 | Mutex &_mutex; 37 | }; 38 | } // namespace detail 39 | } // namespace signals2 40 | } // namespace boost 41 | 42 | #endif // BOOST_SIGNALS2_UNIQUE_LOCK_HPP 43 | -------------------------------------------------------------------------------- /include/boost/signals2/mutex.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // boost/signals2/mutex.hpp - header-only mutex 3 | // 4 | // Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. 5 | // Copyright (c) 2008 Frank Mori Hess 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See 8 | // accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // 11 | // boost::signals2::mutex is a modification of 12 | // boost::detail::lightweight_mutex to follow the newer Lockable 13 | // concept of Boost.Thread. 14 | // 15 | 16 | #ifndef BOOST_SIGNALS2_MUTEX_HPP 17 | #define BOOST_SIGNALS2_MUTEX_HPP 18 | 19 | // MS compatible compilers support #pragma once 20 | 21 | #if defined(_MSC_VER) 22 | # pragma once 23 | #endif 24 | 25 | #include 26 | 27 | #if !defined(BOOST_HAS_THREADS) 28 | # include 29 | #elif defined(BOOST_HAS_PTHREADS) 30 | # include 31 | #elif defined(BOOST_HAS_WINTHREADS) 32 | # include 33 | #else 34 | // Use #define BOOST_DISABLE_THREADS to avoid the error 35 | # error Unrecognized threading platform 36 | #endif 37 | 38 | #endif // #ifndef BOOST_SIGNALS2_MUTEX_HPP 39 | -------------------------------------------------------------------------------- /example/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Boost.Signals2 example programs 2 | 3 | # Copyright Michael Caisse 2010 4 | # Use, modification and 5 | # distribution is subject to the Boost Software License, Version 6 | # 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | # http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | # For more information, see http://www.boost.org 10 | 11 | project : requirements /boost/signals2//boost_signals2 ; 12 | 13 | exe hello_world_slot : hello_world_slot.cpp ; 14 | 15 | exe hello_world_multi_slot : hello_world_multi_slot.cpp ; 16 | 17 | exe ordering_slots : ordering_slots.cpp ; 18 | 19 | exe passing_slots : passing_slots.cpp ; 20 | 21 | exe extended_slot : extended_slot.cpp ; 22 | 23 | exe custom_combiners : custom_combiners.cpp ; 24 | 25 | exe disconnect_and_block : disconnect_and_block.cpp ; 26 | 27 | exe doc_view : doc_view.cpp ; 28 | 29 | exe doc_view_acm : doc_view_acm.cpp ; 30 | 31 | exe doc_view_acm_deconstruct : doc_view_acm_deconstruct.cpp ; 32 | 33 | exe postconstructor_ex1 : postconstructor_ex1.cpp ; 34 | 35 | exe postconstructor_ex2 : postconstructor_ex2.cpp ; 36 | 37 | exe predestructor_example : predestructor_example.cpp ; 38 | 39 | exe signal_return_value : signal_return_value.cpp ; 40 | 41 | exe slot_arguments : slot_arguments.cpp ; 42 | 43 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Peter Dimov 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # https://www.boost.org/LICENSE_1_0.txt 4 | 5 | include(BoostTest OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) 6 | 7 | if(NOT HAVE_BOOST_TEST) 8 | return() 9 | endif() 10 | 11 | set(BOOST_TEST_LINK_LIBRARIES Boost::signals2 Boost::included_unit_test_framework) 12 | 13 | boost_test(TYPE run SOURCES connection_test.cpp) 14 | boost_test(TYPE run SOURCES dead_slot_test.cpp) 15 | boost_test(TYPE run SOURCES deadlock_regression_test.cpp) 16 | boost_test(TYPE run SOURCES deconstruct_test.cpp) 17 | boost_test(TYPE run SOURCES deletion_test.cpp) 18 | boost_test(TYPE run SOURCES ordering_test.cpp) 19 | boost_test(TYPE run SOURCES regression_test.cpp) 20 | boost_test(TYPE run SOURCES shared_connection_block_test.cpp) 21 | boost_test(TYPE run SOURCES signal_n_test.cpp) 22 | boost_test(TYPE run SOURCES signal_test.cpp) 23 | boost_test(TYPE run SOURCES signal_type_test.cpp) 24 | boost_test(TYPE run SOURCES slot_compile_test.cpp) 25 | boost_test(TYPE run SOURCES trackable_test.cpp) 26 | boost_test(TYPE run SOURCES track_test.cpp) 27 | 28 | list(APPEND BOOST_TEST_LINK_LIBRARIES Boost::thread) 29 | 30 | boost_test(TYPE run SOURCES mutex_test.cpp) 31 | boost_test(TYPE run SOURCES threading_models_test.cpp) 32 | -------------------------------------------------------------------------------- /example/signal_return_value.cpp: -------------------------------------------------------------------------------- 1 | // Example program for returning a value from slots to signal invocation. 2 | // 3 | // Copyright Douglas Gregor 2001-2004. 4 | // Copyright Frank Mori Hess 2009. 5 | // 6 | // Use, modification and 7 | // distribution is subject to the Boost Software License, Version 8 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // For more information, see http://www.boost.org 11 | 12 | #include 13 | #include 14 | 15 | //[ signal_return_value_slot_defs_code_snippet 16 | float product(float x, float y) { return x * y; } 17 | float quotient(float x, float y) { return x / y; } 18 | float sum(float x, float y) { return x + y; } 19 | float difference(float x, float y) { return x - y; } 20 | //] 21 | 22 | int main() 23 | { 24 | boost::signals2::signal sig; 25 | 26 | //[ signal_return_value_main_code_snippet 27 | sig.connect(&product); 28 | sig.connect("ient); 29 | sig.connect(&sum); 30 | sig.connect(&difference); 31 | 32 | // The default combiner returns a boost::optional containing the return 33 | // value of the last slot in the slot list, in this case the 34 | // difference function. 35 | std::cout << *sig(5, 3) << std::endl; 36 | //] 37 | } 38 | 39 | -------------------------------------------------------------------------------- /test/cmake_subdir_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018, 2019 Peter Dimov 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 4 | 5 | cmake_minimum_required(VERSION 3.5...3.20) 6 | 7 | project(cmake_subdir_test LANGUAGES CXX) 8 | 9 | add_subdirectory(../.. boostorg/signals2) 10 | 11 | # boostdep --brief signals2 12 | 13 | set(deps 14 | 15 | # Primary dependencies 16 | 17 | assert 18 | bind 19 | config 20 | core 21 | function 22 | iterator 23 | move 24 | mpl 25 | optional 26 | parameter 27 | preprocessor 28 | smart_ptr 29 | throw_exception 30 | tuple 31 | type_traits 32 | variant 33 | 34 | # Secondary dependencies 35 | 36 | static_assert 37 | concept_check 38 | detail 39 | function_types 40 | fusion 41 | utility 42 | predef 43 | mp11 44 | container_hash 45 | integer 46 | type_index 47 | describe 48 | functional 49 | typeof 50 | io 51 | ) 52 | 53 | foreach(dep IN LISTS deps) 54 | 55 | add_subdirectory(../../../${dep} boostorg/${dep}) 56 | 57 | endforeach() 58 | 59 | # --target check 60 | 61 | add_executable(main main.cpp) 62 | target_link_libraries(main Boost::signals2) 63 | 64 | enable_testing() 65 | add_test(main main) 66 | 67 | add_custom_target(check VERBATIM COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) 68 | -------------------------------------------------------------------------------- /.drone/b5847f804b-bbb3de2b00.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | export TRAVIS_BUILD_DIR=$(pwd) 5 | export DRONE_BUILD_DIR=$(pwd) 6 | export TRAVIS_BRANCH=$DRONE_BRANCH 7 | export VCS_COMMIT_ID=$DRONE_COMMIT 8 | export GIT_COMMIT=$DRONE_COMMIT 9 | export REPO_NAME=$DRONE_REPO 10 | export PATH=~/.local/bin:/usr/local/bin:$PATH 11 | 12 | echo '==================================> BEFORE_INSTALL' 13 | 14 | . .drone/before-install.sh 15 | 16 | echo '==================================> INSTALL' 17 | 18 | git clone https://github.com/boostorg/boost-ci.git boost-ci 19 | cp -pr boost-ci/ci boost-ci/.codecov.yml . 20 | 21 | if [ "$TRAVIS_OS_NAME" == "osx" ]; then 22 | unset -f cd 23 | fi 24 | 25 | export SELF=`basename $REPO_NAME` 26 | export BOOST_CI_TARGET_BRANCH="$TRAVIS_BRANCH" 27 | export BOOST_CI_SRC_FOLDER=$(pwd) 28 | 29 | . ./ci/common_install.sh 30 | 31 | echo '==================================> BEFORE_SCRIPT' 32 | 33 | . $DRONE_BUILD_DIR/.drone/before-script.sh 34 | 35 | echo '==================================> SCRIPT' 36 | 37 | pushd /tmp && git clone https://github.com/linux-test-project/lcov.git && export PATH=/tmp/lcov/bin:$PATH && which lcov && lcov --version && popd 38 | cd $BOOST_ROOT/libs/$SELF 39 | ci/travis/codecov.sh 40 | 41 | echo '==================================> AFTER_SUCCESS' 42 | 43 | . $DRONE_BUILD_DIR/.drone/after-success.sh 44 | -------------------------------------------------------------------------------- /example/extended_slot.cpp: -------------------------------------------------------------------------------- 1 | // Example program for connecting an extended slot, 2 | // using a signal's connect_extended and extended_slot_type. 3 | // 4 | // Copyright Frank Mori Hess 2009. 5 | // 6 | // Use, modification and 7 | // distribution is subject to the Boost Software License, Version 8 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // For more information, see http://www.boost.org 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace bs2 = boost::signals2; 17 | 18 | void single_shot_slot(const bs2::connection &conn, const std::string &message) 19 | { 20 | conn.disconnect(); 21 | std::cout << message; 22 | } 23 | 24 | int main() 25 | { 26 | typedef bs2::signal sig_type; 27 | sig_type sig; 28 | { 29 | sig_type::extended_slot_type hello(&single_shot_slot, boost::placeholders::_1, "Hello"); 30 | sig.connect_extended(hello); 31 | } 32 | sig(); // prints "Hello" 33 | { 34 | sig_type::extended_slot_type world(&single_shot_slot, boost::placeholders::_1, ", World!\n"); 35 | sig.connect_extended(world); 36 | } 37 | sig(); // only prints ", World!\n" since hello slot has disconnected itself 38 | sig(); // prints nothing, world slot has disconnected itself 39 | 40 | return 0; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /.drone/b5847f804b-cce9827eb5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | export TRAVIS_BUILD_DIR=$(pwd) 5 | export DRONE_BUILD_DIR=$(pwd) 6 | export TRAVIS_BRANCH=$DRONE_BRANCH 7 | export VCS_COMMIT_ID=$DRONE_COMMIT 8 | export GIT_COMMIT=$DRONE_COMMIT 9 | export REPO_NAME=$DRONE_REPO 10 | export PATH=~/.local/bin:/usr/local/bin:$PATH 11 | 12 | echo '==================================> BEFORE_INSTALL' 13 | 14 | . .drone/before-install.sh 15 | 16 | echo '==================================> INSTALL' 17 | 18 | git clone https://github.com/boostorg/boost-ci.git boost-ci 19 | cp -pr boost-ci/ci boost-ci/.codecov.yml . 20 | 21 | if [ "$TRAVIS_OS_NAME" == "osx" ]; then 22 | unset -f cd 23 | fi 24 | 25 | export SELF=`basename $REPO_NAME` 26 | export BOOST_CI_TARGET_BRANCH="$TRAVIS_BRANCH" 27 | export BOOST_CI_SRC_FOLDER=$(pwd) 28 | 29 | . ./ci/common_install.sh 30 | 31 | echo '==================================> BEFORE_SCRIPT' 32 | 33 | . $DRONE_BUILD_DIR/.drone/before-script.sh 34 | 35 | echo '==================================> SCRIPT' 36 | 37 | if [ -n "${COVERITY_SCAN_NOTIFICATION_EMAIL}" -a \( "$DRONE_BRANCH" = "develop" -o "$DRONE_BRANCH" = "master" \) -a "$DRONE_BUILD_EVENT" = "push" ] ; then 38 | cd $BOOST_ROOT/libs/$SELF 39 | ci/travis/coverity.sh 40 | fi 41 | 42 | echo '==================================> AFTER_SUCCESS' 43 | 44 | . $DRONE_BUILD_DIR/.drone/after-success.sh 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /.drone/b5847f804b-a16f359ef1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | export TRAVIS_BUILD_DIR=$(pwd) 5 | export DRONE_BUILD_DIR=$(pwd) 6 | export TRAVIS_BRANCH=$DRONE_BRANCH 7 | export VCS_COMMIT_ID=$DRONE_COMMIT 8 | export GIT_COMMIT=$DRONE_COMMIT 9 | export REPO_NAME=$DRONE_REPO 10 | export PATH=~/.local/bin:/usr/local/bin:$PATH 11 | 12 | echo '==================================> BEFORE_INSTALL' 13 | 14 | . .drone/before-install.sh 15 | 16 | echo '==================================> INSTALL' 17 | 18 | git clone https://github.com/boostorg/boost-ci.git boost-ci 19 | cp -pr boost-ci/ci boost-ci/.codecov.yml . 20 | 21 | if [ "$TRAVIS_OS_NAME" == "osx" ]; then 22 | unset -f cd 23 | fi 24 | 25 | export SELF=`basename $REPO_NAME` 26 | export BOOST_CI_TARGET_BRANCH="$TRAVIS_BRANCH" 27 | export BOOST_CI_SRC_FOLDER=$(pwd) 28 | 29 | . ./ci/common_install.sh 30 | 31 | echo '==================================> BEFORE_SCRIPT' 32 | 33 | . $DRONE_BUILD_DIR/.drone/before-script.sh 34 | 35 | echo '==================================> SCRIPT' 36 | 37 | mkdir $BOOST_ROOT/__build_cmake__ && cd $BOOST_ROOT/__build_cmake__ 38 | git submodule update --init ../tools/cmake 39 | cmake .. -DBOOST_ENABLE_CMAKE=ON -DBOOST_INCLUDE_LIBRARIES=signals2 -DBOOST_SIGNALS2_INCLUDE_EXAMPLES=ON 40 | cmake --build . 41 | run-parts $BOOST_ROOT/__build_cmake__/stage/bin/ 42 | 43 | echo '==================================> AFTER_SUCCESS' 44 | 45 | . $DRONE_BUILD_DIR/.drone/after-success.sh 46 | -------------------------------------------------------------------------------- /test/dead_slot_test.cpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals library 2 | 3 | // Copyright (C) Douglas Gregor 2001-2006. Use, modification and 4 | // distribution is subject to the Boost Software License, Version 5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | // For more information, see http://www.boost.org 9 | 10 | #include 11 | #include 12 | #include 13 | #define BOOST_TEST_MODULE dead_slot_test 14 | #include 15 | 16 | using namespace boost::placeholders; 17 | 18 | typedef boost::signals2::signal sig_type; 19 | 20 | class with_constant { 21 | public: 22 | with_constant(int c) : constant(c) {} 23 | 24 | int add(int i) { return i + constant; } 25 | 26 | private: 27 | int constant; 28 | }; 29 | 30 | void do_delayed_connect(boost::shared_ptr &wc, 31 | sig_type& sig, 32 | sig_type::slot_type slot) 33 | { 34 | // Should invalidate the slot, so that we cannot connect to it 35 | wc.reset(); 36 | 37 | boost::signals2::connection c = sig.connect(slot); 38 | BOOST_CHECK(!c.connected()); 39 | } 40 | 41 | BOOST_AUTO_TEST_CASE(test_main) 42 | { 43 | sig_type s1; 44 | boost::shared_ptr wc1(new with_constant(7)); 45 | 46 | do_delayed_connect(wc1, s1, sig_type::slot_type(&with_constant::add, wc1.get(), _1).track(wc1)); 47 | } 48 | -------------------------------------------------------------------------------- /doc/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Copyright 2005 Daniel James. 2 | # Copyright 2009 Frank Mori Hess. 3 | # 4 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | using boostbook ; 8 | 9 | boostbook standalone : signals.xml : 10 | hello_world_def_code_snippet.xml 11 | hello_world_def_code_snippet.xml 12 | 13 | boost.root=../../../.. 14 | # navig.graphics=1 15 | 16 | # chunk.first.sections=1 17 | # chunk.section.depth=2 18 | # generate.section.toc.level=2 19 | # toc.section.depth=1 20 | # toc.max.depth=1 21 | 22 | # boost.compact.typedef=0 23 | # boost.compact.function=0 24 | # boost.compact.enum=0 25 | ; 26 | 27 | import snippet-extractor ; 28 | 29 | exe snippet_extractor : snippet_extractor.cpp : release ; 30 | 31 | make hello_world_def_code_snippet.xml 32 | : [ glob ../example/*.cpp ] 33 | : snippet-extractor.extract-snippets 34 | : .//snippet_extractor 35 | ; 36 | 37 | ############################################################################### 38 | alias boostdoc 39 | : signals.xml 40 | : 41 | : 42 | : hello_world_def_code_snippet.xml 43 | hello_world_def_code_snippet.xml ; 44 | explicit boostdoc ; 45 | alias boostrelease ; 46 | explicit boostrelease ; 47 | -------------------------------------------------------------------------------- /test/signal_type_test.cpp: -------------------------------------------------------------------------------- 1 | // Tests for boost::signals2::signal_type 2 | 3 | // Copyright Frank Mori Hess 2009. 4 | // Distributed under the Boost Software License, Version 5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | // See http://www.boost.org/libs/signals2 for library home page. 9 | 10 | #include 11 | #define BOOST_TEST_MODULE signal_type_test 12 | #include 13 | 14 | namespace bs2 = boost::signals2; 15 | 16 | BOOST_AUTO_TEST_CASE(test_main) 17 | { 18 | { 19 | bs2::signal_type::type mysig; 20 | bs2::signal mysig2; 21 | BOOST_CHECK(typeid(mysig) == typeid(mysig2)); 22 | } 23 | 24 | { 25 | bs2::signal_type >::type mysig; 26 | bs2::signal > mysig2; 27 | BOOST_CHECK(typeid(mysig) == typeid(mysig2)); 28 | } 29 | 30 | { 31 | using namespace bs2::keywords; 32 | bs2::signal_type >, group_type >::type mysig; 33 | bs2::signal, float, std::less > mysig2; 34 | BOOST_CHECK(typeid(mysig) == typeid(mysig2)); 35 | } 36 | 37 | { 38 | using namespace bs2::keywords; 39 | bs2::signal_type >::type mysig; 40 | bs2::signal mysig2; 41 | BOOST_CHECK(typeid(mysig) == typeid(mysig2)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /doc/reference/reference.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 11 | 13 |
14 | 15 | Including the "boost/signals2.hpp" header pulls in all the other headers of the Signals2 16 | library. It is provided as a convenience. 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | -------------------------------------------------------------------------------- /example/postconstructor_ex1.cpp: -------------------------------------------------------------------------------- 1 | // Minimal example of defining a postconstructor for a class which 2 | // uses boost::signals2::deconstruct as its factory function. 3 | // 4 | // Copyright Frank Mori Hess 2009. 5 | 6 | // Use, modification and 7 | // distribution is subject to the Boost Software License, Version 8 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // For more information, see http://www.boost.org 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace bs2 = boost::signals2; 17 | 18 | namespace mynamespace 19 | { 20 | class X 21 | { 22 | public: 23 | /* This adl_postconstruct function will be found 24 | via argument-dependent lookup when using boost::signals2::deconstruct. */ 25 | template friend 26 | void adl_postconstruct(const boost::shared_ptr &, X *) 27 | { 28 | std::cout << "world!" << std::endl; 29 | } 30 | private: 31 | friend class bs2::deconstruct_access; // give boost::signals2::deconstruct access to private constructor 32 | // private constructor forces use of boost::signals2::deconstruct to create objects. 33 | X() 34 | { 35 | std::cout << "Hello, "; 36 | } 37 | }; 38 | } 39 | 40 | int main() 41 | { 42 | // adl_postconstruct will be called during implicit conversion of return value to shared_ptr 43 | boost::shared_ptr x = bs2::deconstruct(); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /example/passing_slots.cpp: -------------------------------------------------------------------------------- 1 | // Example program showing passing of slots through an interface. 2 | // 3 | // Copyright Douglas Gregor 2001-2004. 4 | // Copyright Frank Mori Hess 2009. 5 | // 6 | // Use, modification and 7 | // distribution is subject to the Boost Software License, Version 8 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // For more information, see http://www.boost.org 11 | 12 | #include 13 | #include 14 | 15 | //[ passing_slots_defs_code_snippet 16 | // a pretend GUI button 17 | class Button 18 | { 19 | typedef boost::signals2::signal OnClick; 20 | public: 21 | typedef OnClick::slot_type OnClickSlotType; 22 | // forward slots through Button interface to its private signal 23 | boost::signals2::connection doOnClick(const OnClickSlotType & slot); 24 | 25 | // simulate user clicking on GUI button at coordinates 52, 38 26 | void simulateClick(); 27 | private: 28 | OnClick onClick; 29 | }; 30 | 31 | boost::signals2::connection Button::doOnClick(const OnClickSlotType & slot) 32 | { 33 | return onClick.connect(slot); 34 | } 35 | 36 | void Button::simulateClick() 37 | { 38 | onClick(52, 38); 39 | } 40 | 41 | void printCoordinates(long x, long y) 42 | { 43 | std::cout << "(" << x << ", " << y << ")\n"; 44 | } 45 | //] 46 | 47 | int main() 48 | { 49 | //[ passing_slots_usage_code_snippet 50 | Button button; 51 | button.doOnClick(&printCoordinates); 52 | button.simulateClick(); 53 | //] 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /example/slot_arguments.cpp: -------------------------------------------------------------------------------- 1 | // Example program for passing arguments from signal invocations to slots. 2 | // 3 | // Copyright Douglas Gregor 2001-2004. 4 | // Copyright Frank Mori Hess 2009. 5 | // 6 | // Use, modification and 7 | // distribution is subject to the Boost Software License, Version 8 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // For more information, see http://www.boost.org 11 | 12 | #include 13 | #include 14 | 15 | //[ slot_arguments_slot_defs_code_snippet 16 | void print_args(float x, float y) 17 | { 18 | std::cout << "The arguments are " << x << " and " << y << std::endl; 19 | } 20 | 21 | void print_sum(float x, float y) 22 | { 23 | std::cout << "The sum is " << x + y << std::endl; 24 | } 25 | 26 | void print_product(float x, float y) 27 | { 28 | std::cout << "The product is " << x * y << std::endl; 29 | } 30 | 31 | void print_difference(float x, float y) 32 | { 33 | std::cout << "The difference is " << x - y << std::endl; 34 | } 35 | 36 | void print_quotient(float x, float y) 37 | { 38 | std::cout << "The quotient is " << x / y << std::endl; 39 | } 40 | //] 41 | 42 | int main() 43 | { 44 | //[ slot_arguments_main_code_snippet 45 | boost::signals2::signal sig; 46 | 47 | sig.connect(&print_args); 48 | sig.connect(&print_sum); 49 | sig.connect(&print_product); 50 | sig.connect(&print_difference); 51 | sig.connect(&print_quotient); 52 | 53 | sig(5., 3.); 54 | //] 55 | return 0; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /include/boost/signals2/predestructible.hpp: -------------------------------------------------------------------------------- 1 | // DEPRECATED in favor of adl_predestruct with deconstruct(). 2 | // A simple framework for creating objects with predestructors. 3 | // The objects must inherit from boost::signals2::predestructible, and 4 | // have their lifetimes managed by 5 | // boost::shared_ptr created with the boost::signals2::deconstruct_ptr() 6 | // function. 7 | // 8 | // Copyright Frank Mori Hess 2007-2008. 9 | // 10 | //Use, modification and 11 | // distribution is subject to the Boost Software License, Version 12 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 13 | // http://www.boost.org/LICENSE_1_0.txt) 14 | 15 | #ifndef BOOST_SIGNALS2_PREDESTRUCTIBLE_HPP 16 | #define BOOST_SIGNALS2_PREDESTRUCTIBLE_HPP 17 | 18 | namespace boost 19 | { 20 | namespace signals2 21 | { 22 | template class predestructing_deleter; 23 | 24 | namespace predestructible_adl_barrier 25 | { 26 | class predestructible 27 | { 28 | protected: 29 | predestructible() {} 30 | public: 31 | template 32 | friend void adl_postconstruct(const shared_ptr &, ...) 33 | {} 34 | friend void adl_predestruct(predestructible *p) 35 | { 36 | p->predestruct(); 37 | } 38 | virtual ~predestructible() {} 39 | virtual void predestruct() = 0; 40 | }; 41 | } // namespace predestructible_adl_barrier 42 | using predestructible_adl_barrier::predestructible; 43 | } 44 | } 45 | 46 | #endif // BOOST_SIGNALS2_PREDESTRUCTIBLE_HPP 47 | -------------------------------------------------------------------------------- /example/ordering_slots.cpp: -------------------------------------------------------------------------------- 1 | // Ordered slots hello world example for Boost.Signals2 2 | // Copyright Douglas Gregor 2001-2004. 3 | // Copyright Frank Mori Hess 2009. 4 | // 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // For more information, see http://www.boost.org 10 | 11 | #include 12 | #include 13 | 14 | struct Hello 15 | { 16 | void operator()() const 17 | { 18 | std::cout << "Hello"; 19 | } 20 | }; 21 | 22 | struct World 23 | { 24 | void operator()() const 25 | { 26 | std::cout << ", World!" << std::endl; 27 | } 28 | }; 29 | 30 | //[ good_morning_def_code_snippet 31 | struct GoodMorning 32 | { 33 | void operator()() const 34 | { 35 | std::cout << "... and good morning!" << std::endl; 36 | } 37 | }; 38 | //] 39 | 40 | int main() 41 | { 42 | //[ hello_world_ordered_code_snippet 43 | boost::signals2::signal sig; 44 | 45 | sig.connect(1, World()); // connect with group 1 46 | sig.connect(0, Hello()); // connect with group 0 47 | //] 48 | 49 | //[ hello_world_ordered_invoke_code_snippet 50 | // by default slots are connected at the end of the slot list 51 | sig.connect(GoodMorning()); 52 | 53 | // slots are invoked this order: 54 | // 1) ungrouped slots connected with boost::signals2::at_front 55 | // 2) grouped slots according to ordering of their groups 56 | // 3) ungrouped slots connected with boost::signals2::at_back 57 | sig(); 58 | //] 59 | 60 | return 0; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /test/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Boost.Signals2 Library 2 | 3 | # Copyright Douglas Gregor 2001-2003. 4 | # Copyright Frank Mori Hess 2009. 5 | # Use, modification and 6 | # distribution is subject to the Boost Software License, Version 7 | # 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | # http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | # For more information, see http://www.boost.org 11 | 12 | # bring in rules for testing 13 | import testing ; 14 | 15 | project 16 | : requirements 17 | /boost/signals2//boost_signals2 18 | /boost/test//included 19 | true 20 | msvc-14.0:"/bigobj" 21 | gcc,windows:"-Wa,-mbig-obj" 22 | # /boost/test//boost_unit_test_framework 23 | # static 24 | ; 25 | 26 | rule thread-run ( sources ) 27 | { 28 | return 29 | [ run $(sources) : : : /boost/thread//boost_thread 30 | multi ] 31 | ; 32 | } 33 | 34 | { 35 | test-suite signals2 36 | : 37 | [ run connection_test.cpp ] 38 | [ run dead_slot_test.cpp ] 39 | [ run deadlock_regression_test.cpp ] 40 | [ run deconstruct_test.cpp ] 41 | [ run deletion_test.cpp ] 42 | [ thread-run mutex_test.cpp ] 43 | [ run ordering_test.cpp ] 44 | [ run regression_test.cpp ] 45 | [ run shared_connection_block_test.cpp ] 46 | [ run signal_n_test.cpp ] 47 | [ run signal_test.cpp ] 48 | [ run signal_type_test.cpp ] 49 | [ run slot_compile_test.cpp ] 50 | [ thread-run threading_models_test.cpp ] 51 | [ run trackable_test.cpp ] 52 | [ run track_test.cpp ] 53 | ; 54 | } 55 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/preprocessed_arg_type_template.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Frank Mori Hess 2009 2 | // 3 | // Use, modification and 4 | // distribution is subject to the Boost Software License, Version 5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | // For more information, see http://www.boost.org 9 | 10 | // This file is included iteratively, and should not be protected from multiple inclusion 11 | 12 | #define BOOST_SIGNALS2_NUM_ARGS BOOST_PP_ITERATION() 13 | 14 | namespace boost 15 | { 16 | namespace signals2 17 | { 18 | namespace detail 19 | { 20 | template 22 | class BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS); 23 | 24 | // template class preprocessed_arg_typeN{...} ... 25 | #define BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_CLASS_TEMPLATE_SPECIALIZATION(z, n, data) \ 26 | template \ 27 | class BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) \ 29 | { \ 30 | public: \ 31 | typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) type; \ 32 | }; 33 | BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_CLASS_TEMPLATE_SPECIALIZATION, ~) 34 | 35 | } // namespace detail 36 | } // namespace signals2 37 | } // namespace boost 38 | 39 | #undef BOOST_SIGNALS2_NUM_ARGS 40 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/variadic_arg_type.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Frank Mori Hess 2009 2 | // 3 | // Use, modification and 4 | // distribution is subject to the Boost Software License, Version 5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | // For more information, see http://www.boost.org 9 | 10 | #ifndef BOOST_SIGNALS2_DETAIL_VARIADIC_ARG_TYPE_HPP 11 | #define BOOST_SIGNALS2_DETAIL_VARIADIC_ARG_TYPE_HPP 12 | 13 | #include 14 | 15 | namespace boost 16 | { 17 | namespace signals2 18 | { 19 | namespace detail 20 | { 21 | template class variadic_arg_type; 22 | 23 | template class variadic_arg_type<0, T, Args...> 24 | { 25 | public: 26 | typedef T type; 27 | }; 28 | 29 | template class variadic_arg_type 30 | { 31 | public: 32 | typedef typename variadic_arg_type::type type; 33 | }; 34 | 35 | template 36 | struct std_functional_base 37 | {}; 38 | template 39 | struct std_functional_base 40 | { 41 | typedef T1 argument_type; 42 | }; 43 | template 44 | struct std_functional_base 45 | { 46 | typedef T1 first_argument_type; 47 | typedef T2 second_argument_type; 48 | }; 49 | } // namespace detail 50 | } // namespace signals2 51 | } // namespace boost 52 | 53 | 54 | #endif // BOOST_SIGNALS2_DETAIL_VARIADIC_ARG_TYPE_HPP 55 | -------------------------------------------------------------------------------- /include/boost/signals2/variadic_signal.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | A variadic implementation of variadic boost::signals2::signal, used when variadic 3 | template support is detected in the compiler. 4 | 5 | Author: Frank Mori Hess 6 | Begin: 2009-05-26 7 | */ 8 | // Copyright Frank Mori Hess 2009 9 | // Use, modification and 10 | // distribution is subject to the Boost Software License, Version 11 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 12 | // http://www.boost.org/LICENSE_1_0.txt) 13 | 14 | // For more information, see http://www.boost.org 15 | 16 | #ifndef BOOST_SIGNALS2_VARIADIC_SIGNAL_HPP 17 | #define BOOST_SIGNALS2_VARIADIC_SIGNAL_HPP 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace boost 28 | { 29 | namespace signals2 30 | { 31 | namespace detail 32 | { 33 | template class variadic_extended_signature; 34 | // partial template specialization 35 | template 36 | class variadic_extended_signature 37 | { 38 | public: 39 | typedef boost::function function_type; 40 | }; 41 | } // namespace detail 42 | } // namespace signals2 43 | } // namespace boost 44 | 45 | #include 46 | 47 | #endif // BOOST_SIGNALS2_VARIADIC_SIGNAL_HPP 48 | -------------------------------------------------------------------------------- /example/predestructor_example.cpp: -------------------------------------------------------------------------------- 1 | // Minimal example of defining a predestructor for a class which 2 | // uses boost::signals2::deconstruct as its factory function. 3 | // 4 | // Copyright Frank Mori Hess 2009. 5 | 6 | // Use, modification and 7 | // distribution is subject to the Boost Software License, Version 8 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // For more information, see http://www.boost.org 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace bs2 = boost::signals2; 17 | 18 | namespace mynamespace 19 | { 20 | class X 21 | { 22 | public: 23 | ~X() 24 | { 25 | std::cout << "cruel world!" << std::endl; 26 | } 27 | /* This adl_predestruct friend function will be found by 28 | via argument-dependent lookup when using boost::signals2::deconstruct. */ 29 | friend void adl_predestruct(X *) 30 | { 31 | std::cout << "Goodbye, "; 32 | } 33 | /* boost::signals2::deconstruct always requires an adl_postconstruct function 34 | which can be found via argument-dependent, so we define one which does nothing. */ 35 | template friend 36 | void adl_postconstruct(const boost::shared_ptr &, X *) 37 | {} 38 | private: 39 | friend class bs2::deconstruct_access; // give boost::signals2::deconstruct access to private constructor 40 | // private constructor forces use of boost::signals2::deconstruct to create objects. 41 | X() 42 | {} 43 | }; 44 | } 45 | 46 | int main() 47 | { 48 | { 49 | boost::shared_ptr x = bs2::deconstruct(); 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/lwm_pthreads.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // boost/signals2/detail/lwm_pthreads.hpp 3 | // 4 | // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. 5 | // Copyright (c) 2008 Frank Mori Hess 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See 8 | // accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // 11 | 12 | #ifndef BOOST_SIGNALS2_LWM_PTHREADS_HPP 13 | #define BOOST_SIGNALS2_LWM_PTHREADS_HPP 14 | 15 | // MS compatible compilers support #pragma once 16 | 17 | #if defined(_MSC_VER) 18 | # pragma once 19 | #endif 20 | 21 | #include 22 | #include 23 | 24 | namespace boost 25 | { 26 | 27 | namespace signals2 28 | { 29 | 30 | class mutex 31 | { 32 | private: 33 | 34 | pthread_mutex_t m_; 35 | 36 | mutex(mutex const &); 37 | mutex & operator=(mutex const &); 38 | 39 | public: 40 | 41 | mutex() 42 | { 43 | 44 | // HPUX 10.20 / DCE has a nonstandard pthread_mutex_init 45 | 46 | #if defined(__hpux) && defined(_DECTHREADS_) 47 | BOOST_VERIFY(pthread_mutex_init(&m_, pthread_mutexattr_default) == 0); 48 | #else 49 | BOOST_VERIFY(pthread_mutex_init(&m_, 0) == 0); 50 | #endif 51 | } 52 | 53 | ~mutex() 54 | { 55 | BOOST_VERIFY(pthread_mutex_destroy(&m_) == 0); 56 | } 57 | 58 | void lock() 59 | { 60 | BOOST_VERIFY(pthread_mutex_lock(&m_) == 0); 61 | } 62 | 63 | bool try_lock() 64 | { 65 | return pthread_mutex_trylock(&m_) == 0; 66 | } 67 | 68 | void unlock() 69 | { 70 | BOOST_VERIFY(pthread_mutex_unlock(&m_) == 0); 71 | } 72 | }; 73 | 74 | } // namespace signals2 75 | 76 | } // namespace boost 77 | 78 | #endif // #ifndef BOOST_SIGNALS2_LWM_PTHREADS_HPP 79 | -------------------------------------------------------------------------------- /example/postconstructor_ex2.cpp: -------------------------------------------------------------------------------- 1 | // An example of defining a postconstructor for a class which 2 | // uses boost::signals2::deconstruct as its factory function. 3 | // This example expands on the basic postconstructor_ex1.cpp example 4 | // by passing arguments to the constructor and postconstructor. 5 | // 6 | // Copyright Frank Mori Hess 2009. 7 | 8 | // Use, modification and 9 | // distribution is subject to the Boost Software License, Version 10 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 11 | // http://www.boost.org/LICENSE_1_0.txt) 12 | // For more information, see http://www.boost.org 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace bs2 = boost::signals2; 21 | 22 | namespace mynamespace 23 | { 24 | class Y 25 | { 26 | public: 27 | /* This adl_postconstruct function will be found 28 | via argument-dependent lookup when using boost::signals2::deconstruct. */ 29 | template friend 30 | void adl_postconstruct(const boost::shared_ptr &, Y *y, const std::string &text) 31 | { 32 | y->_text_stream << text; 33 | } 34 | void print() const 35 | { 36 | std::cout << _text_stream.str() << std::endl; 37 | } 38 | private: 39 | friend class bs2::deconstruct_access; // give boost::signals2::deconstruct access to private constructor 40 | // private constructor forces use of boost::signals2::deconstruct to create objects. 41 | Y(const std::string &text) 42 | { 43 | _text_stream << text; 44 | } 45 | 46 | std::ostringstream _text_stream; 47 | }; 48 | } 49 | 50 | int main() 51 | { 52 | boost::shared_ptr y = bs2::deconstruct("Hello, ").postconstruct("world!"); 53 | y->print(); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /include/boost/signals2/postconstructible.hpp: -------------------------------------------------------------------------------- 1 | // DEPRECATED in favor of adl_postconstruct with deconstruct(). 2 | // A simple framework for creating objects with postconstructors. 3 | // The objects must inherit from boost::signals2::postconstructible, and 4 | // have their lifetimes managed by 5 | // boost::shared_ptr created with the boost::signals2::deconstruct_ptr() 6 | // function. 7 | // 8 | // Copyright Frank Mori Hess 2007-2008. 9 | // 10 | // Use, modification and 11 | // distribution is subject to the Boost Software License, Version 12 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 13 | // http://www.boost.org/LICENSE_1_0.txt) 14 | 15 | #ifndef BOOST_SIGNALS2_POSTCONSTRUCTIBLE_HPP 16 | #define BOOST_SIGNALS2_POSTCONSTRUCTIBLE_HPP 17 | 18 | namespace boost 19 | { 20 | template class shared_ptr; 21 | 22 | namespace signals2 23 | { 24 | namespace postconstructible_adl_barrier 25 | { 26 | class postconstructible; 27 | } 28 | namespace detail 29 | { 30 | void do_postconstruct(const boost::signals2::postconstructible_adl_barrier::postconstructible *ptr); 31 | } // namespace detail 32 | 33 | namespace postconstructible_adl_barrier 34 | { 35 | class postconstructible 36 | { 37 | public: 38 | friend void detail::do_postconstruct(const postconstructible *ptr); 39 | template 40 | friend void adl_postconstruct(const shared_ptr &, postconstructible *p) 41 | { 42 | p->postconstruct(); 43 | } 44 | protected: 45 | postconstructible() {} 46 | virtual ~postconstructible() {} 47 | virtual void postconstruct() = 0; 48 | }; 49 | } // namespace postconstructible_adl_barrier 50 | using postconstructible_adl_barrier::postconstructible; 51 | 52 | } 53 | } 54 | 55 | #endif // BOOST_SIGNALS2_POSTCONSTRUCTIBLE_HPP 56 | -------------------------------------------------------------------------------- /test/invocation_benchmark.cpp: -------------------------------------------------------------------------------- 1 | /* multi-threaded signal invocation benchmark */ 2 | 3 | // Copyright Frank Mori Hess 2007-2008. 4 | // Distributed under the Boost Software License, Version 5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace boost::placeholders; 15 | 16 | typedef boost::signals2::signal signal_type; 17 | 18 | void myslot() 19 | { 20 | /* std::cout << __FUNCTION__ << std::endl; 21 | sleep(1);*/ 22 | } 23 | 24 | void thread_initial(signal_type *signal, unsigned num_invocations) 25 | { 26 | unsigned i; 27 | for(i = 0; i < num_invocations; ++i) 28 | { 29 | (*signal)(); 30 | } 31 | } 32 | 33 | int main(int argc, const char **argv) 34 | { 35 | if(argc < 3) 36 | { 37 | std::cerr << "usage: " << argv[0] << " " << std::endl; 38 | return -1; 39 | } 40 | static const unsigned num_threads = std::strtol(argv[1], 0, 0); 41 | static const unsigned num_connections = std::strtol(argv[2], 0, 0); 42 | boost::thread_group threads; 43 | signal_type sig; 44 | 45 | std::cout << "Connecting " << num_connections << " connections to signal.\n"; 46 | unsigned i; 47 | for(i = 0; i < num_connections; ++i) 48 | { 49 | sig.connect(&myslot); 50 | } 51 | const unsigned num_slot_invocations = 1000000; 52 | const unsigned signal_invocations_per_thread = num_slot_invocations / (num_threads * num_connections); 53 | std::cout << "Launching " << num_threads << " thread(s) to invoke signal " << signal_invocations_per_thread << " times per thread.\n"; 54 | for(i = 0; i < num_threads; ++i) 55 | { 56 | threads.create_thread(boost::bind(&thread_initial, &sig, signal_invocations_per_thread)); 57 | } 58 | threads.join_all(); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /include/boost/signals2/optional_last_value.hpp: -------------------------------------------------------------------------------- 1 | // optional_last_value function object (documented as part of Boost.Signals2) 2 | 3 | // Copyright Frank Mori Hess 2007-2008. 4 | // Copyright Douglas Gregor 2001-2003. 5 | // Distributed under the Boost Software License, Version 6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/signals2 for library home page. 10 | 11 | #ifndef BOOST_SIGNALS2_OPTIONAL_LAST_VALUE_HPP 12 | #define BOOST_SIGNALS2_OPTIONAL_LAST_VALUE_HPP 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace boost { 20 | namespace signals2 { 21 | 22 | template 23 | class optional_last_value 24 | { 25 | public: 26 | typedef optional result_type; 27 | 28 | template 29 | optional operator()(InputIterator first, InputIterator last) const 30 | { 31 | optional value; 32 | while (first != last) 33 | { 34 | BOOST_TRY 35 | { 36 | value = boost::move_if_not_lvalue_reference(*first); 37 | } 38 | BOOST_CATCH(const expired_slot &) {} 39 | BOOST_CATCH_END 40 | ++first; 41 | } 42 | return value; 43 | } 44 | }; 45 | 46 | template<> 47 | class optional_last_value 48 | { 49 | public: 50 | typedef void result_type; 51 | template 52 | result_type operator()(InputIterator first, InputIterator last) const 53 | { 54 | while (first != last) 55 | { 56 | BOOST_TRY 57 | { 58 | *first; 59 | } 60 | BOOST_CATCH(const expired_slot &) {} 61 | BOOST_CATCH_END 62 | ++first; 63 | } 64 | return; 65 | } 66 | }; 67 | } // namespace signals2 68 | } // namespace boost 69 | #endif // BOOST_SIGNALS2_OPTIONAL_LAST_VALUE_HPP 70 | -------------------------------------------------------------------------------- /doc/reference/dummy_mutex.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | noncopyable 18 | 19 | Fake mutex which does nothing. 20 | 21 | You may wish to use the dummy_mutex class for the Mutex 22 | template type of your signals if you are not concerned about thread safety. 23 | This may give slightly faster 24 | performance, since dummy_mutex performs no actual locking. 25 | 26 | 27 | 28 | 29 | void 30 | 31 | No effect. 32 | 33 | 34 | 35 | 36 | bool 37 | 38 | No effect. 39 | 40 | 41 | true. 42 | 43 | 44 | void 45 | 46 | No effect. 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
55 | -------------------------------------------------------------------------------- /include/boost/signals2/shared_connection_block.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Frank Mori Hess 2007-2008. 4 | // Use, modification and 5 | // distribution is subject to the Boost Software License, Version 6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // For more information, see http://www.boost.org 10 | 11 | #ifndef BOOST_SIGNALS2_SHARED_CONNECTION_BLOCK_HPP 12 | #define BOOST_SIGNALS2_SHARED_CONNECTION_BLOCK_HPP 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace boost 19 | { 20 | namespace signals2 21 | { 22 | class shared_connection_block 23 | { 24 | public: 25 | shared_connection_block(const signals2::connection &conn = signals2::connection(), 26 | bool initially_blocked = true): 27 | _weak_connection_body(conn._weak_connection_body) 28 | { 29 | if(initially_blocked) block(); 30 | } 31 | void block() 32 | { 33 | if(blocking()) return; 34 | boost::shared_ptr connection_body(_weak_connection_body.lock()); 35 | if(connection_body == 0) 36 | { 37 | // Make _blocker non-empty so the blocking() method still returns the correct value 38 | // after the connection has expired. 39 | _blocker.reset(static_cast(0)); 40 | return; 41 | } 42 | _blocker = connection_body->get_blocker(); 43 | } 44 | void unblock() 45 | { 46 | _blocker.reset(); 47 | } 48 | bool blocking() const 49 | { 50 | shared_ptr empty; 51 | return _blocker < empty || empty < _blocker; 52 | } 53 | signals2::connection connection() const 54 | { 55 | return signals2::connection(_weak_connection_body); 56 | } 57 | private: 58 | boost::weak_ptr _weak_connection_body; 59 | shared_ptr _blocker; 60 | }; 61 | } 62 | } // end namespace boost 63 | 64 | #endif // BOOST_SIGNALS2_SHARED_CONNECTION_BLOCK_HPP 65 | -------------------------------------------------------------------------------- /include/boost/signals2/trackable.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Frank Mori Hess 2007,2009. 4 | // Copyright Timmo Stange 2007. 5 | // Copyright Douglas Gregor 2001-2004. Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // Compatibility class to ease porting from the original 11 | // Boost.Signals library. However, 12 | // boost::signals2::trackable is NOT thread-safe. 13 | 14 | // For more information, see http://www.boost.org 15 | 16 | #ifndef BOOST_SIGNALS2_TRACKABLE_HPP 17 | #define BOOST_SIGNALS2_TRACKABLE_HPP 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | namespace boost { 24 | namespace signals2 { 25 | namespace detail 26 | { 27 | class tracked_objects_visitor; 28 | 29 | // trackable_pointee is used to identify the tracked shared_ptr 30 | // originating from the signals2::trackable class. These tracked 31 | // shared_ptr are special in that we shouldn't bother to 32 | // increment their use count during signal invocation, since 33 | // they don't actually control the lifetime of the 34 | // signals2::trackable object they are associated with. 35 | class trackable_pointee 36 | {}; 37 | } 38 | class trackable { 39 | protected: 40 | trackable(): _tracked_ptr(static_cast(0)) {} 41 | trackable(const trackable &): _tracked_ptr(static_cast(0)) {} 42 | trackable& operator=(const trackable &) 43 | { 44 | return *this; 45 | } 46 | ~trackable() {} 47 | private: 48 | friend class detail::tracked_objects_visitor; 49 | weak_ptr get_weak_ptr() const 50 | { 51 | return _tracked_ptr; 52 | } 53 | 54 | shared_ptr _tracked_ptr; 55 | }; 56 | } // end namespace signals2 57 | } // end namespace boost 58 | 59 | #endif // BOOST_SIGNALS2_TRACKABLE_HPP 60 | -------------------------------------------------------------------------------- /include/boost/signals2/signal.hpp: -------------------------------------------------------------------------------- 1 | // A thread-safe version of Boost.Signals. 2 | 3 | // Copyright Frank Mori Hess 2007-2009 4 | // 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // For more information, see http://www.boost.org 11 | 12 | #ifndef BOOST_SIGNALS2_SIGNAL_HPP 13 | #define BOOST_SIGNALS2_SIGNAL_HPP 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES 36 | #include 37 | #else 38 | #include 39 | #endif 40 | 41 | namespace boost 42 | { 43 | namespace signals2 44 | { 45 | // free swap function, findable by ADL 46 | template 53 | void swap( 54 | signal &sig1, 55 | signal &sig2) BOOST_NOEXCEPT 56 | { 57 | sig1.swap(sig2); 58 | } 59 | } 60 | } 61 | 62 | #endif // BOOST_SIGNALS2_SIGNAL_HPP 63 | -------------------------------------------------------------------------------- /doc/signals.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 11 | 14 | 15 | 16 | Douglas 17 | Gregor 18 | 19 | 20 | 21 | Frank 22 | Mori 23 | Hess 24 | 25 | 26 | 27 | 28 | 2001 29 | 2002 30 | 2003 31 | 2004 32 | Douglas Gregor 33 | 34 | 35 | 2007 36 | 2008 37 | 2009 38 | Frank Mori Hess 39 | 40 | 41 | 42 | Distributed under the Boost 43 | Software License, Version 1.0. (See accompanying file 44 | LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 46 | 47 | 48 | Managed signals & slots callback implementation 49 | 50 | 51 | 52 | Boost.Signals2 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /doc/introduction.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 11 |
12 | Introduction 13 | 14 | The Boost.Signals2 library is an implementation of a managed 15 | signals and slots system. Signals represent callbacks with multiple 16 | targets, and are also called publishers or events in similar 17 | systems. Signals are connected to some set of slots, which are 18 | callback receivers (also called event targets or subscribers), which 19 | are called when the signal is "emitted." 20 | 21 | Signals and slots are managed, in that signals and slots (or, 22 | more properly, objects that occur as part of the slots) can track 23 | connections and are capable of automatically disconnecting signal/slot 24 | connections when either is destroyed. This enables the user to make 25 | signal/slot connections without expending a great effort to manage the 26 | lifetimes of those connections with regard to the lifetimes of all 27 | objects involved. 28 | 29 | When signals are connected to multiple slots, there is a 30 | question regarding the relationship between the return values of the 31 | slots and the return value of the signals. Boost.Signals2 allows the 32 | user to specify the manner in which multiple return values are 33 | combined. 34 | 35 |
36 | Signals2 37 | This documentation describes a thread-safe variant of the 38 | original Boost.Signals library. There have been some changes to 39 | the interface to support thread-safety, mostly with respect to 40 | automatic connection management. This implementation was written by 41 | Frank Mori Hess. Acknowledgements are also due to Timmo Stange, Peter 42 | Dimov, and Tony Van Eerd for ideas and feedback, and to Douglas Gregor 43 | for the original version of Boost.Signals this effort was based on. 44 | 45 |
46 |
47 | -------------------------------------------------------------------------------- /doc/reference/slot_base.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | Base class for slots. 17 | 18 | 19 | 20 | 21 | 22 | 23 | std::vector<implementation-detail> 24 | 25 | 26 | 27 | 28 | bool 29 | true if any tracked object has expired. 30 | 31 | 32 | locked_container_type 33 | A container holding shared_ptrs to each of the slot's tracked objects. As long 34 | as the returned container is kept in scope, none of the slot's tracked objects can expire. 35 | expired_slot if any of the slot's tracked objects have expired. 36 | 37 | 38 | 39 | 40 | bad_weak_ptr 41 | Indicates at least one of a slot's tracked objects has expired. 42 | The expired_slot exception is thrown to indicate at least one of 43 | a slot's tracked objects has expired. 44 | 45 | 46 | const char * 47 | 48 | 49 | 50 | 51 |
52 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/result_type_wrapper.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Douglas Gregor 2001-2004. 4 | // Copyright Frank Mori Hess 2007. Use, modification and 5 | // distribution is subject to the Boost Software License, Version 6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // For more information, see http://www.boost.org 10 | 11 | #ifndef BOOST_SIGNALS2_RESULT_TYPE_WRAPPER_HPP 12 | #define BOOST_SIGNALS2_RESULT_TYPE_WRAPPER_HPP 13 | 14 | #include 15 | 16 | namespace boost { 17 | namespace signals2 { 18 | namespace detail { 19 | // A placeholder for void on compilers that don't support void returns 20 | struct void_type {}; 21 | 22 | // Replaces void with void_type 23 | template 24 | struct nonvoid { 25 | typedef R type; 26 | }; 27 | template<> 28 | struct nonvoid { 29 | typedef void_type type; 30 | }; 31 | 32 | // Replaces void with void_type only if compiler doesn't support void returns 33 | template 34 | struct result_type_wrapper { 35 | typedef R type; 36 | }; 37 | #ifdef BOOST_NO_VOID_RETURNS 38 | template<> 39 | struct result_type_wrapper { 40 | typedef void_type type; 41 | }; 42 | #endif 43 | 44 | // specialization deals with possible void return from combiners 45 | template class combiner_invoker 46 | { 47 | public: 48 | typedef R result_type; 49 | template 50 | result_type operator()(Combiner &combiner, 51 | InputIterator first, InputIterator last) const 52 | { 53 | return combiner(first, last); 54 | } 55 | }; 56 | template<> class combiner_invoker 57 | { 58 | public: 59 | typedef result_type_wrapper::type result_type; 60 | template 61 | result_type operator()(Combiner &combiner, 62 | InputIterator first, InputIterator last) const 63 | { 64 | combiner(first, last); 65 | return result_type(); 66 | } 67 | }; 68 | } // end namespace detail 69 | } // end namespace signals2 70 | } // end namespace boost 71 | 72 | #endif // BOOST_SIGNALS2_RESULT_TYPE_WRAPPER_HPP 73 | -------------------------------------------------------------------------------- /doc/faq.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 11 |
12 | Frequently Asked Questions 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Don't noncopyable signal semantics mean that a class 21 | with a signal member will be noncopyable as well? 22 | 23 | 24 | No. The compiler will not be able to generate a copy 25 | constructor or copy assignment operator for your class if it 26 | has a signal as a member, but you are free to write your own 27 | copy constructor and/or copy assignment operator. Just don't 28 | try to copy the signal. 29 | 30 | 31 | 32 | 33 | Is Boost.Signals2 thread-safe? 34 | 35 | 36 | 37 | Yes, as long as the Mutex template parameter is not set to 38 | a fake mutex type like boost::signals2::dummy_mutex. 39 | Also, if your slots depend on objects which may be destroyed concurrently 40 | with signal invocation, you will need to use automatic connection management. 41 | That is, the objects will need to be owned by 42 | shared_ptr and passed to the slot's 43 | track() method before the slot is connected. 44 | The signals2::trackable scheme of automatic connection management 45 | is NOT thread-safe, and is only provided to ease porting of single-threaded 46 | code from Boost.Signals to Boost.Signals2. 47 | 48 | See the documentation section on thread-safety 49 | for more information. 50 | 51 | 52 | 53 | 54 |
55 | -------------------------------------------------------------------------------- /include/boost/signals2/last_value.hpp: -------------------------------------------------------------------------------- 1 | // last_value function object (documented as part of Boost.Signals) 2 | 3 | // Copyright Frank Mori Hess 2007. 4 | // Copyright Douglas Gregor 2001-2003. Use, modification and 5 | // distribution is subject to the Boost Software License, Version 6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // For more information, see http://www.boost.org 10 | 11 | #ifndef BOOST_SIGNALS2_LAST_VALUE_HPP 12 | #define BOOST_SIGNALS2_LAST_VALUE_HPP 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace boost { 22 | namespace signals2 { 23 | 24 | // no_slots_error is thrown when we are unable to generate a return value 25 | // due to no slots being connected to the signal. 26 | class no_slots_error: public std::exception 27 | { 28 | public: 29 | virtual const char* what() const throw() {return "boost::signals2::no_slots_error";} 30 | }; 31 | 32 | template 33 | class last_value { 34 | public: 35 | typedef T result_type; 36 | 37 | template 38 | T operator()(InputIterator first, InputIterator last) const 39 | { 40 | if(first == last) 41 | { 42 | boost::throw_exception(no_slots_error()); 43 | } 44 | optional value; 45 | while (first != last) 46 | { 47 | BOOST_TRY 48 | { 49 | value = boost::move_if_not_lvalue_reference(*first); 50 | } 51 | BOOST_CATCH(const expired_slot &) {} 52 | BOOST_CATCH_END 53 | ++first; 54 | } 55 | if(value) return value.get(); 56 | boost::throw_exception(no_slots_error()); 57 | } 58 | }; 59 | 60 | template<> 61 | class last_value { 62 | public: 63 | typedef void result_type; 64 | template 65 | result_type operator()(InputIterator first, InputIterator last) const 66 | { 67 | while (first != last) 68 | { 69 | BOOST_TRY 70 | { 71 | *first; 72 | } 73 | BOOST_CATCH(const expired_slot &) {} 74 | BOOST_CATCH_END 75 | ++first; 76 | } 77 | return; 78 | } 79 | }; 80 | } // namespace signals2 81 | } // namespace boost 82 | #endif // BOOST_SIGNALS2_LAST_VALUE_HPP 83 | -------------------------------------------------------------------------------- /test/threading_models_test.cpp: -------------------------------------------------------------------------------- 1 | // thread_safe_signals library 2 | // basic test for alternate threading models 3 | 4 | // Copyright Frank Mori Hess 2008 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // For more information, see http://www.boost.org 11 | 12 | #include 13 | #define BOOST_TEST_MODULE threading_models_test 14 | #include 15 | #include 16 | 17 | // combiner that returns the number of slots invoked 18 | struct slot_counter { 19 | typedef unsigned result_type; 20 | template 21 | unsigned operator()(InputIterator first, InputIterator last) const 22 | { 23 | unsigned count = 0; 24 | for (; first != last; ++first) 25 | { 26 | try 27 | { 28 | *first; 29 | ++count; 30 | } 31 | catch(const boost::bad_weak_ptr &) 32 | {} 33 | } 34 | return count; 35 | } 36 | }; 37 | 38 | void myslot() 39 | { 40 | } 41 | 42 | template 43 | void simple_test() 44 | { 45 | signal_type sig; 46 | sig.connect(typename signal_type::slot_type(&myslot)); 47 | BOOST_CHECK(sig() == 1); 48 | sig.disconnect(&myslot); 49 | BOOST_CHECK(sig() == 0); 50 | } 51 | 52 | class recursion_checking_dummy_mutex 53 | { 54 | int recursion_count; 55 | public: 56 | recursion_checking_dummy_mutex(): recursion_count(0) 57 | {} 58 | void lock() 59 | { 60 | BOOST_REQUIRE(recursion_count == 0); 61 | ++recursion_count; 62 | } 63 | bool try_lock() 64 | { 65 | lock(); 66 | return true; 67 | } 68 | void unlock() 69 | { 70 | --recursion_count; 71 | BOOST_REQUIRE(recursion_count == 0); 72 | } 73 | }; 74 | 75 | BOOST_AUTO_TEST_CASE(test_main) 76 | { 77 | typedef boost::signals2::signal, boost::function, 78 | boost::function, recursion_checking_dummy_mutex> sig0_rc_type; 79 | simple_test(); 80 | typedef boost::signals2::signal, boost::function, 81 | boost::function, boost::mutex> sig0_mt_type; 82 | simple_test(); 83 | typedef boost::signals2::signal, boost::function, 84 | boost::function, boost::signals2::dummy_mutex> sig0_st_type; 85 | simple_test(); 86 | } 87 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/signals_common.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals library 2 | 3 | // Copyright Douglas Gregor 2001-2004. 4 | // Copyright Frank Mori Hess 2007. Use, modification and 5 | // distribution is subject to the Boost Software License, Version 6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // For more information, see http://www.boost.org 10 | 11 | #ifndef BOOST_SIGNALS2_SIGNALS_COMMON_HPP 12 | #define BOOST_SIGNALS2_SIGNALS_COMMON_HPP 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace boost { 21 | namespace signals2 { 22 | namespace detail { 23 | // Determine if the given type T is a signal 24 | template 25 | class is_signal: public mpl::bool_::value> 26 | {}; 27 | 28 | // A slot can be a signal, a reference to a function object, or a 29 | // function object. 30 | struct signal_tag {}; 31 | struct reference_tag {}; 32 | struct value_tag {}; 33 | 34 | // Classify the given slot as a signal, a reference-to-slot, or a 35 | // standard slot 36 | template 37 | class get_slot_tag { 38 | typedef typename mpl::if_, 39 | signal_tag, value_tag>::type signal_or_value; 40 | public: 41 | typedef typename mpl::if_, 42 | reference_tag, 43 | signal_or_value>::type type; 44 | }; 45 | 46 | // Get the slot so that it can be copied 47 | template 48 | typename F::weak_signal_type 49 | get_invocable_slot(const F &signal, signal_tag) 50 | { return typename F::weak_signal_type(signal); } 51 | 52 | template 53 | const F& 54 | get_invocable_slot(const F& f, reference_tag) 55 | { return f; } 56 | 57 | template 58 | const F& 59 | get_invocable_slot(const F& f, value_tag) 60 | { return f; } 61 | 62 | // Determines the type of the slot - is it a signal, a reference to a 63 | // slot or just a normal slot. 64 | template 65 | typename get_slot_tag::type 66 | tag_type(const F&) 67 | { 68 | typedef typename get_slot_tag::type 69 | the_tag_type; 70 | the_tag_type tag = the_tag_type(); 71 | return tag; 72 | } 73 | } // end namespace detail 74 | } // end namespace signals2 75 | } // end namespace boost 76 | 77 | #endif // BOOST_SIGNALS2_SIGNALS_COMMON_HPP 78 | -------------------------------------------------------------------------------- /doc/snippet_extractor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Frank Mori Hess 2009. 2 | // 3 | // Quick hack to extract code snippets from example programs, so 4 | // they can be included into boostbook. 5 | // 6 | // Use, modification and 7 | // distribution is subject to the Boost Software License, Version 8 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc, const char *argv[]) 17 | { 18 | if(argc < 3) 19 | { 20 | std::cerr << "Too few arguments: need output directory and input file name(s).\n"; 21 | return -1; 22 | } 23 | static const std::string output_directory = argv[1]; 24 | static const int num_files = argc - 2; 25 | int i; 26 | for(i = 0; i < num_files; ++i) 27 | { 28 | const std::string file_name = argv[2 + i]; 29 | std::cout << "opening file: " << file_name << std::endl; 30 | std::ifstream infile(file_name.c_str()); 31 | bool inside_snippet = false; 32 | std::ofstream snippet_out_file; 33 | while(infile.good()) 34 | { 35 | std::string line; 36 | getline(infile, line); 37 | if(infile.bad()) break; 38 | if(inside_snippet) 39 | { 40 | size_t snippet_end_pos = line.find("//]"); 41 | if(snippet_end_pos == std::string::npos) 42 | { 43 | snippet_out_file << line << "\n"; 44 | }else 45 | { 46 | snippet_out_file << "]]>"; 47 | inside_snippet = false; 48 | std::cout << "done.\n"; 49 | continue; 50 | } 51 | }else 52 | { 53 | size_t snippet_start_pos = line.find("//["); 54 | if(snippet_start_pos == std::string::npos) 55 | { 56 | continue; 57 | }else 58 | { 59 | inside_snippet = true; 60 | std::string snippet_name = line.substr(snippet_start_pos + 3); 61 | std::istringstream snippet_stream(snippet_name); 62 | snippet_stream >> snippet_name; 63 | if(snippet_name == "") 64 | { 65 | throw std::runtime_error("failed to obtain snippet name"); 66 | } 67 | snippet_out_file.close(); 68 | snippet_out_file.clear(); 69 | snippet_out_file.open(std::string(output_directory + "/" + snippet_name + ".xml").c_str()); 70 | snippet_out_file << "(). 3 | // A factory function for creating a shared_ptr that enhances the plain 4 | // shared_ptr constructors by adding support for postconstructors 5 | // and predestructors through the boost::signals2::postconstructible and 6 | // boost::signals2::predestructible base classes. 7 | // 8 | // Copyright Frank Mori Hess 2007-2008. 9 | // 10 | // Use, modification and 11 | // distribution is subject to the Boost Software License, Version 12 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 13 | // http://www.boost.org/LICENSE_1_0.txt) 14 | 15 | #ifndef BOOST_SIGNALS2_DECONSTRUCT_PTR_HPP 16 | #define BOOST_SIGNALS2_DECONSTRUCT_PTR_HPP 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace boost 26 | { 27 | namespace signals2 28 | { 29 | namespace detail 30 | { 31 | inline void do_postconstruct(const postconstructible *ptr) 32 | { 33 | postconstructible *nonconst_ptr = const_cast(ptr); 34 | nonconst_ptr->postconstruct(); 35 | } 36 | inline void do_postconstruct(...) 37 | { 38 | } 39 | inline void do_predestruct(...) 40 | { 41 | } 42 | inline void do_predestruct(const predestructible *ptr) 43 | { 44 | BOOST_TRY 45 | { 46 | predestructible *nonconst_ptr = const_cast(ptr); 47 | nonconst_ptr->predestruct(); 48 | } 49 | BOOST_CATCH(...) 50 | { 51 | BOOST_ASSERT(false); 52 | } 53 | BOOST_CATCH_END 54 | } 55 | } 56 | 57 | template class predestructing_deleter 58 | { 59 | public: 60 | void operator()(const T *ptr) const 61 | { 62 | detail::do_predestruct(ptr); 63 | checked_delete(ptr); 64 | } 65 | }; 66 | 67 | template 68 | shared_ptr deconstruct_ptr(T *ptr) 69 | { 70 | if(ptr == 0) return shared_ptr(ptr); 71 | shared_ptr shared(ptr, boost::signals2::predestructing_deleter()); 72 | detail::do_postconstruct(ptr); 73 | return shared; 74 | } 75 | template 76 | shared_ptr deconstruct_ptr(T *ptr, D deleter) 77 | { 78 | shared_ptr shared(ptr, deleter); 79 | if(ptr == 0) return shared; 80 | detail::do_postconstruct(ptr); 81 | return shared; 82 | } 83 | } 84 | } 85 | 86 | #endif // BOOST_SIGNALS2_DECONSTRUCT_PTR_HPP 87 | -------------------------------------------------------------------------------- /include/boost/signals2/preprocessed_signal.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | A thread-safe version of Boost.Signals. 3 | 4 | Author: Frank Mori Hess 5 | Begin: 2007-01-23 6 | */ 7 | // Copyright Frank Mori Hess 2007-2008 8 | // Use, modification and 9 | // distribution is subject to the Boost Software License, Version 10 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 11 | // http://www.boost.org/LICENSE_1_0.txt) 12 | 13 | // For more information, see http://www.boost.org 14 | 15 | #ifndef BOOST_SIGNALS2_PREPROCESSED_SIGNAL_HPP 16 | #define BOOST_SIGNALS2_PREPROCESSED_SIGNAL_HPP 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define BOOST_PP_ITERATION_LIMITS (0, BOOST_SIGNALS2_MAX_ARGS) 31 | #define BOOST_PP_FILENAME_1 32 | #include BOOST_PP_ITERATE() 33 | 34 | namespace boost 35 | { 36 | namespace signals2 37 | { 38 | template::result_type>, 40 | typename Group = int, 41 | typename GroupCompare = std::less, 42 | typename SlotFunction = function, 43 | typename ExtendedSlotFunction = typename detail::extended_signature::arity, Signature>::function_type, 44 | typename Mutex = mutex > 45 | class signal: public detail::signalN::arity, 46 | Signature, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex>::type 47 | { 48 | private: 49 | typedef typename detail::signalN::arity, 50 | Signature, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex>::type base_type; 51 | public: 52 | signal(const Combiner &combiner_arg = Combiner(), const GroupCompare &group_compare = GroupCompare()): 53 | base_type(combiner_arg, group_compare) 54 | {} 55 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && BOOST_WORKAROUND(BOOST_MSVC, < 1800) 56 | signal(signal && other) BOOST_NOEXCEPT: base_type(std::move(other)) {} 57 | signal & operator=(signal && other) BOOST_NOEXCEPT{ base_type::operator=(std::move(other)); return *this; } 58 | #endif 59 | }; 60 | } 61 | } 62 | 63 | #endif // BOOST_SIGNALS2_PREPROCESSED_SIGNAL_HPP 64 | -------------------------------------------------------------------------------- /doc/tests.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 11 | 12 | 13 | ../../../libs/test/build/boost_test_exec_monitor 14 | 15 | Test functionality of boost::signals2::connection 16 | and boost::signals2::scoped_connection 17 | objects, including release() and swap(). 18 | 19 | 20 | 21 | 22 | ../../../libs/test/build/boost_test_exec_monitor 23 | 24 | Ensure that calling connect with a slot 25 | that has already expired does not actually 26 | connect to the slot. 27 | 28 | 29 | 30 | 31 | ../../../libs/test/build/boost_test_exec_monitor 32 | 33 | Test postconstruction/predestruction functionality of 34 | boost::signals2::deconstruct. 35 | 36 | 37 | 38 | 39 | ../../../libs/test/build/boost_test_exec_monitor 40 | 41 | Test deletion of slots. 42 | 43 | 44 | 45 | 46 | ../../../libs/test/build/boost_test_exec_monitor 47 | Test slot group ordering. 48 | 49 | 50 | 51 | ../../../libs/test/build/boost_test_exec_monitor 52 | Tests for various bugs that have occurred in the past, 53 | to make sure they are fixed and stay fixed. 54 | 55 | 56 | 57 | ../../../libs/test/build/boost_test_exec_monitor 58 | 59 | Basic test of signal/slot connections and invocation using the 60 | boost::signals2::signal class template. 61 | 62 | 63 | 64 | 65 | ../../../libs/test/build/boost_test_exec_monitor 66 | 67 | Test automatic connection management of signals 68 | and slots. 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /example/doc_view.cpp: -------------------------------------------------------------------------------- 1 | // Document/View sample for Boost.Signals 2 | // Copyright Keith MacDonald 2005. 3 | // Copyright Frank Mori Hess 2009. 4 | // 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // For more information, see http://www.boost.org 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | //[ document_def_code_snippet 17 | class Document 18 | { 19 | public: 20 | typedef boost::signals2::signal signal_t; 21 | 22 | public: 23 | Document() 24 | {} 25 | 26 | /* Connect a slot to the signal which will be emitted whenever 27 | text is appended to the document. */ 28 | boost::signals2::connection connect(const signal_t::slot_type &subscriber) 29 | { 30 | return m_sig.connect(subscriber); 31 | } 32 | 33 | void append(const char* s) 34 | { 35 | m_text += s; 36 | m_sig(); 37 | } 38 | 39 | const std::string& getText() const 40 | { 41 | return m_text; 42 | } 43 | 44 | private: 45 | signal_t m_sig; 46 | std::string m_text; 47 | }; 48 | //] 49 | 50 | //[ text_view_def_code_snippet 51 | class TextView 52 | { 53 | public: 54 | TextView(Document& doc): m_document(doc) 55 | { 56 | m_connection = m_document.connect(boost::bind(&TextView::refresh, this)); 57 | } 58 | 59 | ~TextView() 60 | { 61 | m_connection.disconnect(); 62 | } 63 | 64 | void refresh() const 65 | { 66 | std::cout << "TextView: " << m_document.getText() << std::endl; 67 | } 68 | private: 69 | Document& m_document; 70 | boost::signals2::connection m_connection; 71 | }; 72 | //] 73 | 74 | //[ hex_view_def_code_snippet 75 | class HexView 76 | { 77 | public: 78 | HexView(Document& doc): m_document(doc) 79 | { 80 | m_connection = m_document.connect(boost::bind(&HexView::refresh, this)); 81 | } 82 | 83 | ~HexView() 84 | { 85 | m_connection.disconnect(); 86 | } 87 | 88 | void refresh() const 89 | { 90 | const std::string& s = m_document.getText(); 91 | 92 | std::cout << "HexView:"; 93 | 94 | for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) 95 | std::cout << ' ' << std::hex << static_cast(*it); 96 | 97 | std::cout << std::endl; 98 | } 99 | private: 100 | Document& m_document; 101 | boost::signals2::connection m_connection; 102 | }; 103 | //] 104 | 105 | //[ document_view_main_code_snippet 106 | int main(int argc, char* argv[]) 107 | { 108 | Document doc; 109 | TextView v1(doc); 110 | HexView v2(doc); 111 | 112 | doc.append(argc == 2 ? argv[1] : "Hello world!"); 113 | return 0; 114 | } 115 | //] 116 | -------------------------------------------------------------------------------- /doc/reference/visit_each.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 |
11 | 12 | 13 | 17 | void 18 | 19 | const Visitor& 20 | 21 | 22 | const T& 23 | 24 | 25 | int 26 | 27 | 28 | Allow limited exploration of class members. 29 | 30 | 31 | The visit_each mechanism 32 | allows a visitor to be applied to every subobject in a given 33 | object. It was used by the Signals library to discover (now deprecated) 34 | signals::trackable objects within a 35 | function object, but other uses may surface if used 36 | universally (e.g., conservative garbage collection). To fit 37 | within the visit_each framework, 38 | a visit_each overload must be 39 | supplied for each object type. 40 | 41 | 42 | visitor(t), and for 43 | every subobject x of 44 | t: 45 | 46 | If x is a reference, visit_each(visitor, ref(x), 0) 47 | Otherwise, visit_each(visitor, x, 0) 48 | 49 | 50 | 51 | The third parameter is 52 | long for the fallback version 53 | of visit_each and the argument 54 | supplied to this third paramter must always be 0. The third 55 | parameter is an artifact of the widespread lack of proper 56 | function template ordering, and will be removed in the future. 57 | 58 | Library authors will be expected to add additional 59 | overloads that specialize the T argument for their classes, so 60 | that subobjects can be visited. 61 | 62 | Calls to visit_each are required to be unqualified, to 63 | enable argument-dependent lookup. 64 | 65 | 66 |
67 | -------------------------------------------------------------------------------- /include/boost/signals2/preprocessed_slot.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Frank Mori Hess 2007-2009. 4 | // Copyright Timmo Stange 2007. 5 | // Copyright Douglas Gregor 2001-2004. Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // For more information, see http://www.boost.org 11 | 12 | #ifndef BOOST_SIGNALS2_PREPROCESSED_SLOT_HPP 13 | #define BOOST_SIGNALS2_PREPROCESSED_SLOT_HPP 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #ifndef BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS 20 | #define BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS 10 21 | #endif 22 | 23 | 24 | // template slotN(... 25 | #define BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTOR(z, n, data) \ 26 | template \ 27 | BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)( \ 28 | const Func &func, BOOST_SIGNALS2_PREFIXED_FULL_REF_ARGS(n, const BindArg)) \ 29 | { \ 30 | init_slot_function(boost::bind(func, BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(n))); \ 31 | } 32 | #define BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTORS \ 33 | BOOST_PP_REPEAT_FROM_TO(1, BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS, BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTOR, ~) 34 | 35 | 36 | #define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_INC(BOOST_SIGNALS2_MAX_ARGS)) 37 | #define BOOST_PP_FILENAME_1 38 | #include BOOST_PP_ITERATE() 39 | 40 | #undef BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTOR 41 | #undef BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTORS 42 | 43 | namespace boost 44 | { 45 | namespace signals2 46 | { 47 | template > 49 | class slot: public detail::slotN::arity, 50 | Signature, SlotFunction>::type 51 | { 52 | private: 53 | typedef typename detail::slotN::arity, 54 | Signature, SlotFunction>::type base_type; 55 | public: 56 | template 57 | slot(const F& f): base_type(f) 58 | {} 59 | // bind syntactic sugar 60 | // template slot(... 61 | #define BOOST_SIGNALS2_SLOT_BINDING_CONSTRUCTOR(z, n, data) \ 62 | template \ 63 | slot(const Func &func, BOOST_SIGNALS2_PREFIXED_FULL_REF_ARGS(n, const BindArg)): \ 64 | base_type(func, BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(n)) \ 65 | {} 66 | BOOST_PP_REPEAT_FROM_TO(1, BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS, BOOST_SIGNALS2_SLOT_BINDING_CONSTRUCTOR, ~) 67 | #undef BOOST_SIGNALS2_SLOT_BINDING_CONSTRUCTOR 68 | }; 69 | } // namespace signals2 70 | } 71 | 72 | #endif // BOOST_SIGNALS2_PREPROCESSED_SLOT_HPP 73 | -------------------------------------------------------------------------------- /test/deadlock_regression_test.cpp: -------------------------------------------------------------------------------- 1 | // Signals2 library 2 | // 3 | // Regression test based on bug report from Arian Alin Radu. 4 | // The problem was that tracked objects could be released 5 | // while holding the signal mutex during signal invocation. 6 | // This could result in a recursive 7 | // lock attempt if the tracked object manipulates the signal 8 | // in its destructor. 9 | 10 | // Copyright Frank Mori Hess 2019 11 | // Use, modification and 12 | // distribution is subject to the Boost Software License, Version 13 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 14 | // http://www.boost.org/LICENSE_1_0.txt) 15 | 16 | // For more information, see http://www.boost.org 17 | 18 | #define BOOST_TEST_MODULE signals2 deadlock regression test 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace bs2 = boost::signals2; 26 | 27 | 28 | // dummy mutex that detects attempts to recursively lock 29 | class test_mutex 30 | { 31 | public: 32 | test_mutex(): m_locked(false) {} 33 | void lock() 34 | { 35 | BOOST_CHECK(m_locked == false); 36 | m_locked = true; 37 | } 38 | bool try_lock() 39 | { 40 | if(m_locked) return false; 41 | lock(); 42 | return true; 43 | } 44 | void unlock() 45 | { 46 | m_locked = false; 47 | } 48 | private: 49 | bool m_locked; 50 | }; 51 | 52 | using namespace bs2::keywords; 53 | typedef bs2::signal_type >::type Signal; 54 | 55 | class SelfReference: private boost::noncopyable 56 | { 57 | public: 58 | boost::shared_ptr m_self; 59 | boost::shared_ptr m_signal; 60 | 61 | boost::signals2::connection m_conReleaseSelf; 62 | boost::signals2::connection m_conDoNothing; 63 | 64 | SelfReference() 65 | { 66 | m_signal = boost::make_shared(); 67 | } 68 | 69 | ~SelfReference() 70 | { 71 | // the first slot (ReleaseSelf) has been called; now the trackable object (this) 72 | // was released, while the second slot is locked 73 | BOOST_CHECK(!m_conReleaseSelf.connected()); 74 | // the second slot is locked, and we enter a recursive (pthread: dead) lock 75 | BOOST_CHECK(m_conDoNothing.connected()); 76 | m_conReleaseSelf.disconnect(); 77 | m_conDoNothing.disconnect(); 78 | // enter recursive (pthread: dead) lock again: 79 | BOOST_CHECK(m_signal->empty()); 80 | } 81 | 82 | void ReleaseSelf() 83 | { 84 | m_self.reset(); 85 | } 86 | 87 | static void DoNothing() 88 | { 89 | } 90 | 91 | static void Run() 92 | { 93 | boost::shared_ptr signal; 94 | { 95 | boost::shared_ptr obj = boost::make_shared(); 96 | obj->m_self = obj; 97 | signal = obj->m_signal; 98 | 99 | obj->m_conReleaseSelf = signal->connect(Signal::slot_type(&SelfReference::ReleaseSelf, obj.get()).track(obj)); 100 | obj->m_conDoNothing = signal->connect(Signal::slot_type(&SelfReference::DoNothing)); 101 | } 102 | (*signal)(); 103 | } 104 | }; 105 | 106 | BOOST_AUTO_TEST_CASE(test_main) 107 | { 108 | SelfReference::Run(); 109 | } 110 | -------------------------------------------------------------------------------- /doc/reference/mutex.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | A header-only mutex which implements the Lockable concept of Boost.Thread. 17 | 18 | 19 | 20 | The mutex class implements the Lockable 21 | concept of Boost.Thread, and is the default Mutex template parameter 22 | type for signals. 23 | If boost has detected thread support in your compiler, the mutex 24 | class will map to a CRITICAL_SECTION on Windows 25 | or a pthread_mutex on POSIX. If thread support is not detected, mutex 26 | will behave similarly to a dummy_mutex. 27 | The header file boost/config.hpp 28 | defines the macro BOOST_HAS_THREADS when boost detects threading support. 29 | The user may globally disable thread support 30 | in boost by defining BOOST_DISABLE_THREADS before any boost header files are included. 31 | 32 | 33 | If you are already using the Boost.Thread library, you may prefer to use its 34 | boost::mutex class instead as the mutex type for your signals. 35 | 36 | 37 | You may wish to use a thread-unsafe signal, if 38 | the signal is only used by a single thread. In that case, you may prefer to 39 | use the signals2::dummy_mutex class as the Mutex 40 | template type for your signal. 41 | 42 | 43 | 44 | 45 | void 46 | 47 | Locks the mutex. 48 | 49 | 50 | 51 | 52 | bool 53 | 54 | Makes a non-blocking attempt to lock the mutex. 55 | 56 | 57 | true on success. 58 | 59 | 60 | void 61 | 62 | Unlocks the mutex. 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
71 | -------------------------------------------------------------------------------- /example/disconnect_and_block.cpp: -------------------------------------------------------------------------------- 1 | // Various simple examples involving disconnecting and blocking slots. 2 | // Copyright Douglas Gregor 2001-2004. 3 | // Copyright Frank Mori Hess 2009. 4 | // 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // For more information, see http://www.boost.org 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | struct HelloWorld 16 | { 17 | void operator()() const 18 | { 19 | std::cout << "Hello, World!" << std::endl; 20 | } 21 | }; 22 | 23 | void disconnect_example() 24 | { 25 | boost::signals2::signal sig; 26 | 27 | //[ disconnect_code_snippet 28 | boost::signals2::connection c = sig.connect(HelloWorld()); 29 | std::cout << "c is connected\n"; 30 | sig(); // Prints "Hello, World!" 31 | 32 | c.disconnect(); // Disconnect the HelloWorld object 33 | std::cout << "c is disconnected\n"; 34 | sig(); // Does nothing: there are no connected slots 35 | //] 36 | } 37 | 38 | void block_example() 39 | { 40 | boost::signals2::signal sig; 41 | 42 | //[ block_code_snippet 43 | boost::signals2::connection c = sig.connect(HelloWorld()); 44 | std::cout << "c is not blocked.\n"; 45 | sig(); // Prints "Hello, World!" 46 | 47 | { 48 | boost::signals2::shared_connection_block block(c); // block the slot 49 | std::cout << "c is blocked.\n"; 50 | sig(); // No output: the slot is blocked 51 | } // shared_connection_block going out of scope unblocks the slot 52 | std::cout << "c is not blocked.\n"; 53 | sig(); // Prints "Hello, World!"} 54 | //] 55 | } 56 | 57 | struct ShortLived 58 | { 59 | void operator()() const 60 | { 61 | std::cout << "Life is short!" << std::endl; 62 | } 63 | }; 64 | 65 | void scoped_connection_example() 66 | { 67 | boost::signals2::signal sig; 68 | 69 | //[ scoped_connection_code_snippet 70 | { 71 | boost::signals2::scoped_connection c(sig.connect(ShortLived())); 72 | sig(); // will call ShortLived function object 73 | } // scoped_connection goes out of scope and disconnects 74 | 75 | sig(); // ShortLived function object no longer connected to sig 76 | //] 77 | } 78 | 79 | //[ disconnect_by_slot_def_code_snippet 80 | void foo() { std::cout << "foo"; } 81 | void bar() { std::cout << "bar\n"; } 82 | //] 83 | 84 | void disconnect_by_slot_example() 85 | { 86 | boost::signals2::signal sig; 87 | 88 | //[ disconnect_by_slot_usage_code_snippet 89 | sig.connect(&foo); 90 | sig.connect(&bar); 91 | sig(); 92 | 93 | // disconnects foo, but not bar 94 | sig.disconnect(&foo); 95 | sig(); 96 | //] 97 | } 98 | 99 | int main() 100 | { 101 | std::cout << "Disconnect example:\n"; 102 | disconnect_example(); 103 | 104 | std::cout << "\nBlock example:\n"; 105 | block_example(); 106 | 107 | std::cout << "\nScoped connection example:\n"; 108 | scoped_connection_example(); 109 | 110 | std::cout << "\nDisconnect by slot example:\n"; 111 | disconnect_by_slot_example(); 112 | 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /test/ordering_test.cpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Douglas Gregor 2002-2004. Use, modification and 4 | // distribution is subject to the Boost Software License, Version 5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | // For more information, see http://www.boost.org 9 | 10 | #include 11 | #define BOOST_TEST_MODULE ordering_test 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | std::vector valuesOutput; 21 | bool ungrouped1 = false; 22 | bool ungrouped2 = false; 23 | bool ungrouped3 = false; 24 | 25 | struct emit_int { 26 | emit_int(int v) : value(v) {} 27 | 28 | void operator()() const 29 | { 30 | BOOST_CHECK(value == 42 || (!ungrouped1 && !ungrouped2 && !ungrouped3)); 31 | valuesOutput.push_back(value); 32 | std::cout << value << ' '; 33 | } 34 | 35 | private: 36 | int value; 37 | }; 38 | 39 | struct write_ungrouped1 { 40 | void operator()() const 41 | { 42 | BOOST_CHECK(!ungrouped1); 43 | ungrouped1 = true; 44 | std::cout << "(Ungrouped #1)" << ' '; 45 | } 46 | }; 47 | 48 | struct write_ungrouped2 { 49 | void operator()() const 50 | { 51 | BOOST_CHECK(!ungrouped2); 52 | ungrouped2 = true; 53 | std::cout << "(Ungrouped #2)" << ' '; 54 | } 55 | }; 56 | 57 | struct write_ungrouped3 { 58 | void operator()() const 59 | { 60 | BOOST_CHECK(!ungrouped3); 61 | ungrouped3 = true; 62 | std::cout << "(Ungrouped #3)" << ' '; 63 | } 64 | }; 65 | 66 | int return_argument(int x) 67 | { 68 | return x; 69 | } 70 | 71 | void test_group_compare() 72 | { 73 | boost::signals2::signal 74 | < 75 | int (), 76 | boost::signals2::last_value, 77 | int, 78 | std::greater< int > 79 | > sig; 80 | 81 | sig.connect( 1, boost::bind( &return_argument, 1) ); 82 | sig.connect( 2, boost::bind( &return_argument, 2) ); 83 | 84 | BOOST_CHECK(sig() == 1); 85 | } 86 | 87 | BOOST_AUTO_TEST_CASE(test_main) 88 | { 89 | using namespace std; 90 | srand(static_cast(time(0))); 91 | 92 | std::vector sortedValues; 93 | 94 | boost::signals2::signal sig; 95 | sig.connect(write_ungrouped1()); 96 | for (int i = 0; i < 100; ++i) { 97 | #ifdef BOOST_NO_STDC_NAMESPACE 98 | int v = rand() % 100; 99 | #else 100 | int v = std::rand() % 100; 101 | #endif 102 | sortedValues.push_back(v); 103 | sig.connect(v, emit_int(v)); 104 | 105 | if (i == 50) { 106 | sig.connect(write_ungrouped2()); 107 | } 108 | } 109 | sig.connect(write_ungrouped3()); 110 | 111 | std::sort(sortedValues.begin(), sortedValues.end()); 112 | 113 | // 17 at beginning, 42 at end 114 | sortedValues.insert(sortedValues.begin(), 17); 115 | sig.connect(emit_int(17), boost::signals2::at_front); 116 | sortedValues.push_back(42); 117 | sig.connect(emit_int(42)); 118 | 119 | sig(); 120 | std::cout << std::endl; 121 | 122 | BOOST_CHECK(valuesOutput == sortedValues); 123 | BOOST_CHECK(ungrouped1); 124 | BOOST_CHECK(ungrouped2); 125 | BOOST_CHECK(ungrouped3); 126 | 127 | test_group_compare(); 128 | } 129 | -------------------------------------------------------------------------------- /example/custom_combiners.cpp: -------------------------------------------------------------------------------- 1 | // Example program showing signals with custom combiners. 2 | // 3 | // Copyright Douglas Gregor 2001-2004. 4 | // Copyright Frank Mori Hess 2009. 5 | // 6 | // Use, modification and 7 | // distribution is subject to the Boost Software License, Version 8 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // For more information, see http://www.boost.org 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | float product(float x, float y) { return x * y; } 17 | float quotient(float x, float y) { return x / y; } 18 | float sum(float x, float y) { return x + y; } 19 | float difference(float x, float y) { return x - y; } 20 | 21 | //[ custom_combiners_maximum_def_code_snippet 22 | // combiner which returns the maximum value returned by all slots 23 | template 24 | struct maximum 25 | { 26 | typedef T result_type; 27 | 28 | template 29 | T operator()(InputIterator first, InputIterator last) const 30 | { 31 | // If there are no slots to call, just return the 32 | // default-constructed value 33 | if(first == last ) return T(); 34 | T max_value = *first++; 35 | while (first != last) { 36 | if (max_value < *first) 37 | max_value = *first; 38 | ++first; 39 | } 40 | 41 | return max_value; 42 | } 43 | }; 44 | //] 45 | 46 | void maximum_combiner_example() 47 | { 48 | // signal which uses our custom "maximum" combiner 49 | boost::signals2::signal > sig; 50 | 51 | //[ custom_combiners_maximum_usage_code_snippet 52 | sig.connect(&product); 53 | sig.connect("ient); 54 | sig.connect(&sum); 55 | sig.connect(&difference); 56 | 57 | // Outputs the maximum value returned by the connected slots, in this case 58 | // 15 from the product function. 59 | std::cout << "maximum: " << sig(5, 3) << std::endl; 60 | //] 61 | } 62 | 63 | //[ custom_combiners_aggregate_values_def_code_snippet 64 | // aggregate_values is a combiner which places all the values returned 65 | // from slots into a container 66 | template 67 | struct aggregate_values 68 | { 69 | typedef Container result_type; 70 | 71 | template 72 | Container operator()(InputIterator first, InputIterator last) const 73 | { 74 | Container values; 75 | 76 | while(first != last) { 77 | values.push_back(*first); 78 | ++first; 79 | } 80 | return values; 81 | } 82 | }; 83 | //] 84 | 85 | void aggregate_values_example() 86 | { 87 | // signal which uses aggregate_values as its combiner 88 | boost::signals2::signal > > sig; 90 | 91 | //[ custom_combiners_aggregate_values_usage_code_snippet 92 | sig.connect("ient); 93 | sig.connect(&product); 94 | sig.connect(&sum); 95 | sig.connect(&difference); 96 | 97 | std::vector results = sig(5, 3); 98 | std::cout << "aggregate values: "; 99 | std::copy(results.begin(), results.end(), 100 | std::ostream_iterator(std::cout, " ")); 101 | std::cout << "\n"; 102 | //] 103 | } 104 | 105 | int main() 106 | { 107 | maximum_combiner_example(); 108 | aggregate_values_example(); 109 | } 110 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/scope_guard.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2003-2013 Joaquin M Lopez Munoz. 2 | * 2019 Mike Dev 3 | * Distributed under the Boost Software License, Version 1.0. 4 | * (See accompanying file LICENSE_1_0.txt or copy at 5 | * https://www.boost.org/LICENSE_1_0.txt) 6 | * 7 | * NOTE: internalized from Boost.MultiIndex 8 | * 9 | */ 10 | 11 | 12 | #ifndef BOOST_SIGNALS2_DETAIL_SCOPE_GUARD_HPP 13 | #define BOOST_SIGNALS2_DETAIL_SCOPE_GUARD_HPP 14 | 15 | #if defined(_MSC_VER) 16 | #pragma once 17 | #endif 18 | 19 | #include 20 | 21 | namespace boost{ 22 | 23 | namespace signals2{ 24 | 25 | namespace detail{ 26 | 27 | /* This is a merely reformated version of 28 | * ScopeGuard.h as defined in: 29 | * Alexandrescu, A., Marginean, P.:"Generic: Change the Way You 30 | * Write Exception-Safe Code - Forever", C/C++ Users Jornal, Dec 2000, 31 | * http://www.drdobbs.com/184403758 32 | * with the following modifications: 33 | * - General pretty formatting (pretty to my taste at least.) 34 | * - Naming style changed to standard C++ library requirements. 35 | * - Removed RefHolder and ByRef, whose functionality is provided 36 | * already by Boost.Ref. 37 | * - Removed static make_guard's and make_obj_guard's, so that the code 38 | * will work even if BOOST_NO_MEMBER_TEMPLATES is defined. This forces 39 | * us to move some private ctors to public, though. 40 | * 41 | * NB: CodeWarrior Pro 8 seems to have problems looking up safe_execute 42 | * without an explicit qualification. 43 | * 44 | * TODO: Consider replacing with Boost.ScopeExit 45 | * 46 | */ 47 | 48 | class scope_guard_impl_base 49 | { 50 | public: 51 | scope_guard_impl_base():dismissed_(false){} 52 | void dismiss()const{dismissed_=true;} 53 | 54 | protected: 55 | ~scope_guard_impl_base(){} 56 | 57 | scope_guard_impl_base(const scope_guard_impl_base& other): 58 | dismissed_(other.dismissed_) 59 | { 60 | other.dismiss(); 61 | } 62 | 63 | template 64 | static void safe_execute(J& j){ 65 | BOOST_TRY{ 66 | if(!j.dismissed_)j.execute(); 67 | } 68 | BOOST_CATCH(...){} 69 | BOOST_CATCH_END 70 | } 71 | 72 | mutable bool dismissed_; 73 | 74 | private: 75 | scope_guard_impl_base& operator=(const scope_guard_impl_base&); 76 | }; 77 | 78 | typedef const scope_guard_impl_base& scope_guard; 79 | 80 | template 81 | class obj_scope_guard_impl2:public scope_guard_impl_base 82 | { 83 | public: 84 | obj_scope_guard_impl2(Obj& obj,MemFun mem_fun,P1 p1,P2 p2): 85 | obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2) 86 | {} 87 | ~obj_scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);} 88 | void execute(){(obj_.*mem_fun_)(p1_,p2_);} 89 | 90 | protected: 91 | Obj& obj_; 92 | MemFun mem_fun_; 93 | const P1 p1_; 94 | const P2 p2_; 95 | }; 96 | 97 | template 98 | inline obj_scope_guard_impl2 99 | make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2) 100 | { 101 | return obj_scope_guard_impl2(obj,mem_fun,p1,p2); 102 | } 103 | 104 | } /* namespace signals2::detail */ 105 | 106 | } /* namespace signals2 */ 107 | 108 | } /* namespace boost */ 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /test/shared_connection_block_test.cpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Douglas Gregor 2001-2003. 4 | // Use, modification and 5 | // distribution is subject to the Boost Software License, Version 6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // For more information, see http://www.boost.org 10 | 11 | #include 12 | #include 13 | #include 14 | #define BOOST_TEST_MODULE shared_connection_block_test 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | static boost::array connections; 21 | 22 | static std::ostringstream test_output; 23 | 24 | struct test_slot { 25 | explicit test_slot(int v = 0) : value(v) 26 | {} 27 | 28 | void operator()() const { 29 | test_output << value; 30 | } 31 | 32 | int value; 33 | }; 34 | 35 | BOOST_AUTO_TEST_CASE(test_main) 36 | { 37 | boost::signals2::signal s0; 38 | 39 | for(unsigned i = 0; i < connections.size(); ++i) 40 | { 41 | connections.at(i) = s0.connect(test_slot(i)); 42 | } 43 | 44 | 45 | { 46 | // Blocking 2 47 | boost::signals2::shared_connection_block block(connections.at(2)); 48 | BOOST_CHECK(block.blocking()); 49 | test_output.str(""); 50 | s0(); 51 | BOOST_CHECK(test_output.str() == "013"); 52 | } 53 | 54 | // Unblocking 2 55 | test_output.str(""); 56 | s0(); 57 | BOOST_CHECK(test_output.str() == "0123"); 58 | 59 | { 60 | // Blocking 1 through const connection 61 | const boost::signals2::connection conn = connections.at(1); 62 | boost::signals2::shared_connection_block block(conn); 63 | test_output.str(""); 64 | s0(); 65 | std::cout << test_output.str() << std::endl; 66 | BOOST_CHECK(test_output.str() == "023"); 67 | // Unblocking 1 68 | block.unblock(); 69 | BOOST_CHECK(block.blocking() == false); 70 | test_output.str(""); 71 | s0(); 72 | BOOST_CHECK(test_output.str() == "0123"); 73 | } 74 | 75 | { 76 | // initially unblocked 77 | boost::signals2::shared_connection_block block(connections.at(3), false); 78 | BOOST_CHECK(block.blocking() == false); 79 | test_output.str(""); 80 | s0(); 81 | BOOST_CHECK(test_output.str() == "0123"); 82 | // block 83 | block.block(); 84 | test_output.str(""); 85 | s0(); 86 | BOOST_CHECK(test_output.str() == "012"); 87 | } 88 | 89 | { 90 | // test default constructed block 91 | boost::signals2::shared_connection_block block; 92 | BOOST_CHECK(block.blocking() == true); 93 | block.unblock(); 94 | BOOST_CHECK(block.blocking() == false); 95 | block.block(); 96 | BOOST_CHECK(block.blocking() == true); 97 | 98 | // test assignment 99 | { 100 | block.unblock(); 101 | boost::signals2::shared_connection_block block2(connections.at(0)); 102 | BOOST_CHECK(block.connection() != block2.connection()); 103 | BOOST_CHECK(block.blocking() != block2.blocking()); 104 | block = block2; 105 | BOOST_CHECK(block.connection() == block2.connection()); 106 | BOOST_CHECK(block.blocking() == block2.blocking()); 107 | } 108 | test_output.str(""); 109 | s0(); 110 | BOOST_CHECK(test_output.str() == "123"); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /test/trackable_test.cpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Douglas Gregor 2001-2006. 4 | // Copyright Frank Mori Hess 2009. 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // For more information, see http://www.boost.org 11 | 12 | #include 13 | #include 14 | #define BOOST_TEST_MODULE trackable_test 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace boost::placeholders; 21 | 22 | struct short_lived : public boost::signals2::trackable { 23 | ~short_lived() {} 24 | }; 25 | 26 | struct swallow { 27 | typedef int result_type; 28 | template int operator()(const T*, int i) { return i; } 29 | template int operator()(T &, int i) { return i; } 30 | template int operator()(boost::weak_ptr, int i) { return i; } 31 | }; 32 | 33 | template 34 | struct max_or_default { 35 | typedef T result_type; 36 | 37 | template 38 | T operator()(InputIterator first, InputIterator last) const 39 | { 40 | if (first == last) 41 | return T(); 42 | 43 | T max = *first++; 44 | for (; first != last; ++first) 45 | max = (*first > max)? *first : max; 46 | 47 | return max; 48 | } 49 | }; 50 | 51 | struct self_deleting : public boost::signals2::trackable { 52 | void delete_myself(boost::signals2::connection connection) 53 | { 54 | BOOST_CHECK(connection.connected()); 55 | delete this; 56 | BOOST_CHECK(connection.connected() == false); 57 | } 58 | }; 59 | 60 | // test that slot assocated with signals2::trackable 61 | // gets disconnected immediately upon deletion of the 62 | // signals2::trackable, even when a signal invocation 63 | // is in progress. 64 | void test_immediate_disconnect_on_delete() 65 | { 66 | boost::signals2::signal sig; 67 | self_deleting *obj = new self_deleting(); 68 | sig.connect_extended(boost::bind(&self_deleting::delete_myself, obj, _1)); 69 | sig(); 70 | } 71 | 72 | BOOST_AUTO_TEST_CASE(test_main) 73 | { 74 | typedef boost::signals2::signal > sig_type; 75 | sig_type s1; 76 | 77 | // Test auto-disconnection 78 | BOOST_CHECK(s1(5) == 0); 79 | { 80 | short_lived shorty; 81 | s1.connect(boost::bind(swallow(), &shorty, _1)); 82 | BOOST_CHECK(s1(5) == 5); 83 | } 84 | BOOST_CHECK(s1(5) == 0); 85 | // Test auto-disconnection of trackable inside reference_wrapper 86 | { 87 | short_lived shorty; 88 | s1.connect(boost::bind(swallow(), boost::ref(shorty), _1)); 89 | BOOST_CHECK(s1(5) == 5); 90 | } 91 | BOOST_CHECK(s1(5) == 0); 92 | 93 | // Test multiple arg slot constructor 94 | { 95 | short_lived shorty; 96 | s1.connect(sig_type::slot_type(swallow(), &shorty, _1)); 97 | BOOST_CHECK(s1(5) == 5); 98 | } 99 | BOOST_CHECK(s1(5) == 0); 100 | 101 | // Test auto-disconnection of slot before signal connection 102 | { 103 | short_lived* shorty = new short_lived(); 104 | 105 | sig_type::slot_type slot(boost::bind(swallow(), shorty, _1)); 106 | delete shorty; 107 | 108 | BOOST_CHECK(s1(5) == 0); 109 | } 110 | 111 | test_immediate_disconnect_on_delete(); 112 | } 113 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/tracked_objects_visitor.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Frank Mori Hess 2007-2008. 4 | // Copyright Timmo Stange 2007. 5 | // Copyright Douglas Gregor 2001-2004. Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // For more information, see http://www.boost.org 11 | 12 | #ifndef BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP 13 | #define BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace boost 26 | { 27 | namespace signals2 28 | { 29 | namespace detail 30 | { 31 | // Visitor to collect tracked objects from a bound function. 32 | class tracked_objects_visitor 33 | { 34 | public: 35 | tracked_objects_visitor(slot_base *slot) : slot_(slot) 36 | {} 37 | template 38 | void operator()(const T& t) const 39 | { 40 | m_visit_reference_wrapper(t, mpl::bool_::value>()); 41 | } 42 | private: 43 | template 44 | void m_visit_reference_wrapper(const reference_wrapper &t, const mpl::bool_ &) const 45 | { 46 | m_visit_pointer(t.get_pointer(), mpl::bool_()); 47 | } 48 | template 49 | void m_visit_reference_wrapper(const T &t, const mpl::bool_ &) const 50 | { 51 | m_visit_pointer(t, mpl::bool_::value>()); 52 | } 53 | template 54 | void m_visit_pointer(const T &t, const mpl::bool_ &) const 55 | { 56 | m_visit_not_function_pointer(t, mpl::bool_::type>::value>()); 57 | } 58 | template 59 | void m_visit_pointer(const T &t, const mpl::bool_ &) const 60 | { 61 | m_visit_pointer(boost::addressof(t), mpl::bool_()); 62 | } 63 | template 64 | void m_visit_not_function_pointer(const T *t, const mpl::bool_ &) const 65 | { 66 | m_visit_signal(t, mpl::bool_::value>()); 67 | } 68 | template 69 | void m_visit_not_function_pointer(const T &, const mpl::bool_ &) const 70 | {} 71 | template 72 | void m_visit_signal(const T *signal, const mpl::bool_ &) const 73 | { 74 | if(signal) 75 | slot_->track_signal(*signal); 76 | } 77 | template 78 | void m_visit_signal(const T &t, const mpl::bool_ &) const 79 | { 80 | add_if_trackable(t); 81 | } 82 | void add_if_trackable(const trackable *trackable) const 83 | { 84 | if(trackable) 85 | slot_->_tracked_objects.push_back(trackable->get_weak_ptr()); 86 | } 87 | void add_if_trackable(const void *) const {} 88 | 89 | mutable slot_base * slot_; 90 | }; 91 | 92 | 93 | } // end namespace detail 94 | } // end namespace signals2 95 | } // end namespace boost 96 | 97 | #endif // BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP 98 | 99 | -------------------------------------------------------------------------------- /example/doc_view_acm.cpp: -------------------------------------------------------------------------------- 1 | // Document/View sample for Boost.Signals2. 2 | // Expands on doc_view.cpp example by using automatic 3 | // connection management. 4 | // 5 | // Copyright Keith MacDonald 2005. 6 | // Copyright Frank Mori Hess 2009. 7 | // 8 | // Use, modification and 9 | // distribution is subject to the Boost Software License, Version 10 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 11 | // http://www.boost.org/LICENSE_1_0.txt) 12 | // For more information, see http://www.boost.org 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | class Document 22 | { 23 | public: 24 | typedef boost::signals2::signal signal_t; 25 | 26 | public: 27 | Document() 28 | {} 29 | 30 | /* connect a slot to the signal which will be emitted whenever 31 | text is appended to the document. */ 32 | boost::signals2::connection connect(const signal_t::slot_type &subscriber) 33 | { 34 | return m_sig.connect(subscriber); 35 | } 36 | 37 | void append(const char* s) 38 | { 39 | m_text += s; 40 | m_sig(); 41 | } 42 | 43 | const std::string& getText() const 44 | { 45 | return m_text; 46 | } 47 | 48 | private: 49 | signal_t m_sig; 50 | std::string m_text; 51 | }; 52 | 53 | class TextView 54 | { 55 | public: 56 | // static factory function that sets up automatic connection tracking 57 | static boost::shared_ptr create(Document& doc) 58 | { 59 | boost::shared_ptr new_view(new TextView(doc)); 60 | { 61 | typedef Document::signal_t::slot_type slot_type; 62 | slot_type myslot(&TextView::refresh, new_view.get()); 63 | doc.connect(myslot.track(new_view)); 64 | } 65 | return new_view; 66 | } 67 | 68 | void refresh() const 69 | { 70 | std::cout << "TextView: " << m_document.getText() << std::endl; 71 | } 72 | private: 73 | // private constructor to force use of static factory function 74 | TextView(Document &doc): m_document(doc) 75 | {} 76 | 77 | Document& m_document; 78 | }; 79 | 80 | class HexView 81 | { 82 | public: 83 | // static factory function that sets up automatic connection tracking 84 | static boost::shared_ptr create(Document& doc) 85 | { 86 | boost::shared_ptr new_view(new HexView(doc)); 87 | { 88 | typedef Document::signal_t::slot_type slot_type; 89 | slot_type myslot(&HexView::refresh, new_view.get()); 90 | doc.connect(myslot.track(new_view)); 91 | } 92 | return new_view; 93 | } 94 | 95 | void refresh() const 96 | { 97 | boost::io::ios_flags_saver ifs(std::cout); 98 | const std::string& s = m_document.getText(); 99 | 100 | std::cout << "HexView:"; 101 | 102 | for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) 103 | std::cout << ' ' << std::hex << static_cast(*it); 104 | 105 | std::cout << std::endl; 106 | } 107 | private: 108 | // private constructor to force use of static factory function 109 | HexView(Document& doc): m_document(doc) 110 | {} 111 | 112 | Document& m_document; 113 | }; 114 | 115 | int main(int argc, char* argv[]) 116 | { 117 | Document doc; 118 | boost::shared_ptr v1 = TextView::create(doc); 119 | boost::shared_ptr v2 = HexView::create(doc); 120 | 121 | doc.append(argc >= 2 ? argv[1] : "Hello world!"); 122 | 123 | v2.reset(); // destroy the HexView, automatically disconnecting 124 | doc.append(" HexView should no longer be connected."); 125 | 126 | return 0; 127 | } 128 | -------------------------------------------------------------------------------- /include/boost/signals2/detail/lwm_win32_cs.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // boost/signals2/detail/lwm_win32_cs.hpp 3 | // 4 | // Copyright (c) 2002, 2003 Peter Dimov 5 | // Copyright (c) 2008 Frank Mori Hess 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See 8 | // accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // 11 | 12 | #ifndef BOOST_SIGNALS2_LWM_WIN32_CS_HPP 13 | #define BOOST_SIGNALS2_LWM_WIN32_CS_HPP 14 | 15 | // MS compatible compilers support #pragma once 16 | 17 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 18 | # pragma once 19 | #endif 20 | 21 | #include 22 | 23 | #ifdef BOOST_USE_WINDOWS_H 24 | 25 | #include 26 | 27 | #else 28 | 29 | struct _RTL_CRITICAL_SECTION; 30 | 31 | #endif 32 | 33 | namespace boost 34 | { 35 | 36 | namespace signals2 37 | { 38 | 39 | namespace detail 40 | { 41 | 42 | #ifndef BOOST_USE_WINDOWS_H 43 | 44 | struct critical_section 45 | { 46 | struct critical_section_debug * DebugInfo; 47 | long LockCount; 48 | long RecursionCount; 49 | void * OwningThread; 50 | void * LockSemaphore; 51 | #if defined(_WIN64) 52 | unsigned __int64 SpinCount; 53 | #else 54 | unsigned long SpinCount; 55 | #endif 56 | }; 57 | 58 | extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *); 59 | extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRITICAL_SECTION *); 60 | extern "C" __declspec(dllimport) int __stdcall TryEnterCriticalSection(::_RTL_CRITICAL_SECTION *); 61 | extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *); 62 | extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *); 63 | 64 | typedef ::_RTL_CRITICAL_SECTION rtl_critical_section; 65 | 66 | #else // #ifndef BOOST_USE_WINDOWS_H 67 | 68 | typedef ::CRITICAL_SECTION critical_section; 69 | 70 | using ::InitializeCriticalSection; 71 | using ::EnterCriticalSection; 72 | using ::TryEnterCriticalSection; 73 | using ::LeaveCriticalSection; 74 | using ::DeleteCriticalSection; 75 | 76 | typedef ::CRITICAL_SECTION rtl_critical_section; 77 | 78 | #endif // #ifndef BOOST_USE_WINDOWS_H 79 | 80 | } // namespace detail 81 | 82 | class mutex 83 | { 84 | private: 85 | 86 | boost::signals2::detail::critical_section cs_; 87 | 88 | mutex(mutex const &); 89 | mutex & operator=(mutex const &); 90 | 91 | public: 92 | 93 | mutex() 94 | { 95 | boost::signals2::detail::InitializeCriticalSection(reinterpret_cast< boost::signals2::detail::rtl_critical_section* >(&cs_)); 96 | } 97 | 98 | ~mutex() 99 | { 100 | boost::signals2::detail::DeleteCriticalSection(reinterpret_cast< boost::signals2::detail::rtl_critical_section* >(&cs_)); 101 | } 102 | 103 | void lock() 104 | { 105 | boost::signals2::detail::EnterCriticalSection(reinterpret_cast< boost::signals2::detail::rtl_critical_section* >(&cs_)); 106 | } 107 | // TryEnterCriticalSection only exists on Windows NT 4.0 and later 108 | #if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)) 109 | bool try_lock() 110 | { 111 | return boost::signals2::detail::TryEnterCriticalSection(reinterpret_cast< boost::signals2::detail::rtl_critical_section* >(&cs_)) != 0; 112 | } 113 | #else 114 | bool try_lock() 115 | { 116 | BOOST_ASSERT(false); 117 | return false; 118 | } 119 | #endif 120 | void unlock() 121 | { 122 | boost::signals2::detail::LeaveCriticalSection(reinterpret_cast< boost::signals2::detail::rtl_critical_section* >(&cs_)); 123 | } 124 | }; 125 | 126 | } // namespace signals2 127 | 128 | } // namespace boost 129 | 130 | #endif // #ifndef BOOST_SIGNALS2_LWM_WIN32_CS_HPP 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Signals2, part of collection of the [Boost C++ Libraries](http://github.com/boostorg), is an implementation of a managed signals and slots system. 2 | 3 | ### License 4 | 5 | Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). 6 | 7 | ### Properties 8 | 9 | * C++03 10 | * Header-Only 11 | 12 | ### Build Status 13 | 14 | Branch | Travis | Appveyor | Coverity Scan | codecov.io | Deps | Docs | Tests | 15 | :-------------: | ------ | -------- | ------------- | ---------- | ---- | ---- | ----- | 16 | [`master`](https://github.com/boostorg/signals2/tree/master) | [![Build Status](https://travis-ci.org/boostorg/signals2.svg?branch=master)](https://travis-ci.org/boostorg/signals2) | [![Build status](https://ci.appveyor.com/api/projects/status/vjbstowu1s13x4l5/branch/master?svg=true)](https://ci.appveyor.com/project/jeking3/signals2-db91c/branch/master) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/15884/badge.svg)](https://scan.coverity.com/projects/boostorg-signals2) | [![codecov](https://codecov.io/gh/boostorg/signals2/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/signals2/branch/master)| [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/signals2.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](http://www.boost.org/doc/libs/master/doc/html/signals2.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](https://regression.boost.io/master/developer/signals2.html) 17 | [`develop`](https://github.com/boostorg/signals2/tree/develop) | [![Build Status](https://travis-ci.org/boostorg/signals2.svg?branch=develop)](https://travis-ci.org/boostorg/signals2) | [![Build status](https://ci.appveyor.com/api/projects/status/vjbstowu1s13x4l5/branch/develop?svg=true)](https://ci.appveyor.com/project/jeking3/signals2-db91c/branch/develop) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/15884/badge.svg)](https://scan.coverity.com/projects/boostorg-signals2) | [![codecov](https://codecov.io/gh/boostorg/signals2/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/signals2/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/signals2.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/develop/doc/html/signals2.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](https://regression.boost.io/develop/developer/signals2.html) 18 | 19 | ### Directories 20 | 21 | | Name | Purpose | 22 | | ----------- | ------------------------------ | 23 | | `ci` | continuous integration scripts | 24 | | `doc` | documentation | 25 | | `example` | examples | 26 | | `include` | headers | 27 | | `test` | unit tests | 28 | 29 | ### More information 30 | 31 | * [Ask questions](http://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-signals2) 32 | * [Report bugs](https://github.com/boostorg/signals2/issues): Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well. 33 | * Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). 34 | * Discussions about the library are held on the [Boost developers mailing list](http://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](http://www.boost.org/community/policy.html) before posting and add the `[signals2]` tag at the beginning of the subject line. 35 | 36 | -------------------------------------------------------------------------------- /include/boost/signals2/slot_base.hpp: -------------------------------------------------------------------------------- 1 | // Boost.Signals2 library 2 | 3 | // Copyright Frank Mori Hess 2007-2008. 4 | // Copyright Timmo Stange 2007. 5 | // Copyright Douglas Gregor 2001-2004. Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // For more information, see http://www.boost.org 11 | 12 | #ifndef BOOST_SIGNALS2_SLOT_BASE_HPP 13 | #define BOOST_SIGNALS2_SLOT_BASE_HPP 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace boost 26 | { 27 | namespace signals2 28 | { 29 | namespace detail 30 | { 31 | class tracked_objects_visitor; 32 | class trackable_pointee; 33 | 34 | typedef boost::variant, boost::weak_ptr, detail::foreign_void_weak_ptr > void_weak_ptr_variant; 35 | typedef boost::variant, detail::foreign_void_shared_ptr > void_shared_ptr_variant; 36 | class lock_weak_ptr_visitor 37 | { 38 | public: 39 | typedef void_shared_ptr_variant result_type; 40 | template 41 | result_type operator()(const WeakPtr &wp) const 42 | { 43 | return wp.lock(); 44 | } 45 | // overload to prevent incrementing use count of shared_ptr associated 46 | // with signals2::trackable objects 47 | result_type operator()(const weak_ptr &) const 48 | { 49 | return boost::shared_ptr(); 50 | } 51 | }; 52 | class expired_weak_ptr_visitor 53 | { 54 | public: 55 | typedef bool result_type; 56 | template 57 | bool operator()(const WeakPtr &wp) const 58 | { 59 | return wp.expired(); 60 | } 61 | }; 62 | } 63 | 64 | class slot_base 65 | { 66 | public: 67 | typedef std::vector tracked_container_type; 68 | typedef std::vector locked_container_type; 69 | 70 | const tracked_container_type& tracked_objects() const {return _tracked_objects;} 71 | locked_container_type lock() const 72 | { 73 | locked_container_type locked_objects; 74 | tracked_container_type::const_iterator it; 75 | for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it) 76 | { 77 | locked_objects.push_back(apply_visitor(detail::lock_weak_ptr_visitor(), *it)); 78 | if(apply_visitor(detail::expired_weak_ptr_visitor(), *it)) 79 | { 80 | boost::throw_exception(expired_slot()); 81 | } 82 | } 83 | return locked_objects; 84 | } 85 | bool expired() const 86 | { 87 | tracked_container_type::const_iterator it; 88 | for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it) 89 | { 90 | if(apply_visitor(detail::expired_weak_ptr_visitor(), *it)) return true; 91 | } 92 | return false; 93 | } 94 | protected: 95 | friend class detail::tracked_objects_visitor; 96 | 97 | void track_signal(const signal_base &signal) 98 | { 99 | _tracked_objects.push_back(signal.lock_pimpl()); 100 | } 101 | 102 | tracked_container_type _tracked_objects; 103 | }; 104 | } 105 | } // end namespace boost 106 | 107 | #endif // BOOST_SIGNALS2_SLOT_BASE_HPP 108 | -------------------------------------------------------------------------------- /test/connection_test.cpp: -------------------------------------------------------------------------------- 1 | // Signals2 library 2 | // tests for connection class 3 | 4 | // Copyright Frank Mori Hess 2008 5 | // Use, modification and 6 | // distribution is subject to the Boost Software License, Version 7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // For more information, see http://www.boost.org 11 | #include 12 | #define BOOST_TEST_MODULE connection_test 13 | #include 14 | 15 | namespace bs2 = boost::signals2; 16 | 17 | typedef bs2::signal sig_type; 18 | 19 | void myslot() 20 | {} 21 | 22 | void swap_test() 23 | { 24 | sig_type sig; 25 | 26 | { 27 | bs2::connection conn1 = sig.connect(&myslot); 28 | BOOST_CHECK(conn1.connected()); 29 | bs2::connection conn2; 30 | BOOST_CHECK(conn2.connected() == false); 31 | 32 | conn1.swap(conn2); 33 | BOOST_CHECK(conn2.connected()); 34 | BOOST_CHECK(conn1.connected() == false); 35 | 36 | swap(conn1, conn2); 37 | BOOST_CHECK(conn1.connected()); 38 | BOOST_CHECK(conn2.connected() == false); 39 | } 40 | 41 | { 42 | bs2::scoped_connection conn1; 43 | conn1 = sig.connect(&myslot); 44 | BOOST_CHECK(conn1.connected()); 45 | bs2::scoped_connection conn2; 46 | BOOST_CHECK(conn2.connected() == false); 47 | 48 | conn1.swap(conn2); 49 | BOOST_CHECK(conn2.connected()); 50 | BOOST_CHECK(conn1.connected() == false); 51 | 52 | swap(conn1, conn2); 53 | BOOST_CHECK(conn1.connected()); 54 | BOOST_CHECK(conn2.connected() == false); 55 | } 56 | } 57 | 58 | void release_test() 59 | { 60 | sig_type sig; 61 | bs2::connection conn; 62 | { 63 | bs2::scoped_connection scoped(sig.connect(&myslot)); 64 | BOOST_CHECK(scoped.connected()); 65 | conn = scoped.release(); 66 | } 67 | BOOST_CHECK(conn.connected()); 68 | 69 | bs2::connection conn2; 70 | { 71 | bs2::scoped_connection scoped(conn); 72 | BOOST_CHECK(scoped.connected()); 73 | conn = scoped.release(); 74 | BOOST_CHECK(conn.connected()); 75 | BOOST_CHECK(scoped.connected() == false); 76 | conn.disconnect(); 77 | 78 | // earlier release shouldn't affect new connection 79 | conn2 = sig.connect(&myslot); 80 | scoped = conn2; 81 | } 82 | BOOST_CHECK(conn2.connected() == false); 83 | } 84 | 85 | void move_test() 86 | { 87 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 88 | sig_type sig; 89 | bs2::connection conn; 90 | // test move assignment from scoped_connection to connection 91 | { 92 | bs2::scoped_connection scoped(sig.connect(&myslot)); 93 | BOOST_CHECK(scoped.connected()); 94 | conn = std::move(scoped); 95 | BOOST_CHECK(scoped.connected() == false); 96 | } 97 | BOOST_CHECK(conn.connected()); 98 | 99 | // test move construction from scoped to scoped 100 | { 101 | bs2::scoped_connection scoped2(conn); 102 | BOOST_CHECK(scoped2.connected()); 103 | bs2::scoped_connection scoped3(std::move(scoped2)); 104 | BOOST_CHECK(scoped2.connected() == false); 105 | BOOST_CHECK(scoped3.connected() == true); 106 | BOOST_CHECK(conn.connected() == true); 107 | } 108 | BOOST_CHECK(conn.connected() == false); 109 | 110 | // test move assignment from scoped to scoped 111 | conn = sig.connect(&myslot); 112 | { 113 | bs2::scoped_connection scoped3; 114 | bs2::scoped_connection scoped2(conn); 115 | BOOST_CHECK(scoped2.connected()); 116 | scoped3 = std::move(scoped2); 117 | BOOST_CHECK(scoped2.connected() == false); 118 | BOOST_CHECK(scoped3.connected() == true); 119 | BOOST_CHECK(conn.connected() == true); 120 | } 121 | BOOST_CHECK(conn.connected() == false); 122 | #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 123 | } 124 | 125 | BOOST_AUTO_TEST_CASE(test_main) 126 | { 127 | release_test(); 128 | swap_test(); 129 | move_test(); 130 | } 131 | -------------------------------------------------------------------------------- /test/regression_test.cpp: -------------------------------------------------------------------------------- 1 | // thread_safe_signals library 2 | // Some assorted tests to expose various bugs that existed at some point, 3 | // to make sure they stay fixed 4 | 5 | // Copyright Frank Mori Hess 2008 6 | // Use, modification and 7 | // distribution is subject to the Boost Software License, Version 8 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | 11 | // For more information, see http://www.boost.org 12 | 13 | #include 14 | #define BOOST_TEST_MODULE regression_test 15 | #include 16 | #include 17 | 18 | typedef boost::signals2::signal sig0_type; 19 | 20 | // combiner that returns the number of slots invoked 21 | struct slot_counter { 22 | typedef unsigned result_type; 23 | template 24 | unsigned operator()(InputIterator first, InputIterator last) const 25 | { 26 | unsigned count = 0; 27 | for (; first != last; ++first) 28 | { 29 | try 30 | { 31 | *first; 32 | ++count; 33 | } 34 | catch(const boost::bad_weak_ptr &) 35 | {} 36 | } 37 | return count; 38 | } 39 | }; 40 | 41 | void my_slot() 42 | { 43 | } 44 | 45 | void my_connecting_slot(sig0_type &sig) 46 | { 47 | sig.connect(&my_slot); 48 | } 49 | 50 | void slot_connect_test() 51 | { 52 | sig0_type sig; 53 | sig.connect(sig0_type::slot_type(&my_connecting_slot, boost::ref(sig)).track(sig)); 54 | /* 2008-02-28: the following signal invocation triggered a (bogus) failed assertion of _shared_state.unique() 55 | at detail/signal_template.hpp:285 */ 56 | sig(); 57 | BOOST_CHECK(sig.num_slots() == 2); 58 | sig.disconnect(&my_slot); 59 | BOOST_CHECK(sig.num_slots() == 1); 60 | /* 2008-03-11: checked iterator barfed on next line, due to bad semantics of copy construction 61 | for boost::signals2::detail::grouped_list */ 62 | sig(); 63 | BOOST_CHECK(sig.num_slots() == 2); 64 | } 65 | 66 | /* 2008-03-10: we weren't disconnecting old connection in scoped_connection assignment operator */ 67 | void scoped_connection_test() 68 | { 69 | typedef boost::signals2::signal signal_type; 70 | signal_type sig; 71 | { 72 | boost::signals2::scoped_connection conn(sig.connect(&my_slot)); 73 | BOOST_CHECK(sig() == 1); 74 | conn = sig.connect(&my_slot); 75 | BOOST_CHECK(sig() == 1); 76 | } 77 | BOOST_CHECK(sig() == 0); 78 | } 79 | 80 | // testsignal that returns a reference type 81 | 82 | struct ref_returner 83 | { 84 | static int i; 85 | 86 | int& ref_return_slot() 87 | { 88 | return i; 89 | } 90 | }; 91 | 92 | int ref_returner::i = 0; 93 | 94 | void reference_return_test() 95 | { 96 | boost::signals2::signal rTest; 97 | ref_returner rr; 98 | rTest.connect(boost::bind(&ref_returner::ref_return_slot, &rr)); 99 | int& r = *rTest(); 100 | BOOST_CHECK(ref_returner::i == 0); 101 | r = 1; 102 | BOOST_CHECK(ref_returner::i == 1); 103 | } 104 | 105 | 106 | // disconnecting a function pointer by passing the function without an explicit 107 | // address-of operator fails to compile in boost 1.83 due to 108 | // commit 7a16fc1405f01e13463b6ce7723f30f40ba41fa4 109 | 110 | void foo() { } 111 | 112 | void disconnect_by_function_test() 113 | { 114 | boost::signals2::signal sig; 115 | sig.connect(foo); 116 | sig.disconnect(foo); // compile failure in boost 1.83 117 | } 118 | 119 | // returning a move-only type from optional_last_value produced compile error 120 | void return_move_only_test() 121 | { 122 | boost::signals2::signal()> sig; 123 | sig(); // error: overload resolution selected deleted operator '=' 124 | } 125 | 126 | BOOST_AUTO_TEST_CASE(test_main) 127 | { 128 | slot_connect_test(); 129 | scoped_connection_test(); 130 | reference_return_test(); 131 | disconnect_by_function_test(); 132 | return_move_only_test(); 133 | } 134 | -------------------------------------------------------------------------------- /example/doc_view_acm_deconstruct.cpp: -------------------------------------------------------------------------------- 1 | // Document/View sample for Boost.Signals2. 2 | // Expands on doc_view_acm.cpp example by using boost::signals2::deconstruct 3 | // as a post-constructing factory function. 4 | // 5 | // Copyright Keith MacDonald 2005. 6 | // Copyright Frank Mori Hess 2009. 7 | // 8 | // Use, modification and 9 | // distribution is subject to the Boost Software License, Version 10 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 11 | // http://www.boost.org/LICENSE_1_0.txt) 12 | // For more information, see http://www.boost.org 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | class Document 23 | { 24 | public: 25 | typedef boost::signals2::signal signal_t; 26 | 27 | public: 28 | Document() 29 | {} 30 | 31 | /* Connect a slot to the signal which will be emitted whenever 32 | text is appended to the document. */ 33 | boost::signals2::connection connect(const signal_t::slot_type &subscriber) 34 | { 35 | return m_sig.connect(subscriber); 36 | } 37 | 38 | void append(const char* s) 39 | { 40 | m_text += s; 41 | m_sig(); 42 | } 43 | 44 | const std::string& getText() const 45 | { 46 | return m_text; 47 | } 48 | 49 | private: 50 | signal_t m_sig; 51 | std::string m_text; 52 | }; 53 | 54 | class TextView 55 | { 56 | public: 57 | /* This adl_postconstruct function will be found 58 | via argument-dependent lookup when using boost::signals2::deconstruct. */ 59 | template 60 | friend void adl_postconstruct(const boost::shared_ptr &view_sp, TextView *view, Document& doc) 61 | { 62 | view->m_document = &doc; 63 | { 64 | typedef Document::signal_t::slot_type slot_type; 65 | slot_type myslot(&TextView::refresh, view); 66 | doc.connect(myslot.track(view_sp)); 67 | } 68 | } 69 | 70 | void refresh() const 71 | { 72 | std::cout << "TextView: " << m_document->getText() << std::endl; 73 | } 74 | private: 75 | // give boost::signals2::deconstruct access to private constructor 76 | friend class boost::signals2::deconstruct_access; 77 | // private constructor to force use of deconstruct 78 | TextView() : m_document(0) 79 | {} 80 | 81 | Document* m_document; 82 | }; 83 | 84 | class HexView 85 | { 86 | public: 87 | /* This adl_postconstruct function will be found 88 | via argument-dependent lookup when using boost::signals2::deconstruct. */ 89 | template 90 | friend void adl_postconstruct(const boost::shared_ptr &view_sp, HexView *view, Document& doc) 91 | { 92 | view->m_document = &doc; 93 | { 94 | typedef Document::signal_t::slot_type slot_type; 95 | slot_type myslot(&HexView::refresh, view); 96 | doc.connect(myslot.track(view_sp)); 97 | } 98 | } 99 | 100 | void refresh() const 101 | { 102 | const std::string& s = m_document->getText(); 103 | 104 | std::cout << "HexView:"; 105 | 106 | for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) 107 | std::cout << ' ' << std::hex << static_cast(*it); 108 | 109 | std::cout << std::endl; 110 | } 111 | private: 112 | // give boost::signals2::deconstruct access to private constructor 113 | friend class boost::signals2::deconstruct_access; 114 | // private constructor to force use of deconstruct 115 | HexView(): m_document(0) 116 | {} 117 | 118 | Document* m_document; 119 | }; 120 | 121 | namespace bs2 = boost::signals2; 122 | 123 | int main(int argc, char* argv[]) 124 | { 125 | Document doc; 126 | boost::shared_ptr v1 = bs2::deconstruct().postconstruct(boost::ref(doc)); 127 | boost::shared_ptr v2 = bs2::deconstruct().postconstruct(boost::ref(doc)); 128 | 129 | doc.append(argc >= 2 ? argv[1] : "Hello world!"); 130 | 131 | v2.reset(); // destroy the HexView, automatically disconnecting 132 | doc.append(" HexView should no longer be connected."); 133 | 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto !eol svneol=native#text/plain 2 | *.gitattributes text svneol=native#text/plain 3 | 4 | # Scriptish formats 5 | *.bat text svneol=native#text/plain 6 | *.bsh text svneol=native#text/x-beanshell 7 | *.cgi text svneol=native#text/plain 8 | *.cmd text svneol=native#text/plain 9 | *.js text svneol=native#text/javascript 10 | *.php text svneol=native#text/x-php 11 | *.pl text svneol=native#text/x-perl 12 | *.pm text svneol=native#text/x-perl 13 | *.py text svneol=native#text/x-python 14 | *.sh eol=lf svneol=LF#text/x-sh 15 | configure eol=lf svneol=LF#text/x-sh 16 | 17 | # Image formats 18 | *.bmp binary svneol=unset#image/bmp 19 | *.gif binary svneol=unset#image/gif 20 | *.ico binary svneol=unset#image/ico 21 | *.jpeg binary svneol=unset#image/jpeg 22 | *.jpg binary svneol=unset#image/jpeg 23 | *.png binary svneol=unset#image/png 24 | *.tif binary svneol=unset#image/tiff 25 | *.tiff binary svneol=unset#image/tiff 26 | *.svg text svneol=native#image/svg%2Bxml 27 | 28 | # Data formats 29 | *.pdf binary svneol=unset#application/pdf 30 | *.avi binary svneol=unset#video/avi 31 | *.doc binary svneol=unset#application/msword 32 | *.dsp text svneol=crlf#text/plain 33 | *.dsw text svneol=crlf#text/plain 34 | *.eps binary svneol=unset#application/postscript 35 | *.gz binary svneol=unset#application/gzip 36 | *.mov binary svneol=unset#video/quicktime 37 | *.mp3 binary svneol=unset#audio/mpeg 38 | *.ppt binary svneol=unset#application/vnd.ms-powerpoint 39 | *.ps binary svneol=unset#application/postscript 40 | *.psd binary svneol=unset#application/photoshop 41 | *.rdf binary svneol=unset#text/rdf 42 | *.rss text svneol=unset#text/xml 43 | *.rtf binary svneol=unset#text/rtf 44 | *.sln text svneol=native#text/plain 45 | *.swf binary svneol=unset#application/x-shockwave-flash 46 | *.tgz binary svneol=unset#application/gzip 47 | *.vcproj text svneol=native#text/xml 48 | *.vcxproj text svneol=native#text/xml 49 | *.vsprops text svneol=native#text/xml 50 | *.wav binary svneol=unset#audio/wav 51 | *.xls binary svneol=unset#application/vnd.ms-excel 52 | *.zip binary svneol=unset#application/zip 53 | 54 | # Text formats 55 | .htaccess text svneol=native#text/plain 56 | *.bbk text svneol=native#text/xml 57 | *.cmake text svneol=native#text/plain 58 | *.css text svneol=native#text/css 59 | *.dtd text svneol=native#text/xml 60 | *.htm text svneol=native#text/html 61 | *.html text svneol=native#text/html 62 | *.ini text svneol=native#text/plain 63 | *.log text svneol=native#text/plain 64 | *.mak text svneol=native#text/plain 65 | *.qbk text svneol=native#text/plain 66 | *.rst text svneol=native#text/plain 67 | *.sql text svneol=native#text/x-sql 68 | *.txt text svneol=native#text/plain 69 | *.xhtml text svneol=native#text/xhtml%2Bxml 70 | *.xml text svneol=native#text/xml 71 | *.xsd text svneol=native#text/xml 72 | *.xsl text svneol=native#text/xml 73 | *.xslt text svneol=native#text/xml 74 | *.xul text svneol=native#text/xul 75 | *.yml text svneol=native#text/plain 76 | boost-no-inspect text svneol=native#text/plain 77 | CHANGES text svneol=native#text/plain 78 | COPYING text svneol=native#text/plain 79 | INSTALL text svneol=native#text/plain 80 | Jamfile text svneol=native#text/plain 81 | Jamroot text svneol=native#text/plain 82 | Jamfile.v2 text svneol=native#text/plain 83 | Jamrules text svneol=native#text/plain 84 | Makefile* text svneol=native#text/plain 85 | README text svneol=native#text/plain 86 | TODO text svneol=native#text/plain 87 | 88 | # Code formats 89 | *.c text svneol=native#text/plain 90 | *.cpp text svneol=native#text/plain 91 | *.h text svneol=native#text/plain 92 | *.hpp text svneol=native#text/plain 93 | *.ipp text svneol=native#text/plain 94 | *.tpp text svneol=native#text/plain 95 | *.jam text svneol=native#text/plain 96 | *.java text svneol=native#text/plain 97 | -------------------------------------------------------------------------------- /doc/reference/trackable.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 11 |
12 | 13 | 14 | 15 | Provided to ease porting for code using the boost::signals::trackable class from 16 | the original Boost.Signals library. 17 | 18 | 19 | Use of the trackable class is not recommended 20 | for new code. The trackable class is not thread-safe 21 | since trackable objects disconnect their associated 22 | connections in the trackable destructor. 23 | Since the trackable destructor is not run until 24 | after the destructors of any derived classes have completed, 25 | that leaves open a window where a partially destructed 26 | object can still have active connections. 27 | 28 | 29 | 30 | The preferred method of automatic connection management 31 | with Boost.Signals2 is to manage the lifetime of 32 | tracked objects with shared_ptrs and 33 | to use the signals2::slot::track 34 | method to track their lifetimes. 35 | 36 | The trackable class provides automatic 37 | disconnection of signals and slots when objects bound in 38 | slots (via pointer or reference) are destroyed. 39 | trackable class may only be used as a public 40 | base class for some other class; when used as such, that 41 | class may be bound to function objects used as part of 42 | slots. The manner in which a trackable object 43 | tracks the set of signal-slot connections it is a part of is 44 | unspecified. 45 | 46 | The actual use of trackable is contingent 47 | on the presence of appropriate 48 | visit_each overloads for any 49 | type that may contain pointers or references to trackable 50 | objects. 51 | 52 | 53 | 54 | 55 | Sets the list of connected slots to empty. 56 | Will not throw. 57 | 58 | 59 | 60 | 61 | const trackable& 62 | 63 | 64 | Sets the list of connected slots to empty. 65 | Will not throw. 66 | Signal-slot connections can only be created via calls to an explicit connect method, and therefore cannot be created here when trackable objects are copied. 67 | 68 | 69 | 70 | Disconnects all signal/slot connections that 71 | contain a pointer or reference to this trackable object that 72 | can be found by 73 | visit_each. 74 | 75 | 76 | 77 | 78 | const trackable& 79 | 80 | 81 | Sets the list of connected slots to empty. 82 | *this 83 | Will not throw. 84 | Signal-slot connections can only be created via calls to an explicit connect method, and therefore cannot be created here when trackable objects are copied. 85 | 86 | 87 | 88 | 89 |
-------------------------------------------------------------------------------- /doc/reference/last_value.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 11 |
12 | 13 | 14 | 15 | 18 | 19 | Evaluate an InputIterator sequence and return the 20 | last value in the sequence. 21 | 22 | 23 | 24 | The last_value class was the default Combiner template parameter 25 | type for signals in the original Signals library. 26 | Signals2 uses optional_last_value as the default, which 27 | does not throw. 28 | 29 | 30 | 31 | T 32 | 33 | 34 | 35 | 38 | result_type 39 | 40 | InputIterator 41 | 42 | 43 | InputIterator 44 | 45 | 46 | Attempts to dereference every iterator in the sequence [first, last). 47 | 48 | The result of the last successful iterator dereference. 49 | no_slots_error if no iterators were successfully dereferenced, 50 | unless the template type of last_value is void. 51 | 52 | 53 | 54 | 55 | 56 |