Implement ASIO custom execution handlers

36 Views Asked by At

I am going through asio tutorial and how to implement asio handler which allocate memory from a specific user defined region. In my case I tried to allocate memory from synchronized_pool_resource Find below the piece of code based on asio example

My naive functionality

#include <array>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <type_traits>
#include <utility>
#include "boost/asio.hpp"
#include <memory_resource>


class MemoryStorage
{
public:
    inline static char buffer[0124] {}; // a small buffer on the stack
    inline static std::pmr::monotonic_buffer_resource pool{std::data(buffer), std::size(buffer)};
    inline static std::pmr::synchronized_pool_resource mem {&pool};
};

class handler_memory
{
public:
  handler_memory()
  {
  }

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

  void* allocate(std::size_t size)
  {
    std::cout << "allocate " << size <<std::endl;
    memory_block_size_ = size;
    return _upstream->allocate(size);
  }

  void deallocate(void* pointer,std::size_t size)
  {
    std::cout << "deallocate" << size << std::endl;
     return _upstream->deallocate(pointer,memory_block_size_);
  }

private:
  
  std::pmr::memory_resource* _upstream = &MemoryStorage::mem;
  std::size_t memory_block_size_ {};
};

template <typename T>
class handler_allocator
{
public:
  using value_type = T;

  explicit handler_allocator(handler_memory& mem)
    : memory_(mem)
  {
  }

  template <typename U>
  handler_allocator(const handler_allocator<U>& other) noexcept
    : memory_(other.memory_)
  {
  }

  template <typename U>
  struct rebind
  {
    typedef handler_allocator<U> other;
  };


  bool operator==(const handler_allocator& other) const noexcept
  {
    return &memory_ == &other.memory_;
  }

  bool operator!=(const handler_allocator& other) const noexcept
  {
    return &memory_ != &other.memory_;
  }

  T* allocate(std::size_t n) const
  {
    std::cout << "allocate" << n << "," << sizeof(T) << std::endl;
    return static_cast<T*>(memory_.allocate(sizeof(T) * n));
  }

  void deallocate(T* p, std::size_t n) const
  {
    return memory_.deallocate(p,sizeof(T) * n);
  }

private:
  template <typename> friend class handler_allocator;

  // The underlying memory.
  handler_memory& memory_;
};

class session
  : public std::enable_shared_from_this<session>
{

public:

  handler_memory handler_memory_;
  void foo()
  {
        boost::system::error_code ec;
        auto handler = [](boost::system::error_code ec){std::cout << "hello world"<<std::endl;};

         auto  allocator_handler =   boost::asio::bind_allocator(
        handler_allocator<std::decay<decltype(handler)>::type>(handler_memory_),std::move(handler));
       boost::asio::system_timer timer(io_context_);
        timer.expires_after(std::chrono::seconds{1});
        timer.async_wait(boost::asio::bind_executor(io_context_, std::move(allocator_handler)));
        io_context_.run();
  }
  boost::asio::io_context io_context_;
};

int main(int argc, char* argv[])
{
    s.foo();
  return 0;
}

Focus on foo function I hardly understand why when allocator_handler is constructed , explicitly deducing Type T in handler_allocator as int as example below,

auto  allocator_handler =   boost::asio::bind_allocator(
        handler_allocator<int>(handler_memory_),std::move(handler));

and print the sizeof(T), this is not 4 bytes but 144 . Somehow it is deduced in the whole lamda object in my point view. But the question is how? demo

0

There are 0 best solutions below