Coder Social home page Coder Social logo

signals2's Introduction

Signals2, part of collection of the Boost C++ Libraries, is an implementation of a managed signals and slots system.

License

Distributed under the Boost Software License, Version 1.0.

Properties

  • C++03
  • Header-Only

Build Status

Branch Travis Appveyor Coverity Scan codecov.io Deps Docs Tests
master Build Status Build status Coverity Scan Build Status codecov Deps Documentation Enter the Matrix
develop Build Status Build status Coverity Scan Build Status codecov Deps Documentation Enter the Matrix

Directories

Name Purpose
ci continuous integration scripts
doc documentation
example examples
include headers
test unit tests

More information

  • Ask questions
  • Report bugs: 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.
  • 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.
  • Discussions about the library are held on the Boost developers mailing list. Be sure to read the discussion policy before posting and add the [signals2] tag at the beginning of the subject line.

signals2's People

Contributors

belcourt avatar beman avatar cromwellenage avatar danielae avatar danieljames avatar douggregor avatar eldiener avatar fanquake avatar florianbehrens avatar fmhess avatar glenfe avatar grafikrobot avatar hkaiser avatar jaredgrubb avatar jeking3 avatar joachim-faulhaber avatar k-satoda avatar marcelraad avatar mclow avatar mike-devel avatar pdimov avatar rick68 avatar romain-geissler-1a avatar sdarwin avatar steveire avatar stgates avatar straszheim avatar swatanabe avatar tobiaskohlbau avatar vprus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

signals2's Issues

C++20 Support for auto_buffer

Boost 1.74 Clang 11 macOS

The new standard C++20 https://en.cppreference.com/w/cpp/memory/allocator marks

size_type
difference_type

as deprecated:

/usr/local/opt/llvm/include/c++/v1/memory:

class _LIBCPP_TEMPLATE_VIS allocator
{
public:
#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS)
    _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t     size_type;
    _LIBCPP_DEPRECATED_IN_CXX17 typedef ptrdiff_t  difference_type;
    _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp*       pointer;
    _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer;
    _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp&       reference;
    _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& const_reference;

    template <class _Up> struct _LIBCPP_DEPRECATED_IN_CXX17 rebind {typedef allocator<_Up> other;};
#endif

    typedef _Tp value_type;

    typedef true_type propagate_on_container_move_assignment;
    typedef true_type is_always_equal;

    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    allocator() _NOEXCEPT {}

    template <class _Up>
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    allocator(const allocator<_Up>&) _NOEXCEPT {}

#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS)
    _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY
    pointer address(reference __x) const _NOEXCEPT
        {return _VSTD::addressof(__x);}
    _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY
    const_pointer address(const_reference __x) const _NOEXCEPT
        {return _VSTD::addressof(__x);}
#endif

    _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _Tp* allocate(size_t __n)
        {
        // TODO(mpark): Replace with `allocator_traits<allocator>::max_size(*this)`.
        if (__n > (size_t(~0) / sizeof(_Tp)))
            __throw_length_error("allocator<T>::allocate(size_t n)"
                                 " 'n' exceeds maximum supported size");
        return static_cast<_Tp*>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)));
        }

#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS)
    _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_IN_CXX17
    _Tp* allocate(size_t __n, const void*) { return allocate(__n); }
#endif

    _LIBCPP_INLINE_VISIBILITY void deallocate(_Tp* __p, size_t __n) _NOEXCEPT
        {_VSTD::__libcpp_deallocate((void*)__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));}

#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS)
    _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT
        {return size_type(~0) / sizeof(_Tp);}

    template <class _Up, class... _Args>
        _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY
        void
        construct(_Up* __p, _Args&&... __args)
        {
            ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
        }
    _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY void destroy(pointer __p) {__p->~_Tp();}
#endif
};

So compile signal2 library with -std=c++20 got an error:

/usr/local/include/boost/signals2/detail/auto_buffer.hpp:143:37: error: no type named 'size_type' in 'std::__1::allocator<boost::shared_ptr<void>>'
        typedef typename Allocator::size_type            size_type;
                ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
/usr/local/include/boost/signals2/connection.hpp:53:61: note: in instantiation of template class 'boost::signals2::detail::auto_buffer<boost::shared_ptr<void>, boost::signals2::detail::store_n_objects<10>, boost::signals2::detail::default_grow_policy, std::__1::allocator<boost::shared_ptr<void>>>' requested here
        auto_buffer<shared_ptr<void>, store_n_objects<10> > garbage;

Safe disconnection

As the documentation states: when I disconnect a slot, then there is a chance that an emission is running from another thread. This makes me some trouble with my application, because after disconnection I cannot be sure that my callback object is really not used any more.

I did not find (or overlooked) any solution in signals2. So I came up with a special scoped_connection, where I inject/capture a RAII tracker object into the slot (see the template constructor PostEmissionSafeConnection), so that in the connection I know when all slot copies are gone. The RAII tracker object (here: HandlerTrace) manipulates an atomic reference counter (TraceCounter) to keep track of the slot copies. By the way it was interesting to see how many copies of the slot object is created during registration (via the slot counter) - maybe that can be optimized too?

