<commit_before>#ifndef  LIBBITCOIN_UTILITY_SUBSCRIBER_H
#define  LIBBITCOIN_UTILITY_SUBSCRIBER_H

#include <bitcoin/types.hpp>

namespace libbitcoin {

template <typename... Args>
class subscriber
  : public std::enable_shared_from_this<subscriber<Args...>>
{
public:
    typedef std::function<void (Args...)> handler_type;

    subscriber(strand_ptr async_strand)
      : strand_(async_strand)
    {
    }

    void subscribe(handler_type handle)
    {
        strand_->dispatch(
            std::bind(&subscriber<Args...>::do_subscribe,
                this->shared_from_this(), handle));
    }

    void relay(Args... params)
    {
        strand_->dispatch(
            std::bind(&subscriber<Args...>::do_relay,
                this->shared_from_this(), std::forward<Args>(params)...));
    }

private:
    typedef std::stack<handler_type> registry_stack;

    void do_subscribe(handler_type handle)
    {
        registry_.push(handle);
    }

    void do_relay(Args... params)
    {
        while (!registry_.empty())
        {
            registry_.top()(std::forward<Args>(params)...);
            registry_.pop();
        }
        BITCOIN_ASSERT(registry_.empty());
    }

    strand_ptr strand_;
    registry_stack registry_;
};

// C++11 - not in g++ yet!
//template <typename Handler>
//using subscriber_ptr = std::shared_ptr<subscribe<Handler>>;

} // libbitcoin

#endif
<commit_msg>BUGFIX: add to subscribe queue while inside function call causes infinite loop so make copy of queue before calling functions.<commit_after>#ifndef  LIBBITCOIN_UTILITY_SUBSCRIBER_H
#define  LIBBITCOIN_UTILITY_SUBSCRIBER_H

#include <bitcoin/types.hpp>

namespace libbitcoin {

template <typename... Args>
class subscriber
  : public std::enable_shared_from_this<subscriber<Args...>>
{
public:
    typedef std::function<void (Args...)> handler_type;

    subscriber(strand_ptr async_strand)
      : strand_(async_strand)
    {
    }

    void subscribe(handler_type handle)
    {
        strand_->dispatch(
            std::bind(&subscriber<Args...>::do_subscribe,
                this->shared_from_this(), handle));
    }

    void relay(Args... params)
    {
        strand_->dispatch(
            std::bind(&subscriber<Args...>::do_relay,
                this->shared_from_this(), std::forward<Args>(params)...));
    }

private:
    typedef std::stack<handler_type> registry_stack;

    void do_subscribe(handler_type handle)
    {
        registry_.push(handle);
    }

    void do_relay(Args... params)
    {
        registry_stack notify_copy = registry_;
        registry_ = registry_stack();
        while (!notify_copy.empty())
        {
            notify_copy.top()(std::forward<Args>(params)...);
            notify_copy.pop();
        }
        BITCOIN_ASSERT(notify_copy.empty());
    }

    strand_ptr strand_;
    registry_stack registry_;
};

// C++11 - not in g++ yet!
//template <typename Handler>
//using subscriber_ptr = std::shared_ptr<subscribe<Handler>>;

} // libbitcoin

#endif

{'fraction_non_alphanumeric': 0.13262245918027324, 'fraction_numerical': 0.0013328890369876708, 'mean_word_length': 2.79040404040404, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4026603', 'n_tokens_mistral': 955, 'n_tokens_neox': 906, 'n_words': 164}