Realistic 3D camera system
3D camera system components
win_iocp_socket_service_base.hpp
Go to the documentation of this file.
1 //
2 // detail/win_iocp_socket_service_base.hpp
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 #ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_HPP
12 #define ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include "asio/detail/config.hpp"
19 
20 #if defined(ASIO_HAS_IOCP)
21 
22 #include "asio/error.hpp"
23 #include "asio/io_service.hpp"
24 #include "asio/socket_base.hpp"
31 #include "asio/detail/mutex.hpp"
33 #include "asio/detail/reactor.hpp"
44 
46 
47 namespace asio {
48 namespace detail {
49 
50 class win_iocp_socket_service_base
51 {
52 public:
53  // The implementation type of the socket.
54  struct base_implementation_type
55  {
56  // The native socket representation.
57  socket_type socket_;
58 
59  // The current state of the socket.
61 
62  // We use a shared pointer as a cancellation token here to work around the
63  // broken Windows support for cancellation. MSDN says that when you call
64  // closesocket any outstanding WSARecv or WSASend operations will complete
65  // with the error ERROR_OPERATION_ABORTED. In practice they complete with
66  // ERROR_NETNAME_DELETED, which means you can't tell the difference between
67  // a local cancellation and the socket being hard-closed by the peer.
69 
70  // Per-descriptor data used by the reactor.
71  reactor::per_descriptor_data reactor_data_;
72 
73 #if defined(ASIO_ENABLE_CANCELIO)
74  // The ID of the thread from which it is safe to cancel asynchronous
75  // operations. 0 means no asynchronous operations have been started yet.
76  // ~0 means asynchronous operations have been started from more than one
77  // thread, and cancellation is not supported for the socket.
78  DWORD safe_cancellation_thread_id_;
79 #endif // defined(ASIO_ENABLE_CANCELIO)
80 
81  // Pointers to adjacent socket implementations in linked list.
82  base_implementation_type* next_;
83  base_implementation_type* prev_;
84  };
85 
86  // Constructor.
87  ASIO_DECL win_iocp_socket_service_base(
88  asio::io_service& io_service);
89 
90  // Destroy all user-defined handler objects owned by the service.
91  ASIO_DECL void shutdown_service();
92 
93  // Construct a new socket implementation.
94  ASIO_DECL void construct(base_implementation_type& impl);
95 
96  // Move-construct a new socket implementation.
97  ASIO_DECL void base_move_construct(base_implementation_type& impl,
98  base_implementation_type& other_impl);
99 
100  // Move-assign from another socket implementation.
101  ASIO_DECL void base_move_assign(base_implementation_type& impl,
102  win_iocp_socket_service_base& other_service,
103  base_implementation_type& other_impl);
104 
105  // Destroy a socket implementation.
106  ASIO_DECL void destroy(base_implementation_type& impl);
107 
108  // Determine whether the socket is open.
109  bool is_open(const base_implementation_type& impl) const
110  {
111  return impl.socket_ != invalid_socket;
112  }
113 
114  // Destroy a socket implementation.
116  base_implementation_type& impl, asio::error_code& ec);
117 
118  // Cancel all operations associated with the socket.
120  base_implementation_type& impl, asio::error_code& ec);
121 
122  // Determine whether the socket is at the out-of-band data mark.
123  bool at_mark(const base_implementation_type& impl,
124  asio::error_code& ec) const
125  {
126  return socket_ops::sockatmark(impl.socket_, ec);
127  }
128 
129  // Determine the number of bytes available for reading.
130  std::size_t available(const base_implementation_type& impl,
131  asio::error_code& ec) const
132  {
133  return socket_ops::available(impl.socket_, ec);
134  }
135 
136  // Place the socket into the state where it will listen for new connections.
137  asio::error_code listen(base_implementation_type& impl,
138  int backlog, asio::error_code& ec)
139  {
140  socket_ops::listen(impl.socket_, backlog, ec);
141  return ec;
142  }
143 
144  // Perform an IO control command on the socket.
145  template <typename IO_Control_Command>
146  asio::error_code io_control(base_implementation_type& impl,
147  IO_Control_Command& command, asio::error_code& ec)
148  {
149  socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
150  static_cast<ioctl_arg_type*>(command.data()), ec);
151  return ec;
152  }
153 
154  // Gets the non-blocking mode of the socket.
155  bool non_blocking(const base_implementation_type& impl) const
156  {
157  return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
158  }
159 
160  // Sets the non-blocking mode of the socket.
161  asio::error_code non_blocking(base_implementation_type& impl,
162  bool mode, asio::error_code& ec)
163  {
164  socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
165  return ec;
166  }
167 
168  // Gets the non-blocking mode of the native socket implementation.
169  bool native_non_blocking(const base_implementation_type& impl) const
170  {
171  return (impl.state_ & socket_ops::internal_non_blocking) != 0;
172  }
173 
174  // Sets the non-blocking mode of the native socket implementation.
175  asio::error_code native_non_blocking(base_implementation_type& impl,
176  bool mode, asio::error_code& ec)
177  {
178  socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
179  return ec;
180  }
181 
182  // Disable sends or receives on the socket.
183  asio::error_code shutdown(base_implementation_type& impl,
185  {
186  socket_ops::shutdown(impl.socket_, what, ec);
187  return ec;
188  }
189 
190  // Send the given data to the peer. Returns the number of bytes sent.
191  template <typename ConstBufferSequence>
192  size_t send(base_implementation_type& impl,
193  const ConstBufferSequence& buffers,
195  {
196  buffer_sequence_adapter<asio::const_buffer,
197  ConstBufferSequence> bufs(buffers);
198 
199  return socket_ops::sync_send(impl.socket_, impl.state_,
200  bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
201  }
202 
203  // Wait until data can be sent without blocking.
204  size_t send(base_implementation_type& impl, const null_buffers&,
206  {
207  // Wait for socket to become ready.
208  socket_ops::poll_write(impl.socket_, impl.state_, ec);
209 
210  return 0;
211  }
212 
213  // Start an asynchronous send. The data being sent must be valid for the
214  // lifetime of the asynchronous operation.
215  template <typename ConstBufferSequence, typename Handler>
216  void async_send(base_implementation_type& impl,
217  const ConstBufferSequence& buffers,
218  socket_base::message_flags flags, Handler& handler)
219  {
220  // Allocate and construct an operation to wrap the handler.
221  typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op;
222  typename op::ptr p = { asio::detail::addressof(handler),
224  sizeof(op), handler), 0 };
225  p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
226 
227  ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
228 
229  buffer_sequence_adapter<asio::const_buffer,
230  ConstBufferSequence> bufs(buffers);
231 
232  start_send_op(impl, bufs.buffers(), bufs.count(), flags,
233  (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),
234  p.p);
235  p.v = p.p = 0;
236  }
237 
238  // Start an asynchronous wait until data can be sent without blocking.
239  template <typename Handler>
240  void async_send(base_implementation_type& impl, const null_buffers&,
241  socket_base::message_flags, Handler& handler)
242  {
243  // Allocate and construct an operation to wrap the handler.
244  typedef win_iocp_null_buffers_op<Handler> op;
245  typename op::ptr p = { asio::detail::addressof(handler),
247  sizeof(op), handler), 0 };
248  p.p = new (p.v) op(impl.cancel_token_, handler);
249 
250  ASIO_HANDLER_CREATION((p.p, "socket",
251  &impl, "async_send(null_buffers)"));
252 
253  start_reactor_op(impl, reactor::write_op, p.p);
254  p.v = p.p = 0;
255  }
256 
257  // Receive some data from the peer. Returns the number of bytes received.
258  template <typename MutableBufferSequence>
259  size_t receive(base_implementation_type& impl,
260  const MutableBufferSequence& buffers,
262  {
263  buffer_sequence_adapter<asio::mutable_buffer,
264  MutableBufferSequence> bufs(buffers);
265 
266  return socket_ops::sync_recv(impl.socket_, impl.state_,
267  bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
268  }
269 
270  // Wait until data can be received without blocking.
271  size_t receive(base_implementation_type& impl, const null_buffers&,
273  {
274  // Wait for socket to become ready.
275  socket_ops::poll_read(impl.socket_, impl.state_, ec);
276 
277  return 0;
278  }
279 
280  // Start an asynchronous receive. The buffer for the data being received
281  // must be valid for the lifetime of the asynchronous operation.
282  template <typename MutableBufferSequence, typename Handler>
283  void async_receive(base_implementation_type& impl,
284  const MutableBufferSequence& buffers,
285  socket_base::message_flags flags, Handler& handler)
286  {
287  // Allocate and construct an operation to wrap the handler.
288  typedef win_iocp_socket_recv_op<MutableBufferSequence, Handler> op;
289  typename op::ptr p = { asio::detail::addressof(handler),
291  sizeof(op), handler), 0 };
292  p.p = new (p.v) op(impl.state_, impl.cancel_token_, buffers, handler);
293 
294  ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive"));
295 
296  buffer_sequence_adapter<asio::mutable_buffer,
297  MutableBufferSequence> bufs(buffers);
298 
299  start_receive_op(impl, bufs.buffers(), bufs.count(), flags,
300  (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),
301  p.p);
302  p.v = p.p = 0;
303  }
304 
305  // Wait until data can be received without blocking.
306  template <typename Handler>
307  void async_receive(base_implementation_type& impl, const null_buffers&,
308  socket_base::message_flags flags, Handler& handler)
309  {
310  // Allocate and construct an operation to wrap the handler.
311  typedef win_iocp_null_buffers_op<Handler> op;
312  typename op::ptr p = { asio::detail::addressof(handler),
314  sizeof(op), handler), 0 };
315  p.p = new (p.v) op(impl.cancel_token_, handler);
316 
317  ASIO_HANDLER_CREATION((p.p, "socket",
318  &impl, "async_receive(null_buffers)"));
319 
320  start_null_buffers_receive_op(impl, flags, p.p);
321  p.v = p.p = 0;
322  }
323 
324  // Receive some data with associated flags. Returns the number of bytes
325  // received.
326  template <typename MutableBufferSequence>
327  size_t receive_with_flags(base_implementation_type& impl,
328  const MutableBufferSequence& buffers,
331  {
332  buffer_sequence_adapter<asio::mutable_buffer,
333  MutableBufferSequence> bufs(buffers);
334 
335  return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
336  bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
337  }
338 
339  // Wait until data can be received without blocking.
340  size_t receive_with_flags(base_implementation_type& impl,
341  const null_buffers&, socket_base::message_flags,
343  {
344  // Wait for socket to become ready.
345  socket_ops::poll_read(impl.socket_, impl.state_, ec);
346 
347  // Clear out_flags, since we cannot give it any other sensible value when
348  // performing a null_buffers operation.
349  out_flags = 0;
350 
351  return 0;
352  }
353 
354  // Start an asynchronous receive. The buffer for the data being received
355  // must be valid for the lifetime of the asynchronous operation.
356  template <typename MutableBufferSequence, typename Handler>
357  void async_receive_with_flags(base_implementation_type& impl,
358  const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
359  socket_base::message_flags& out_flags, Handler& handler)
360  {
361  // Allocate and construct an operation to wrap the handler.
362  typedef win_iocp_socket_recvmsg_op<MutableBufferSequence, Handler> op;
363  typename op::ptr p = { asio::detail::addressof(handler),
365  sizeof(op), handler), 0 };
366  p.p = new (p.v) op(impl.cancel_token_, buffers, out_flags, handler);
367 
368  ASIO_HANDLER_CREATION((p.p, "socket",
369  &impl, "async_receive_with_flags"));
370 
371  buffer_sequence_adapter<asio::mutable_buffer,
372  MutableBufferSequence> bufs(buffers);
373 
374  start_receive_op(impl, bufs.buffers(), bufs.count(), in_flags, false, p.p);
375  p.v = p.p = 0;
376  }
377 
378  // Wait until data can be received without blocking.
379  template <typename Handler>
380  void async_receive_with_flags(base_implementation_type& impl,
381  const null_buffers&, socket_base::message_flags in_flags,
382  socket_base::message_flags& out_flags, Handler& handler)
383  {
384  // Allocate and construct an operation to wrap the handler.
385  typedef win_iocp_null_buffers_op<Handler> op;
386  typename op::ptr p = { asio::detail::addressof(handler),
388  sizeof(op), handler), 0 };
389  p.p = new (p.v) op(impl.cancel_token_, handler);
390 
391  ASIO_HANDLER_CREATION((p.p, "socket", &impl,
392  "async_receive_with_flags(null_buffers)"));
393 
394  // Reset out_flags since it can be given no sensible value at this time.
395  out_flags = 0;
396 
397  start_null_buffers_receive_op(impl, in_flags, p.p);
398  p.v = p.p = 0;
399  }
400 
401  // Helper function to restart an asynchronous accept operation.
402  ASIO_DECL void restart_accept_op(socket_type s,
403  socket_holder& new_socket, int family, int type, int protocol,
404  void* output_buffer, DWORD address_length, operation* op);
405 
406 protected:
407  // Open a new socket implementation.
408  ASIO_DECL asio::error_code do_open(
409  base_implementation_type& impl, int family, int type,
410  int protocol, asio::error_code& ec);
411 
412  // Assign a native socket to a socket implementation.
413  ASIO_DECL asio::error_code do_assign(
414  base_implementation_type& impl, int type,
415  socket_type native_socket, asio::error_code& ec);
416 
417  // Helper function to start an asynchronous send operation.
418  ASIO_DECL void start_send_op(base_implementation_type& impl,
419  WSABUF* buffers, std::size_t buffer_count,
420  socket_base::message_flags flags, bool noop, operation* op);
421 
422  // Helper function to start an asynchronous send_to operation.
423  ASIO_DECL void start_send_to_op(base_implementation_type& impl,
424  WSABUF* buffers, std::size_t buffer_count,
425  const socket_addr_type* addr, int addrlen,
427 
428  // Helper function to start an asynchronous receive operation.
429  ASIO_DECL void start_receive_op(base_implementation_type& impl,
430  WSABUF* buffers, std::size_t buffer_count,
431  socket_base::message_flags flags, bool noop, operation* op);
432 
433  // Helper function to start an asynchronous null_buffers receive operation.
434  ASIO_DECL void start_null_buffers_receive_op(
435  base_implementation_type& impl,
436  socket_base::message_flags flags, reactor_op* op);
437 
438  // Helper function to start an asynchronous receive_from operation.
439  ASIO_DECL void start_receive_from_op(base_implementation_type& impl,
440  WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr,
441  socket_base::message_flags flags, int* addrlen, operation* op);
442 
443  // Helper function to start an asynchronous accept operation.
444  ASIO_DECL void start_accept_op(base_implementation_type& impl,
445  bool peer_is_open, socket_holder& new_socket, int family, int type,
446  int protocol, void* output_buffer, DWORD address_length, operation* op);
447 
448  // Start an asynchronous read or write operation using the reactor.
449  ASIO_DECL void start_reactor_op(base_implementation_type& impl,
450  int op_type, reactor_op* op);
451 
452  // Start the asynchronous connect operation using the reactor.
453  ASIO_DECL void start_connect_op(base_implementation_type& impl,
454  int family, int type, const socket_addr_type* remote_addr,
455  std::size_t remote_addrlen, win_iocp_socket_connect_op_base* op);
456 
457  // Helper function to close a socket when the associated object is being
458  // destroyed.
459  ASIO_DECL void close_for_destruction(base_implementation_type& impl);
460 
461  // Update the ID of the thread from which cancellation is safe.
462  ASIO_DECL void update_cancellation_thread_id(
463  base_implementation_type& impl);
464 
465  // Helper function to get the reactor. If no reactor has been created yet, a
466  // new one is obtained from the io_service and a pointer to it is cached in
467  // this service.
468  ASIO_DECL reactor& get_reactor();
469 
470  // The type of a ConnectEx function pointer, as old SDKs may not provide it.
471  typedef BOOL (PASCAL *connect_ex_fn)(SOCKET,
472  const socket_addr_type*, int, void*, DWORD, DWORD*, OVERLAPPED*);
473 
474  // Helper function to get the ConnectEx pointer. If no ConnectEx pointer has
475  // been obtained yet, one is obtained using WSAIoctl and the pointer is
476  // cached. Returns a null pointer if ConnectEx is not available.
477  ASIO_DECL connect_ex_fn get_connect_ex(
478  base_implementation_type& impl, int type);
479 
480  // Helper function to emulate InterlockedCompareExchangePointer functionality
481  // for:
482  // - very old Platform SDKs; and
483  // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
484  ASIO_DECL void* interlocked_compare_exchange_pointer(
485  void** dest, void* exch, void* cmp);
486 
487  // Helper function to emulate InterlockedExchangePointer functionality for:
488  // - very old Platform SDKs; and
489  // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
490  ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val);
491 
492  // The io_service used to obtain the reactor, if required.
493  asio::io_service& io_service_;
494 
495  // The IOCP service used for running asynchronous operations and dispatching
496  // handlers.
497  win_iocp_io_service& iocp_service_;
498 
499  // The reactor used for performing connect operations. This object is created
500  // only if needed.
501  reactor* reactor_;
502 
503  // Pointer to ConnectEx implementation.
504  void* connect_ex_;
505 
506  // Mutex to protect access to the linked list of implementations.
507  asio::detail::mutex mutex_;
508 
509  // The head of a linked list of all implementations.
510  base_implementation_type* impl_list_;
511 };
512 
513 } // namespace detail
514 } // namespace asio
515 
517 
518 #if defined(ASIO_HEADER_ONLY)
520 #endif // defined(ASIO_HEADER_ONLY)
521 
522 #endif // defined(ASIO_HAS_IOCP)
523 
524 #endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_HPP
int message_flags
Bitmask type for flags that can be passed to send and receive operations.
Definition: socket_base.hpp:53
bool set_user_non_blocking(socket_type s, state_type &state, bool value, asio::error_code &ec)
Definition: socket_ops.ipp:360
shared_ptr< void > shared_cancel_token_type
Definition: socket_ops.hpp:62
Provides core I/O functionality.
Definition: io_service.hpp:184
size_t sync_recv(socket_type s, state_type state, buf *bufs, size_t count, int flags, bool all_empty, asio::error_code &ec)
Definition: socket_ops.ipp:790
Holds a buffer that cannot be modified.
Definition: buffer.hpp:211
SocketService & s
Definition: connect.hpp:521
bool sockatmark(socket_type s, asio::error_code &ec)
Definition: socket_ops.ipp:630
size_t sync_send(socket_type s, state_type state, const buf *bufs, size_t count, int flags, bool all_empty, asio::error_code &ec)
int poll_read(socket_type s, state_type state, asio::error_code &ec)
int listen(socket_type s, int backlog, asio::error_code &ec)
Definition: socket_ops.ipp:684
sockaddr socket_addr_type
const MutableBufferSequence & buffers
Definition: read.hpp:521
int ioctl(socket_type s, state_type &state, int cmd, ioctl_arg_type *arg, asio::error_code &ec)
signed_size_type send(socket_type s, const buf *bufs, size_t count, int flags, asio::error_code &ec)
Holds a buffer that can be modified.
Definition: buffer.hpp:91
class select_reactor reactor
Definition: reactor_fwd.hpp:34
int poll_write(socket_type s, state_type state, asio::error_code &ec)
unsigned char state_type
Definition: socket_ops.hpp:59
shutdown_type
Different ways a socket may be shutdown.
Definition: socket_base.hpp:34
size_t available(socket_type s, asio::error_code &ec)
Definition: socket_ops.ipp:660
Class to represent an error code value.
Definition: error_code.hpp:80
size_t sync_recvmsg(socket_type s, state_type state, buf *bufs, size_t count, int in_flags, int &out_flags, asio::error_code &ec)
#define ASIO_DECL
Definition: config.hpp:43
task_io_service_operation operation
Definition: operation.hpp:32
ASIO_DECL int close(int d, state_type &state, asio::error_code &ec)
void * allocate(std::size_t s, Handler &h)
int shutdown(socket_type s, int what, asio::error_code &ec)
Definition: socket_ops.ipp:452
const int invalid_socket
#define ASIO_HANDLER_CREATION(args)
bool set_internal_non_blocking(socket_type s, state_type &state, bool value, asio::error_code &ec)
Definition: socket_ops.ipp:404