I wonder if there is a better solution to that or this implementation sketch can evolve into the signals2 library. I used here C++20, but it can be relaxed.

What do you think about this idea?

#include <latch>
#include <future>
#include <thread>
#include <chrono>
#include <cassert>

class PostEmissionSafeConnection : public boost::signals2::scoped_connection
{
public:
    template <typename TSignal, typename THandler>
    PostEmissionSafeConnection(TSignal &signal, const THandler &handler)
        : counter_(std::make_unique<TraceCounter>())
    {
        auto trackedHandler = [handlerTrace = HandlerTrace(*(counter_.get())), handler] { handler(); };
        boost::signals2::scoped_connection::operator=(signal.connect(std::move(trackedHandler)));
    }

    PostEmissionSafeConnection(const PostEmissionSafeConnection &) = delete;
    PostEmissionSafeConnection &operator=(const PostEmissionSafeConnection &) = delete;

    PostEmissionSafeConnection(PostEmissionSafeConnection &&other)
        : boost::signals2::scoped_connection::scoped_connection(std::move(other))
        , counter_(std::move(other.counter_))
    { }

    PostEmissionSafeConnection &operator=(PostEmissionSafeConnection &&other)
    {
        Release();

        boost::signals2::scoped_connection::operator=(std::move(other));
        counter_ = std::move(other.counter_);

        return *this;
    }

    ~PostEmissionSafeConnection() { Release(); }

    // The base class methods can be used
    // disconnect(), connected(), blocked() etc.
    // The only thing is: this class blocks at the destructor until all handlers are released

private:
    // A shared counter, which tracks the living Trace instances
    // NOTE: This object is on the heap. This pins down its address, so the Trace-es can refer to it via
    // a C++ reference. The Connection can be moved, because that also refers to this fixed address counter.
    struct TraceCounter
    {
        void RegisterCreation()
        {
            auto currentTraceCount = traceCount_.load();
            assert(traceCount_ == 0);
            for (;;)
            {
                auto incrementedTraceCount = currentTraceCount + 1;

                const bool exchanged = traceCount_.compare_exchange_strong(
                    currentTraceCount, incrementedTraceCount, std::memory_order_release, std::memory_order_relaxed);

                if (exchanged)
                    break;
            }
        }

        void RegisterCopy()
        {
            auto currentTraceCount = traceCount_.load();
            assert(currentTraceCount > 0);
            for (;;)
            {
                auto incrementedTraceCount = currentTraceCount + 1;

                const bool exchanged = traceCount_.compare_exchange_strong(
                    currentTraceCount, incrementedTraceCount, std::memory_order_release, std::memory_order_relaxed);

                if (exchanged)
                    break;
            }
        }

        void UnRegister()
        {
            auto currentTraceCount = traceCount_.load();
            assert(currentTraceCount > 0);
            for (;;)
            {
                auto decrementedTraceCount = currentTraceCount - 1;

                const bool exchanged = traceCount_.compare_exchange_strong(
                    currentTraceCount, decrementedTraceCount, std::memory_order_release, std::memory_order_relaxed);

                if (exchanged)
                    break;
            }
        }

        void WaitForLastHandlerTrace()
        {
            for (;;)
            {
                auto currentTraceCount = traceCount_.load();

                if (currentTraceCount == 0)
                    break;

                using namespace std::literals;
                std::this_thread::sleep_for(1ms);
            }
        }

        std::atomic<std::size_t> traceCount_ = 0;
    };

    // RAII object captured in the handler, so that we can keep track of the living handlers
    struct HandlerTrace
    {
        HandlerTrace() = delete;

        HandlerTrace(TraceCounter &counter)
            : counter_(&counter)
        {
            counter_->RegisterCreation();
        }

        HandlerTrace(const HandlerTrace &other)
            : counter_(other.counter_)
        {
            counter_->RegisterCopy();
        }

        HandlerTrace &operator=(const HandlerTrace &other)
        {
            counter_ = other.counter_;
            counter_->RegisterCopy();
            return *this;
        }

        HandlerTrace(HandlerTrace &&other)
            : counter_(other.counter_)
        {
            other.counter_ = nullptr;
        }

        HandlerTrace &operator=(HandlerTrace &&other)
        {
            counter_ = other.counter_;
            other.counter_ = nullptr;
            return *this;
        }

        ~HandlerTrace()
        {
            if (counter_)
                counter_->UnRegister();
        }

        TraceCounter *counter_ = nullptr;
    };

    void Release()
    {
        if (!counter_)
            return;

        disconnect();
        counter_->WaitForLastHandlerTrace();
        counter_.reset();
    }

    std::unique_ptr<TraceCounter> counter_;
};

TEST(SignalTest, PostUnsubscriptionEmission)
{
    // The handler must outlive all traces
    boost::signals2::signal<void()> signal;

    std::latch latch(2);
    PostEmissionSafeConnection connection(signal, [&latch] {
        latch.count_down();
        using namespace std::literals;
        std::this_thread::sleep_for(2s);
        std::this_thread::sleep_for(2s);
    });

    std::thread signalSenderThread([&signal] { signal(); });
    signalSenderThread.detach();

    latch.arrive_and_wait();
    connection.disconnect();

    // the connection blocks its destruction until all handler instances are destroyed.
}

