]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/example/cpp11/nonblocking/third_party_lib.cpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / libs / asio / example / cpp11 / nonblocking / third_party_lib.cpp
1 //
2 // third_party_lib.cpp
3 // ~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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 <boost/asio.hpp>
12 #include <array>
13 #include <iostream>
14 #include <memory>
15
16 using boost::asio::ip::tcp;
17
18 namespace third_party_lib {
19
20 // Simulation of a third party library that wants to perform read and write
21 // operations directly on a socket. It needs to be polled to determine whether
22 // it requires a read or write operation, and notified when the socket is ready
23 // for reading or writing.
24 class session
25 {
26 public:
27 session(tcp::socket& socket)
28 : socket_(socket)
29 {
30 }
31
32 // Returns true if the third party library wants to be notified when the
33 // socket is ready for reading.
34 bool want_read() const
35 {
36 return state_ == reading;
37 }
38
39 // Notify that third party library that it should perform its read operation.
40 void do_read(boost::system::error_code& ec)
41 {
42 if (std::size_t len = socket_.read_some(boost::asio::buffer(data_), ec))
43 {
44 write_buffer_ = boost::asio::buffer(data_, len);
45 state_ = writing;
46 }
47 }
48
49 // Returns true if the third party library wants to be notified when the
50 // socket is ready for writing.
51 bool want_write() const
52 {
53 return state_ == writing;
54 }
55
56 // Notify that third party library that it should perform its write operation.
57 void do_write(boost::system::error_code& ec)
58 {
59 if (std::size_t len = socket_.write_some(
60 boost::asio::buffer(write_buffer_), ec))
61 {
62 write_buffer_ = write_buffer_ + len;
63 state_ = boost::asio::buffer_size(write_buffer_) > 0 ? writing : reading;
64 }
65 }
66
67 private:
68 tcp::socket& socket_;
69 enum { reading, writing } state_ = reading;
70 std::array<char, 128> data_;
71 boost::asio::const_buffer write_buffer_;
72 };
73
74 } // namespace third_party_lib
75
76 // The glue between asio's sockets and the third party library.
77 class connection
78 : public std::enable_shared_from_this<connection>
79 {
80 public:
81 connection(tcp::socket socket)
82 : socket_(std::move(socket))
83 {
84 }
85
86 void start()
87 {
88 // Put the socket into non-blocking mode.
89 socket_.non_blocking(true);
90
91 do_operations();
92 }
93
94 private:
95 void do_operations()
96 {
97 auto self(shared_from_this());
98
99 // Start a read operation if the third party library wants one.
100 if (session_impl_.want_read() && !read_in_progress_)
101 {
102 read_in_progress_ = true;
103 socket_.async_wait(tcp::socket::wait_read,
104 [this, self](boost::system::error_code ec)
105 {
106 read_in_progress_ = false;
107
108 // Notify third party library that it can perform a read.
109 if (!ec)
110 session_impl_.do_read(ec);
111
112 // The third party library successfully performed a read on the
113 // socket. Start new read or write operations based on what it now
114 // wants.
115 if (!ec || ec == boost::asio::error::would_block)
116 do_operations();
117
118 // Otherwise, an error occurred. Closing the socket cancels any
119 // outstanding asynchronous read or write operations. The
120 // connection object will be destroyed automatically once those
121 // outstanding operations complete.
122 else
123 socket_.close();
124 });
125 }
126
127 // Start a write operation if the third party library wants one.
128 if (session_impl_.want_write() && !write_in_progress_)
129 {
130 write_in_progress_ = true;
131 socket_.async_wait(tcp::socket::wait_write,
132 [this, self](boost::system::error_code ec)
133 {
134 write_in_progress_ = false;
135
136 // Notify third party library that it can perform a write.
137 if (!ec)
138 session_impl_.do_write(ec);
139
140 // The third party library successfully performed a write on the
141 // socket. Start new read or write operations based on what it now
142 // wants.
143 if (!ec || ec == boost::asio::error::would_block)
144 do_operations();
145
146 // Otherwise, an error occurred. Closing the socket cancels any
147 // outstanding asynchronous read or write operations. The
148 // connection object will be destroyed automatically once those
149 // outstanding operations complete.
150 else
151 socket_.close();
152 });
153 }
154 }
155
156 private:
157 tcp::socket socket_;
158 third_party_lib::session session_impl_{socket_};
159 bool read_in_progress_ = false;
160 bool write_in_progress_ = false;
161 };
162
163 class server
164 {
165 public:
166 server(boost::asio::io_context& io_context, unsigned short port)
167 : acceptor_(io_context, {tcp::v4(), port})
168 {
169 do_accept();
170 }
171
172 private:
173 void do_accept()
174 {
175 acceptor_.async_accept(
176 [this](boost::system::error_code ec, tcp::socket socket)
177 {
178 if (!ec)
179 {
180 std::make_shared<connection>(std::move(socket))->start();
181 }
182
183 do_accept();
184 });
185 }
186
187 tcp::acceptor acceptor_;
188 };
189
190 int main(int argc, char* argv[])
191 {
192 try
193 {
194 if (argc != 2)
195 {
196 std::cerr << "Usage: third_party_lib <port>\n";
197 return 1;
198 }
199
200 boost::asio::io_context io_context;
201
202 server s(io_context, std::atoi(argv[1]));
203
204 io_context.run();
205 }
206 catch (std::exception& e)
207 {
208 std::cerr << "Exception: " << e.what() << "\n";
209 }
210
211 return 0;
212 }