#include <atomic>
#include <chrono>
#include <csignal>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>

#include <cds-pubsub/pub.hh>

std::atomic< bool > done{ false };

extern "C" {
void
handler( int dummy )
{
    done = true;
}
}

class Counting_deleter
{
public:
    void
    operator( )( unsigned char* data ) noexcept
    {
        if ( data )
        {
            std::unique_lock< std::mutex > l_{ live_mutex_ };
            delete[] data;
            --cur_live_;
        }
    }

    static std::shared_ptr< unsigned char[] >
    new_block( std::size_t size, unsigned char val )
    {
        std::shared_ptr< unsigned char[] > p( new unsigned char[ size ],
                                              Counting_deleter( ) );
        {
            std::unique_lock< std::mutex > l_{ live_mutex_ };
            ++cur_live_;
        }
        unsigned char* start = p.get( );
        auto           end = start + size;
        std::fill( start, end, val );
        return p;
    }

    static std::size_t
    get_count( ) noexcept
    {
        std::unique_lock< std::mutex > l_{ live_mutex_ };
        return cur_live_;
    }

private:
    static int        cur_live_;
    static std::mutex live_mutex_;
};

int        Counting_deleter::cur_live_{ 0 };
std::mutex Counting_deleter::live_mutex_{};

int
main( int argc, char* argv[] )
{
    std::signal( SIGINT, handler );

    pub_sub::Publisher pub( "tcp://127.0.0.1:9000" );

    for ( pub_sub::KeyType key = 1; !done; ++key )
    {
        const int        msg_size = 100 * 1024 * 1024 / 16;
        pub_sub::Message msg(
            Counting_deleter::new_block(
                msg_size, static_cast< unsigned char >( key % 256 ) ),
            msg_size );

        pub.publish( key, std::move( msg ) );
        std::this_thread::sleep_for( std::chrono::milliseconds( 62 ) );

        if ( key % 16 == 0 )
        {
            std::cout << "Live buffer count = "
                      << Counting_deleter::get_count( ) << std::endl;
        }
    }
    return 0;
}