Incompatibility with C++20

In C++20 from std::allocator was removed some typedef's, and boost/signals2.hpp can't even compile:

test.cpp:

#include <boost/signals2.hpp>

auto main(void) -> int
{
    return 0;
}

Compiler output:

➜  /tmp g++-10 -std=c++20 -Og test.cpp -o test
In file included from /usr/include/boost/signals2/connection.hpp:21,
                 from /usr/include/boost/signals2/signal.hpp:22,
                 from /usr/include/boost/signals2.hpp:19,
                 from test.cpp:1:
/usr/include/boost/signals2/detail/auto_buffer.hpp: In instantiation of ‘class boost::signals2::detail::auto_buffer<boost::shared_ptr<void>, boost::signals2::detail::store_n_objects<10> >’:
/usr/include/boost/signals2/connection.hpp:53:61:   required from here
/usr/include/boost/signals2/detail/auto_buffer.hpp:145:58: error: no type named ‘pointer’ in ‘class std::allocator<boost::shared_ptr<void> >’
  145 |         typedef typename Allocator::pointer              allocator_pointer;
      |                                                          ^~~~~~~~~~~~~~~~~
/usr/include/boost/signals2/detail/auto_buffer.hpp: In instantiation of ‘class boost::signals2::detail::auto_buffer<boost::variant<boost::shared_ptr<void>, boost::signals2::detail::foreign_void_shared_ptr>, boost::signals2::detail::store_n_objects<10> >’:
/usr/include/boost/signals2/detail/slot_call_iterator.hpp:65:27:   required from here
/usr/include/boost/signals2/detail/auto_buffer.hpp:145:58: error: no type named ‘pointer’ in ‘class std::allocator<boost::variant<boost::shared_ptr<void>, boost::signals2::detail::foreign_void_shared_ptr> >’

VS2019 / C++ 17, signal::disconnect compile error: syntax error: 'template'

Using custom functor, Signals fail to compile with:
signal_template.hpp(537,50): error C2059: syntax error: 'template'

Here:

              // check for wrapped extended slot
              bound_extended_slot_function_type *fp;
              fp = (*it)->slot().slot_function().template target<bound_extended_slot_function_type>();

The reason behind is that the signal expects the functor to be the boost::function / std::function, that would contain the target() method.

Minimal example:

struct MyFunctorThisComparer
{
	MyFunctorThisComparer(const void* this_) {}
	bool operator==(const MyFunctorThisComparer& other) const { return true; }
};

struct MyFunctor
{
	typedef void result_type;

	template<typename F>
	void operator=(F) {}
	void operator()() {}

	// disconnect by comparison with custom predicate
	bool operator==(const MyFunctorThisComparer& other) const { return true; }
	operator MyFunctorThisComparer() const { return MyFunctorThisComparer { nullptr }; }
};

void signals_disconnect()
{
	boost::signals2::signal<
		void(), 
		//SignalSupport_::AllCall<typename boost::function_traits<void()>::result_type>,
		boost::signals2::optional_last_value<typename boost::function_traits<void()>::result_type>,
		int,
		std::less<int>,
		MyFunctor > s;

	s.connect( &signals_disconnect );
	s.disconnect( MyFunctorThisComparer(nullptr) );
}

I attempted here to provide the equivalence MyFunctorThisComparer predicate, that would filter out functors. In particular, it would know how to extract 'this' pointer from MyFunctor. However, it could be a more generic predicate.

Boost 1.72.0. However, I have checked the development version - it has the same lines there, so the issue is still present.

VS 2022 / c++20 signal2 disconnect compilation fail

Hi,

We have a compilation issue with VS 2022 / c++20. It compiles fine with c++17.
This code doesn't compile anymore:

class CTest
{
public:
	CTest()
	{
		boost::signals2::signal<void()> mySignal;
		mySignal.connect(boost::bind(&CTest::Method, this));
		mySignal.disconnect(boost::bind(&CTest::Method, this));
	}

	void Method()
	{}
};

Is there any workaround ?

Crashes LLDB on Windows

When using clang++ with c++20 the debugger crashes with the following message

error: example.exe :: Class 'std::strong_ordering' has a member 'less' of type 'std::strong_ordering' which does not have a complete definition.
error: example.exe :: Class 'std::partial_ordering' has a member 'less' of type 'std::partial_ordering' which does not have a complete definition.
error: example.exe :: Class 'std::weak_ordering' has a member 'less' of type 'std::weak_ordering' which does not have a complete definition.
Debug adapter exit code=3221225477 (0xc0000005), signal=null.

Repository with simple reproductible example: https://github.com/everdrone/clang_signals2

  • Clang version:
clang version 15.0.7
Target: x86_64-pc-windows-msvc
Thread model: posix
  • Windows 11, 22621
  • Boost 1.81.0
  • CMake 3.26.3
  • C++20

