zoukankan      html  css  js  c++  java
  • boost asio allocation

    allocation演示了自定义异步操作的内存分配策略,因为asio在执行异步IO操作时会使用系统函数来动态分配内存,使用完后便立即释放掉;在IO操作密集的应用中,这种内存动态分配策略会较大地影响程序的整体性能。为了避免这个问题,可以在在应用程序中创建一个内存块供asio异步IO操作使用,异步IO操作通过自定义接口 asio_handler_allocate 和 asio_handler_deallocate 来使用该内存块。该例子中使用到了 boost::aligned_storage<1024> storage_ 来管理原始内存。

    cpp03

      1 //
      2 // server.cpp
      3 // ~~~~~~~~~~
      4 //
      5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
      6 //
      7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
      8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
      9 //
     10 
     11 #include <cstdlib>
     12 #include <iostream>
     13 #include <boost/aligned_storage.hpp>
     14 #include <boost/array.hpp>
     15 #include <boost/bind.hpp>
     16 #include <boost/enable_shared_from_this.hpp>
     17 #include <boost/noncopyable.hpp>
     18 #include <boost/shared_ptr.hpp>
     19 #include <boost/asio.hpp>
     20 
     21 
     22 using boost::asio::ip::tcp;
     23 
     24 // Class to manage the memory to be used for handler-based custom allocation.
     25 // It contains a single block of memory which may be returned for allocation
     26 // requests. If the memory is in use when an allocation request is made, the
     27 // allocator delegates allocation to the global heap.
     28 class handler_allocator
     29   : private boost::noncopyable
     30 {
     31 public:
     32   handler_allocator()
     33     : in_use_(false)
     34   {
     35   }
     36 
     37   void* allocate(std::size_t size)
     38   {
     39     if (!in_use_ && size < storage_.size)
     40     {
     41       in_use_ = true;
     42       return storage_.address();
     43     }
     44     else
     45     {
     46       return ::operator new(size);
     47     }
     48   }
     49 
     50   void deallocate(void* pointer)
     51   {
     52     if (pointer == storage_.address())
     53     {
     54       in_use_ = false;
     55     }
     56     else
     57     {
     58       ::operator delete(pointer);
     59     }
     60   }
     61 
     62 private:
     63   // Storage space used for handler-based custom memory allocation.
     64   boost::aligned_storage<1024> storage_;
     65 
     66   // Whether the handler-based custom allocation storage has been used.
     67   bool in_use_;
     68 };
     69 
     70 // Wrapper class template for handler objects to allow handler memory
     71 // allocation to be customised. Calls to operator() are forwarded to the
     72 // encapsulated handler.
     73 template <typename Handler>
     74 class custom_alloc_handler
     75 {
     76 public:
     77   custom_alloc_handler(handler_allocator& a, Handler h)
     78     : allocator_(a),
     79       handler_(h)
     80   {
     81   }
     82 
     83   template <typename Arg1>
     84   void operator()(Arg1 arg1)
     85   {
     86     handler_(arg1);
     87   }
     88 
     89   template <typename Arg1, typename Arg2>
     90   void operator()(Arg1 arg1, Arg2 arg2)
     91   {
     92     handler_(arg1, arg2);
     93   }
     94 
     95   friend void* asio_handler_allocate(std::size_t size,
     96       custom_alloc_handler<Handler>* this_handler)
     97   {
     98     return this_handler->allocator_.allocate(size);
     99   }
    100 
    101   friend void asio_handler_deallocate(void* pointer, std::size_t /*size*/,
    102       custom_alloc_handler<Handler>* this_handler)
    103   {
    104     this_handler->allocator_.deallocate(pointer);
    105   }
    106 private:
    107   handler_allocator& allocator_;
    108   Handler handler_;
    109 };
    110 // Helper function to wrap a handler object to add custom allocation.
    111 template <typename Handler>
    112 inline custom_alloc_handler<Handler> make_custom_alloc_handler(
    113     handler_allocator& a, Handler h)
    114 {
    115   return custom_alloc_handler<Handler>(a, h);
    116 }
    117 
    118 class session
    119   : public boost::enable_shared_from_this<session>
    120 {
    121 public:
    122   session(boost::asio::io_service& io_service)
    123     : socket_(io_service)
    124   {
    125   }
    126   tcp::socket& socket()
    127   {
    128     return socket_;
    129   }
    130   void start()
    131   {
    132     socket_.async_read_some(boost::asio::buffer(data_),
    133         make_custom_alloc_handler(allocator_,
    134           boost::bind(&session::handle_read,
    135             shared_from_this(),
    136             boost::asio::placeholders::error,
    137             boost::asio::placeholders::bytes_transferred)));
    138   }
    139   void handle_read(const boost::system::error_code& error,
    140       size_t bytes_transferred)
    141   {
    142     if (!error)
    143     {
    144       boost::asio::async_write(socket_,
    145           boost::asio::buffer(data_, bytes_transferred),
    146           make_custom_alloc_handler(allocator_,
    147             boost::bind(&session::handle_write,
    148               shared_from_this(),
    149               boost::asio::placeholders::error)));
    150     }
    151   }
    152   void handle_write(const boost::system::error_code& error)
    153   {
    154     if (!error)
    155     {
    156       socket_.async_read_some(boost::asio::buffer(data_),
    157           make_custom_alloc_handler(allocator_,
    158             boost::bind(&session::handle_read,
    159               shared_from_this(),
    160               boost::asio::placeholders::error,
    161               boost::asio::placeholders::bytes_transferred)));
    162     }
    163   }
    164 private:
    165   // The socket used to communicate with the client.
    166   tcp::socket socket_;
    167   // Buffer used to store data received from the client.
    168   boost::array<char, 1024> data_;
    169   // The allocator to use for handler-based custom memory allocation.
    170   handler_allocator allocator_;
    171 };
    172 
    173 typedef boost::shared_ptr<session> session_ptr;
    174 class server
    175 {
    176 public:
    177   server(boost::asio::io_service& io_service, short port)
    178     : io_service_(io_service),
    179       acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
    180   {
    181     session_ptr new_session(new session(io_service_));
    182     acceptor_.async_accept(new_session->socket(),
    183         boost::bind(&server::handle_accept, this, new_session,
    184           boost::asio::placeholders::error));
    185   }
    186   void handle_accept(session_ptr new_session,
    187       const boost::system::error_code& error)
    188   {
    189     if (!error)
    190     {
    191       new_session->start();
    192     }
    193 
    194     new_session.reset(new session(io_service_));
    195     acceptor_.async_accept(new_session->socket(),
    196         boost::bind(&server::handle_accept, this, new_session,
    197           boost::asio::placeholders::error));
    198   }
    199 private:
    200   boost::asio::io_service& io_service_;
    201   tcp::acceptor acceptor_;
    202 };
    203 
    204 int main(int argc, char* argv[])
    205 {
    206   try
    207   {
    208     boost::asio::io_service io_service;
    209     using namespace std;                // For atoi.
    210     server s(io_service, 4004);
    211     io_service.run();
    212   }
    213   catch (std::exception& e)
    214   {
    215     std::cerr << "Exception: " << e.what() << "
    ";
    216   }
    217 
    218   return 0;
    219 }

    cpp11

      1 //
      2 // server.cpp
      3 // ~~~~~~~~~~
      4 //
      5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
      6 //
      7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
      8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
      9 //
     10 
     11 #include <array>
     12 #include <cstdlib>
     13 #include <iostream>
     14 #include <memory>
     15 #include <type_traits>
     16 #include <utility>
     17 #include "asio.hpp"
     18 
     19 using asio::ip::tcp;
     20 
     21 // Class to manage the memory to be used for handler-based custom allocation.
     22 // It contains a single block of memory which may be returned for allocation
     23 // requests. If the memory is in use when an allocation request is made, the
     24 // allocator delegates allocation to the global heap.
     25 class handler_allocator
     26 {
     27 public:
     28   handler_allocator()
     29     : in_use_(false)
     30   {
     31   }
     32 
     33   handler_allocator(const handler_allocator&) = delete;
     34   handler_allocator& operator=(const handler_allocator&) = delete;
     35 
     36   void* allocate(std::size_t size)
     37   {
     38     if (!in_use_ && size < sizeof(storage_))
     39     {
     40       in_use_ = true;
     41       return &storage_;
     42     }
     43     else
     44     {
     45       return ::operator new(size);
     46     }
     47   }
     48 
     49   void deallocate(void* pointer)
     50   {
     51     if (pointer == &storage_)
     52     {
     53       in_use_ = false;
     54     }
     55     else
     56     {
     57       ::operator delete(pointer);
     58     }
     59   }
     60 
     61 private:
     62   // Storage space used for handler-based custom memory allocation.
     63   typename std::aligned_storage<1024>::type storage_;
     64 
     65   // Whether the handler-based custom allocation storage has been used.
     66   bool in_use_;
     67 };
     68 
     69 // Wrapper class template for handler objects to allow handler memory
     70 // allocation to be customised. Calls to operator() are forwarded to the
     71 // encapsulated handler.
     72 template <typename Handler>
     73 class custom_alloc_handler
     74 {
     75 public:
     76   custom_alloc_handler(handler_allocator& a, Handler h)
     77     : allocator_(a),
     78       handler_(h)
     79   {
     80   }
     81 
     82   template <typename ...Args>
     83   void operator()(Args&&... args)
     84   {
     85     handler_(std::forward<Args>(args)...);
     86   }
     87 
     88   friend void* asio_handler_allocate(std::size_t size,
     89       custom_alloc_handler<Handler>* this_handler)
     90   {
     91     return this_handler->allocator_.allocate(size);
     92   }
     93 
     94   friend void asio_handler_deallocate(void* pointer, std::size_t /*size*/,
     95       custom_alloc_handler<Handler>* this_handler)
     96   {
     97     this_handler->allocator_.deallocate(pointer);
     98   }
     99 
    100 private:
    101   handler_allocator& allocator_;
    102   Handler handler_;
    103 };
    104 
    105 // Helper function to wrap a handler object to add custom allocation.
    106 template <typename Handler>
    107 inline custom_alloc_handler<Handler> make_custom_alloc_handler(
    108     handler_allocator& a, Handler h)
    109 {
    110   return custom_alloc_handler<Handler>(a, h);
    111 }
    112 
    113 class session
    114   : public std::enable_shared_from_this<session>
    115 {
    116 public:
    117   session(tcp::socket socket)
    118     : socket_(std::move(socket))
    119   {
    120   }
    121 
    122   void start()
    123   {
    124     do_read();
    125   }
    126 
    127 private:
    128   void do_read()
    129   {
    130     auto self(shared_from_this());
    131     socket_.async_read_some(asio::buffer(data_),
    132         make_custom_alloc_handler(allocator_,
    133           [this, self](std::error_code ec, std::size_t length)
    134           {
    135             if (!ec)
    136             {
    137               do_write(length);
    138             }
    139           }));
    140   }
    141 
    142   void do_write(std::size_t length)
    143   {
    144     auto self(shared_from_this());
    145     asio::async_write(socket_, asio::buffer(data_, length),
    146         make_custom_alloc_handler(allocator_,
    147           [this, self](std::error_code ec, std::size_t /*length*/)
    148           {
    149             if (!ec)
    150             {
    151               do_read();
    152             }
    153           }));
    154   }
    155 
    156   // The socket used to communicate with the client.
    157   tcp::socket socket_;
    158 
    159   // Buffer used to store data received from the client.
    160   std::array<char, 1024> data_;
    161 
    162   // The allocator to use for handler-based custom memory allocation.
    163   handler_allocator allocator_;
    164 };
    165 
    166 class server
    167 {
    168 public:
    169   server(asio::io_service& io_service, short port)
    170     : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
    171       socket_(io_service)
    172   {
    173     do_accept();
    174   }
    175 
    176 private:
    177   void do_accept()
    178   {
    179     acceptor_.async_accept(socket_,
    180         [this](std::error_code ec)
    181         {
    182           if (!ec)
    183           {
    184             std::make_shared<session>(std::move(socket_))->start();
    185           }
    186 
    187           do_accept();
    188         });
    189   }
    190 
    191   tcp::acceptor acceptor_;
    192   tcp::socket socket_;
    193 };
    194 
    195 int main(int argc, char* argv[])
    196 {
    197   try
    198   {
    199     if (argc != 2)
    200     {
    201       std::cerr << "Usage: server <port>
    ";
    202       return 1;
    203     }
    204 
    205     asio::io_service io_service;
    206     server s(io_service, std::atoi(argv[1]));
    207     io_service.run();
    208   }
    209   catch (std::exception& e)
    210   {
    211     std::cerr << "Exception: " << e.what() << "
    ";
    212   }
    213 
    214   return 0;
    215 }
  • 相关阅读:
    postman Variables变量的详解与应用
    windows 快速设置环境变量工具 Rapid Environment Editor
    Redis 客户端工具
    python 安装 pymongo
    python ImportError:No module named 'PIL'
    linux 通过命令行终端去控制vnc终端【export DISPLAY使用方法】
    centos7 安装vnc-server 与卸载
    vagrant box centos7硬盘扩容【不删除原数据】
    vboxmanage不是内部或外部命令
    用docker搭建的nginx报upstream错误
  • 原文地址:https://www.cnblogs.com/Forever-Kenlen-Ja/p/7844561.html
Copyright © 2011-2022 走看看