clang-tidy is reporting "Use of memory after it is freed"

Hi, do you think it is misreporting? If it is I would like to suppress the warning

#include <boost/signals2.hpp>

int main()
{
  boost::signals2::signal<void ()> sig;
  sig.connect([]{});
  sig();
}

The output of clang-tidy

❯ clang-tidy-14 --checks='clang-diag*' ../a.cpp
1 warning generated.
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/shared_count.hpp:586:22: warning: Use of memory after it is freed [clang-analyzer-cplusplus.NewDelete]
        if(pi_ != 0) pi_->weak_release();
                     ^
/tmp/foo/a.cpp:10:3: note: Calling 'signal::connect'
  sig.connect([]{});
  ^~~~~~~~~~~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/detail/signal_template.hpp:691:16: note: Calling 'signal_impl::connect'
        return (*_pimpl).connect(slot, position);
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/detail/signal_template.hpp:164:18: note: Calling 'signal_impl::nolock_connect'
          return nolock_connect(lock, slot, position);
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/detail/signal_template.hpp:552:14: note: 'position' is equal to at_back
          if(position == at_back)
             ^~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/detail/signal_template.hpp:552:11: note: Taking true branch
          if(position == at_back)
          ^
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/detail/signal_template.hpp:562:29: note: Calling implicit destructor for 'weak_ptr<boost::signals2::detail::connection_body_base>'
          return connection(newConnectionBody);
                            ^
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/detail/signal_template.hpp:562:29: note: Calling '~weak_count'
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/shared_count.hpp:586:12: note: Field 'pi_' is not equal to null
        if(pi_ != 0) pi_->weak_release();
           ^
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/shared_count.hpp:586:9: note: Taking true branch
        if(pi_ != 0) pi_->weak_release();
        ^
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/shared_count.hpp:586:22: note: Calling 'sp_counted_base::weak_release'
        if(pi_ != 0) pi_->weak_release();
                     ^~~~~~~~~~~~~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp:132:13: note: Assuming the condition is true
        if( atomic_decrement( &weak_count_ ) == 1 )
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp:132:9: note: Taking true branch
        if( atomic_decrement( &weak_count_ ) == 1 )
        ^
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp:134:13: note: Calling 'sp_counted_base::destroy'
            destroy();
            ^~~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp:99:9: note: Memory is released
        delete this;
        ^~~~~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp:134:13: note: Returning; memory was released
            destroy();
            ^~~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/shared_count.hpp:586:22: note: Returning; memory was released
        if(pi_ != 0) pi_->weak_release();
                     ^~~~~~~~~~~~~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/detail/signal_template.hpp:562:29: note: Returning from '~weak_count'
          return connection(newConnectionBody);
                            ^
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/detail/signal_template.hpp:562:29: note: Returning from destructor for 'weak_ptr<boost::signals2::detail::connection_body_base>'
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/detail/signal_template.hpp:164:18: note: Returning; memory was released
          return nolock_connect(lock, slot, position);
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/detail/signal_template.hpp:691:16: note: Returning; memory was released
        return (*_pimpl).connect(slot, position);
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/foo/a.cpp:10:3: note: Returning; memory was released
  sig.connect([]{});
  ^~~~~~~~~~~~~~~~~
/tmp/foo/a.cpp:10:19: note: Calling '~connection'
  sig.connect([]{});
                  ^
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/connection.hpp:265:22: note: Calling implicit destructor for 'weak_ptr<boost::signals2::detail::connection_body_base>'
      ~connection() {}
                     ^
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/signals2/connection.hpp:265:22: note: Calling '~weak_count'
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/shared_count.hpp:586:12: note: Field 'pi_' is not equal to null
        if(pi_ != 0) pi_->weak_release();
           ^
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/shared_count.hpp:586:9: note: Taking true branch
        if(pi_ != 0) pi_->weak_release();
        ^
/home/hg/.conan/data/boost/1.78.0/_/_/package/cfef62e446e1bb07894de4523f2649afdfa94524/include/boost/smart_ptr/detail/shared_count.hpp:586:22: note: Use of memory after it is freed
        if(pi_ != 0) pi_->weak_release();

Change in allowed code with boost 1.83

The following example code used to compile with boost 1.81 but not with 1.83. Likely a behavior change after 7a16fc1.

#include <iostream>
#include <boost/signals2/signal.hpp>

void foo() { std::cout << "foo" << std::endl; }
void bar() { std::cout << "bar" << std::endl; }

int main() {
  boost::signals2::signal<void ()> sig;
  sig.connect(foo);
  sig.connect(bar);
  sig.disconnect(bar);
  sig();
}

The above faiils to compile with:

/usr/include/boost/function/function_base.hpp:651:14: error: invalid ‘static_cast’ from type
‘boost::detail::function::function_buffer_members::obj_ptr_t’ {aka ‘void*’} to type ‘void (*)()’
  651 |       return static_cast<const Functor*>(type_result.members.obj_ptr);

Changing the disconnect call to sig.disconnect(&bar); allows it to compile. I'm just not sure if this is expected or not, so I thought I'd ask anyway.

signal_template.hpp uses 'new' to create shared_ptr when it should use make_shared

boost_1_78_0\boost\signals2\detail\signal_template.hpp lines 156, 309, 478, 500, and 513 use 'new' when make_shared would be more efficient. ( There's probably even more places in the code base that could use make_shared, but lines 156, and 513 were the ones flagged by the profiler, and are unnecessary bottlenecks).

Calling new to create a shared pointer forces an additional allocation for the shared count (new sp_counted_impl_p).
Using make_shared, on the other hand, combines the allocations into one, thereby cutting the total number of allocations/deallocations in half.

compile error on C++20

I got following compile error when I compile boost signals2 with -std=c++2a.
Reason for error is std::allocator::pointer is deprecated in C++17 and removed in C++20.

/usr/include/boost/signals2/connection.hpp|53 col 61| required from here
/usr/include/boost/signals2/detail/auto_buffer.hpp|145 col 58| error: no type named ‘pointer’ in ‘class std::allocator<boost::shared_ptr<void> >’
||   145 |         typedef typename Allocator::pointer              allocator_pointer;
||       |                                                          ^~~~~~~~~~~~~~~~~

Compilation failure under clang-11 -stdlib=libc++ -std=c++20

Test program:

#include <boost/signals2.hpp>
int main()
{
}

clang-11 -stdlib=libc++ -std=c++20 test.cpp

I apprears that the code relies on the presence of std::allocator::difference_type etc [which were removed in c++20 ?]

Error output:

In file included from <source>:1:

In file included from /celibs/boost_1_74_0/boost/signals2.hpp:19:

In file included from /celibs/boost_1_74_0/boost/signals2/signal.hpp:22:

In file included from /celibs/boost_1_74_0/boost/signals2/connection.hpp:21:

/celibs/boost_1_74_0/boost/signals2/detail/auto_buffer.hpp:143:37: error: no type named 'size_type' in 'std::__1::allocator<boost::shared_ptr<void>>'

        typedef typename Allocator::size_type            size_type;

                ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~

/celibs/boost_1_74_0/boost/signals2/connection.hpp:53:61: note: in instantiation of template class 'boost::signals2::detail::auto_buffer<boost::shared_ptr<void>, boost::signals2::detail::store_n_objects<10>, boost::signals2::detail::default_grow_policy, std::__1::allocator<boost::shared_ptr<void>>>' requested here

        auto_buffer<shared_ptr<void>, store_n_objects<10> > garbage;

                                                            ^

In file included from <source>:1:

In file included from /celibs/boost_1_74_0/boost/signals2.hpp:19:

In file included from /celibs/boost_1_74_0/boost/signals2/signal.hpp:22:

In file included from /celibs/boost_1_74_0/boost/signals2/connection.hpp:21:

/celibs/boost_1_74_0/boost/signals2/detail/auto_buffer.hpp:144:37: error: no type named 'difference_type' in 'std::__1::allocator<boost::shared_ptr<void>>'

        typedef typename Allocator::difference_type      difference_type;

                ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~

/celibs/boost_1_74_0/boost/signals2/detail/auto_buffer.hpp:143:37: error: no type named 'size_type' in 'std::__1::allocator<boost::variant<boost::shared_ptr<void>, boost::signals2::detail::foreign_void_shared_ptr>>'

        typedef typename Allocator::size_type            size_type;

                ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~

/celibs/boost_1_74_0/boost/signals2/detail/slot_call_iterator.hpp:65:27: note: in instantiation of template class 'boost::signals2::detail::auto_buffer<boost::variant<boost::shared_ptr<void>, boost::signals2::detail::foreign_void_shared_ptr>, boost::signals2::detail::store_n_objects<10>, boost::signals2::detail::default_grow_policy, std::__1::allocator<boost::variant<boost::shared_ptr<void>, boost::signals2::detail::foreign_void_shared_ptr>>>' requested here

        tracked_ptrs_type tracked_ptrs;

                          ^

In file included from <source>:1:

In file included from /celibs/boost_1_74_0/boost/signals2.hpp:19:

In file included from /celibs/boost_1_74_0/boost/signals2/signal.hpp:22:

In file included from /celibs/boost_1_74_0/boost/signals2/connection.hpp:21:

/celibs/boost_1_74_0/boost/signals2/detail/auto_buffer.hpp:144:37: error: no type named 'difference_type' in 'std::__1::allocator<boost::variant<boost::shared_ptr<void>, boost::signals2::detail::foreign_void_shared_ptr>>'

        typedef typename Allocator::difference_type      difference_type;

                ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~

4 errors generated.

Compiler returned: 1

Godbolt link: https://godbolt.org/z/cenzv1

$ clang++ --version
clang version 11.0.0 (Fedora 11.0.0-1.fc33)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

'This header is deprecated' warnings from signal.hpp in boost 1.74

#include <boost/signals2/signal.hpp> in boost 1.74 generates the following warning/message:

In file included from /celibs/boost_1_74_0/boost/smart_ptr/detail/sp_thread_sleep.hpp:22,
                 from /celibs/boost_1_74_0/boost/smart_ptr/detail/yield_k.hpp:23,
                 from /celibs/boost_1_74_0/boost/smart_ptr/detail/spinlock_gcc_atomic.hpp:14,
                 from /celibs/boost_1_74_0/boost/smart_ptr/detail/spinlock.hpp:42,
                 from /celibs/boost_1_74_0/boost/smart_ptr/detail/spinlock_pool.hpp:25,
                 from /celibs/boost_1_74_0/boost/smart_ptr/shared_ptr.hpp:29,
                 from /celibs/boost_1_74_0/boost/shared_ptr.hpp:17,
                 from /celibs/boost_1_74_0/boost/signals2/signal.hpp:21,
                 from <source>:1:

/celibs/boost_1_74_0/boost/function_output_iterator.hpp:14:1: note: '#pragma message: This header is deprecated. Use <boost/iterator/function_output_iterator.hpp> instead.'

   14 | BOOST_HEADER_DEPRECATED("<boost/iterator/function_output_iterator.hpp>")

      | ^~~~~~~~~~~~~~~~~~~~~~~

A demo is here on godbolt.
Note that even though the warning is generated inside shared_ptr.hpp, it is not emitted by the compiler if you include only boost/shared_ptr.hpp (as demonstrated in the link to compiler explorer).

boost::signals2::connection use of deprecated header

Hi,
during the compile time of the current boost library 1.74 I get the following message.

In file included from /usr/local/include/boost/signals2.hpp:19:
In file included from /usr/local/include/boost/signals2/signal.hpp:22:
In file included from /usr/local/include/boost/signals2/connection.hpp:22:
In file included from /usr/local/include/boost/signals2/detail/null_output_iterator.hpp:14:
/usr/local/include/boost/function_output_iterator.hpp:14:1: warning: This header is deprecated. Use <boost/iterator/function_output_iterator.hpp> instead. [-W#pragma-messages]
BOOST_HEADER_DEPRECATED("<boost/iterator/function_output_iterator.hpp>")

Release numbering and tag stability policy

Hullo!

Guix provides a boost-signals2 package. We noticed that the boost-1.77.0 tag moved significantly between 2019 and 2021.

Looking back, this was (long) before boost 1.77.0 was actually released. If so, using that tag so early was premature on our part!

Could you confirm my suspicion

  • that you develop for upcoming Boost releases using a movable tag,
  • but that this tag is not touched once that Boost has been officially released — even to fix bugs found later?

From a brief glance at the repository this seems to be the case, but it would be great if that were a deliberate policy.

Thanks in advance!

Fails to compile on NVCC CUDA 11.0

The following code snippet will not compile in Nvidia's compiler.

  #include <boost/signals2/signal.hpp>
  
  // TODO: This is an example of a library function
  void fnBoostPreprocessorHeader()
  {
  }

The compiler chokes somewhere inside of the include statement without any additional code except the snippet above. The following error is returned:

C1012 unmatched parenthesis: missing ')' BoostPreprocessorHeader in C:\vcpkg\installed\x64-windows-static\include\boost\preprocessor\slot\detail\shared.hpp on line 27

I have spoken to the nvidia compiler group and they responded with the following:

We checked the issue and confirmed that it is a Boost issue .The error is emitted by Microsoft cl.exe compiler. Something in the    Boost headers is checking for one of the CUDA macros (__CUDACC__ / __NVCC__) and enabling code that is not accepted by the Microsoft compiler used for preprocessing.
We suggest you track a ticket to Boost with this reproducer . Thank you.

Nvidia

C++/WinRT UWP App fails to compile when using C++20

Hello

I would like to use the Boost 1.80 Header-Only Libraries in my C++/WinRT UWP App. But when I switch the C++ Language Standard to "ISO C++20 Standard (/std:c++20)", then the app will not compile anymore.

I get the following output:

Build started...
1>------ Build started: Project: BlankApp1, Configuration: Debug x64 ------
1>App.cpp
1>MainPage.cpp
1>C:\Users\juliuszet\source\repos\BlankApp1\BlankApp1\boost\signals2\detail\lwm_win32_cs.hpp(61,49): error C2371: 'InitializeCriticalSectionEx': redefinition; different basic types (compiling source file MainPage.cpp)
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\synchapi.h(155): message : see declaration of 'InitializeCriticalSectionEx' (compiling source file MainPage.cpp)
1>C:\Users\juliuszet\source\repos\BlankApp1\BlankApp1\boost\signals2\detail\lwm_win32_cs.hpp(61,49): error C2733: 'InitializeCriticalSectionEx': you cannot overload a function with 'extern "C"' linkage (compiling source file MainPage.cpp)
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\synchapi.h(155,1): message : see declaration of 'InitializeCriticalSectionEx' (compiling source file MainPage.cpp)
1>C:\Users\juliuszet\source\repos\BlankApp1\BlankApp1\boost\signals2\detail\lwm_win32_cs.hpp(61,49): error C2371: 'InitializeCriticalSectionEx': redefinition; different basic types (compiling source file App.cpp)
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\synchapi.h(155): message : see declaration of 'InitializeCriticalSectionEx' (compiling source file App.cpp)
1>C:\Users\juliuszet\source\repos\BlankApp1\BlankApp1\boost\signals2\detail\lwm_win32_cs.hpp(61,49): error C2733: 'InitializeCriticalSectionEx': you cannot overload a function with 'extern "C"' linkage (compiling source file App.cpp)
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\synchapi.h(155,1): message : see declaration of 'InitializeCriticalSectionEx' (compiling source file App.cpp)
1>C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\XamlCompiler\Microsoft.Windows.UI.Xaml.Common.targets(486,5): error MSB4181: The "CompileXaml" task returned false but did not log an error.
1>Done building project "BlankApp1.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Steps to reproduce:

  1. Create a new project in Visual Studio 2022. Project template: "Blank App (C++/WinRT)".

    Do not change any settings during the project creation.
  2. Copy the "boost_1_80_0.7z\boost_1_80_0\boost" folder into your project directory (where your BlankApp1.vcxproj) is located.
    For me the path is "C:\Users\juliuszet\source\repos\BlankApp1\BlankApp1" <-- boost folder goes here.
  3. Add #include <boost/signals2.hpp> to your MainPage.h file, right below the #include "MainPage.g.h".
  4. Click Build --> Build Solution and notice, that it compiles successfully.
  5. Click Project --> Properties, Navigate to Configuration Properties --> C/C++ --> Language and change the C++ Language Standard to "ISO C++20 Standard (/std:c++20)".
  6. Click Build --> Build Solution and notice, that it does not compile anymore.

After taking a closer look at the error messages in the output, I played around a bit and found out, that it does compile again, when changing a few lines of code in "boost\signals2\detail\lwm_win32_cs.hpp"

replace this:

#if BOOST_PLAT_WINDOWS_RUNTIME
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(::_RTL_CRITICAL_SECTION *, unsigned long, unsigned long);
#else
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *);
#endif

with this:

extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *);

and replace this:

#if BOOST_PLAT_WINDOWS_RUNTIME
        boost::signals2::detail::InitializeCriticalSectionEx(reinterpret_cast< boost::signals2::detail::rtl_critical_section* >(&cs_), 4000, 0);
#else
        boost::signals2::detail::InitializeCriticalSection(reinterpret_cast< boost::signals2::detail::rtl_critical_section* >(&cs_)); 
#endif

with this:

        boost::signals2::detail::InitializeCriticalSection(reinterpret_cast< boost::signals2::detail::rtl_critical_section* >(&cs_)); 

Could someone have a look at this to find out what the issue is and who is at fault here?

Thank you very much in advance and have an awesome day! :)

Kind regards
JuliusZet

Mark move ctors/assignment and swap noexcept

In connection and signal classes, move constructors/assignment and swap are not marked noexcept, which prevents the user's types that have objects of these types as members to have noexcept constructors/assignment. It also prevents optimizations in standard library containers.

Documentation connect to another signal

Boost.Signals2 can connect to boost::signals2::signal object, I found test:

static void
test_signal_signal_connect()
{
typedef boost::signals2::signal<int (int value), max_or_default<int> > signal_type;
signal_type s1;
s1.connect(std::negate<int>());
BOOST_CHECK(s1(3) == -3);
{
signal_type s2;
s1.connect(s2);
s2.connect(boost::bind(std::multiplies<int>(), 2, _1));
s2.connect(boost::bind(std::multiplies<int>(), -3, _1));
BOOST_CHECK(s2(-3) == 9);
BOOST_CHECK(s1(3) == 6);
} // s2 goes out of scope and disconnects
BOOST_CHECK(s1(3) == -3);
}

If the connected signal object is deleted, auto disconnected.

This feature is very useful but does not found documented.

Adding documentation for this feature will help users.

Compilation failure with 1.83

We're seeing one specific failure of Boost.Signals2 in our Gentoo package tree: Bug 912309

This code used to compile fine under Boost 1.82. The offending line is:

stanzaChannel_->onPresenceReceived.disconnect(boost::ref(onPresenceReceived));

here stanzaChannel_->onPresenceReceived is of type boost::signals2::signal<void (std::shared_ptr<Message>)> and the onPresenceReceived argument on the right-hand side is of type boost::signals2::signal<void (std::shared_ptr<Message>)> too. The error boils down to an ambiguous overload

/usr/include/boost/function_equal.hpp:17:14: error: no match for 'operator==' (operand types are 'const boost::reference_wrapper<boost::signals2::signal<void(std::shared_ptr<Swift::Presence>)> >' and 'const boost::reference_wrapper<boost::signals2::signal<void(std::shared_ptr<Swift::Presence>)> >')
   17 |   { return f == g; }
      | 

Do you have any ideas or guidance that could help us fix this locally? Upstream seems mostly gone, and this is the last bug for us in Boost 1.83. Paging in @pdimov who recommended I file a bug here.

Api reference with description api

How about api reference with normal description class and methods, as for example in the stl
When navigate on table of contents in part reference, it is not obvious that class names are references. Can I add a list of classes separately in the table of contents?

Error: 'InitializeCriticalSectionEx': is not a member of 'boost::signals2::detail' in a Universal Windows project

Steps to reproduce:
Open the attached solution BoostSignals2.zip using Visual Studio and compile the project.

#include <boost/predef/platform.h>
#include <boost/signals2.hpp>

This results in the following error
boost\signals2\detail\lwm_win32_cs.hpp(96,34): error C2039: 'InitializeCriticalSectionEx': is not a member of 'boost::signals2::detail'

Building on Windows 10 Enterprise LTSC (1809), OS build 17763.5122
Using Visual Studio 2022, 17.7.6
for WindowsTargetPlatformVersion = 10.0.22621.0
WindowsTargetPlatformMinVersion = 10.0.17134.0

Diagnosis:
The problem first appeared when I included <boost/regex.hpp> before including <boost/signals2.hpp>.
The former indirectly includes the deprecated header <boost/predef/platform/windows_runtime.h>
That eventually sets BOOST_PLAT_WINDOWS_RUNTIME = 1

This is the chain of includes for regex.hpp and signals2.hpp

  boost/regex.hpp
   boost/regex/config.hpp
    boost/predef.h
     boost/predef/platform.h
      boost/predef/platform/windows_runtime.h

  boost/signals2.hpp
   boost/signals2/deconstruct.hpp
    boost/signals2/mutex.hpp
     boost/signals2/detail/lwm_win32_cs.hpp

The following change is to blame: Adapt changes from smart_ptr commit id
It removed the declaration of boost::signals2::detail::InitializeCriticalSectionEx but failed to remove its use in line 96.

How to fix

  • Do a partial rollback by recreating the declaration of InitializeCriticalSectionEx
  • Replace symbol BOOST_PLAT_WINDOWS_RUNTIME in line 96 with another symbol that is not deprecated
  • Remove lines 95 - 97

I cannot assess the side effects of the aforementioned possible fixes.
So I'd like to kindly ask fmhess to pick one.

Frank

Modular Boost C++ Libraries Request

We are in the process of making B2 build changes to all of the B2 build files
to support "modular" consumption of the Boost Libraries by users. See this list
post for some details: https://lists.boost.org/Archives/boost/2024/01/255704.php

The process requires making a variety of changes to make each Boost library
independent of the super-project structure. But the changes do not remove the
super-project structure or the comprehensive Boost release. The changes make
solely make it possible, optionally, for users, like package manages, to easily
consume libraries individually.

Generally the changes include:

  • Adding a libroot/build.jam.
  • Porting any functionality from libroot/jamfile to libroot/build.jam.
  • Moving boost-install declaration from libroot/build/jamfile is applicable.
  • Adjusting other B2 build files in the library, like test/jamfile, as needed.
  • Possible changes to C++ source files to remove includes relative to the
    super-project boostroot location.

Some examples of such changes:

We are asking how you would like us to handle the changes. We would prefer if
you allow the owners of the Boost.org GitHub project to make changes to B2
build files, as needed, to accomplish the changes. But understand
that you may want to manage the proposed changes yourself.

We previously sent emails to all known maintainers to fill out a form with their
preference. We are contacting you in this issue as we have not gotten a response
to that email. You can see the ongoing responses for that form and the responses
to these issues here https://github.com/users/grafikrobot/projects/1/views/6

We are now asking if you can reply directly to this issue to indicate your
preference of handling the changes. Please supply a response to this question
and close the issue (so that we can verify you are a maintainer).

How would you like the build changes to be processed?

  1. Pull request, reviewed and merged by a BOOSTORG OWNER.
  2. Pull request, reviewed and merged by YOU.
  3. Other. (please specify details in the reply)

Also please indicate any special instructions you want us to consider. Or other
information you want us to be aware of.

Thanks you, René

Two tests from boost libraries failed to run after boost submodule signals2 updated from 0c51b5 to 19bf28

Environment:
VS 2017 + Windows Server 2016

Issue description:
We build and run test for boost and we found two tests failed to run after boost submodule signals2 updated from 0c51b5 (master) to 19bf28 boostorg/signals2@358f052 Could you please take a look?

Reproduce steps:

  1. git clone -c core.autocrlf=true --recursive ​https://github.com/boostorg/boost.git D:\Boost\src
  2. open a VS 2017 x86 command prompt and browse to D:\Boost\src
  3. .\bootstrap
  4. .\b2 headers variant=release --build-dir=..\out\Release --address-model=32
  5. .\b2 variant=release --build-dir=..\out\Release --address-model=32
  6. .\b2 -j4 variant=release --build-dir=..\out\x86rel libs\signals2\test
  7. .\b2 -j4 variant=release --build-dir=..\out\x86rel libs\phoenix\test

ErrorMessage:
.\boost/signals2/signal_type.hpp(26): fatal error C1083: Cannot open include file: 'boost/parameter/template_keyword.hpp': No such file or directory

log_x86_test_96.log
log_x86_test_74.log

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.