1 // Copyright Daniel Wallin and Arvid Norberg 2007.
2 // Use, modification and distribution is
3 // subject to the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #ifndef VARIANT_STREAM_070211_HPP
7 # define VARIANT_STREAM_070211_HPP
9 # include <boost/variant.hpp>
11 # include <boost/mpl/vector.hpp>
12 # include <boost/mpl/void.hpp>
13 # include <boost/mpl/remove.hpp>
14 # include <boost/mpl/transform.hpp>
15 # include <boost/mpl/size.hpp>
17 # include <boost/preprocessor/repetition/enum_params.hpp>
18 # include <boost/preprocessor/repetition/enum_binary_params.hpp>
19 # include <boost/preprocessor/facilities/intercept.hpp>
21 # include <boost/type_traits/add_pointer.hpp>
22 # include <boost/noncopyable.hpp>
24 #if BOOST_VERSION < 103500
25 #include <asio/io_service.hpp>
27 #include <boost/asio/io_service.hpp>
30 # define NETWORK_VARIANT_STREAM_LIMIT 5
32 namespace libtorrent
{
38 : boost::static_visitor
<>
41 void operator()(T
* p
) const
46 void operator()(boost::blank
) const
50 // -------------- io_control -----------
52 template<class IO_Control_Command
>
53 struct io_control_visitor_ec
: boost::static_visitor
<>
55 io_control_visitor_ec(IO_Control_Command
& ioc
, error_code
& ec_
)
56 : ioc(ioc
), ec(ec_
) {}
59 void operator()(T
* p
) const
61 p
->io_control(ioc
, ec
);
64 void operator()(boost::blank
) const
67 IO_Control_Command
& ioc
;
71 template<class IO_Control_Command
>
72 struct io_control_visitor
73 : boost::static_visitor
<>
75 io_control_visitor(IO_Control_Command
& ioc
)
79 void operator()(T
* p
) const
84 void operator()(boost::blank
) const
87 IO_Control_Command
& ioc
;
89 // -------------- async_connect -----------
91 template <class EndpointType
, class Handler
>
92 struct async_connect_visitor
93 : boost::static_visitor
<>
95 async_connect_visitor(EndpointType
const& endpoint
, Handler
const& handler
)
101 void operator()(T
* p
) const
103 p
->async_connect(endpoint
, handler
);
106 void operator()(boost::blank
) const
109 EndpointType
const& endpoint
;
110 Handler
const& handler
;
113 // -------------- bind -----------
115 template <class EndpointType
>
116 struct bind_visitor_ec
117 : boost::static_visitor
<>
119 bind_visitor_ec(EndpointType
const& ep
, error_code
& ec_
)
125 void operator()(T
* p
) const
126 { p
->bind(endpoint
, ec
); }
128 void operator()(boost::blank
) const {}
130 EndpointType
const& endpoint
;
134 template <class EndpointType
>
136 : boost::static_visitor
<>
138 bind_visitor(EndpointType
const& ep
)
143 void operator()(T
* p
) const
144 { p
->bind(endpoint
); }
146 void operator()(boost::blank
) const {}
148 EndpointType
const& endpoint
;
151 // -------------- open -----------
153 template <class Protocol
>
154 struct open_visitor_ec
155 : boost::static_visitor
<>
157 open_visitor_ec(Protocol
const& p
, error_code
& ec_
)
163 void operator()(T
* p
) const
164 { p
->open(proto
, ec
); }
166 void operator()(boost::blank
) const {}
168 Protocol
const& proto
;
172 template <class Protocol
>
174 : boost::static_visitor
<>
176 open_visitor(Protocol
const& p
)
181 void operator()(T
* p
) const
184 void operator()(boost::blank
) const {}
186 Protocol
const& proto
;
189 // -------------- is_open -----------
191 struct is_open_visitor
192 : boost::static_visitor
<bool>
197 bool operator()(T
const* p
) const
198 { return p
->is_open(); }
200 bool operator()(boost::blank
) const { return false; }
203 // -------------- close -----------
205 struct close_visitor_ec
206 : boost::static_visitor
<>
208 close_visitor_ec(error_code
& ec_
)
213 void operator()(T
* p
) const
216 void operator()(boost::blank
) const {}
222 : boost::static_visitor
<>
225 void operator()(T
* p
) const
228 void operator()(boost::blank
) const {}
231 // -------------- remote_endpoint -----------
233 template <class EndpointType
>
234 struct remote_endpoint_visitor_ec
235 : boost::static_visitor
<EndpointType
>
237 remote_endpoint_visitor_ec(error_code
& ec_
)
242 EndpointType
operator()(T
const* p
) const
243 { return p
->remote_endpoint(ec
); }
245 EndpointType
operator()(boost::blank
) const
246 { return EndpointType(); }
251 template <class EndpointType
>
252 struct remote_endpoint_visitor
253 : boost::static_visitor
<EndpointType
>
256 EndpointType
operator()(T
const* p
) const
257 { return p
->remote_endpoint(); }
259 EndpointType
operator()(boost::blank
) const
260 { return EndpointType(); }
263 // -------------- set_option -----------
265 template <class SettableSocketOption
>
266 struct set_option_visitor
267 : boost::static_visitor
<>
269 set_option_visitor(SettableSocketOption
const& opt
)
274 void operator()(T
* p
) const
275 { p
->set_option(opt_
); }
277 void operator()(boost::blank
) const {}
279 SettableSocketOption
const& opt_
;
282 template <class SettableSocketOption
>
283 struct set_option_visitor_ec
284 : boost::static_visitor
<error_code
>
286 set_option_visitor_ec(SettableSocketOption
const& opt
, error_code
& ec
)
292 error_code
operator()(T
* p
) const
293 { return p
->set_option(opt_
, ec_
); }
295 error_code
operator()(boost::blank
) const
298 SettableSocketOption
const& opt_
;
302 // -------------- local_endpoint -----------
304 template <class EndpointType
>
305 struct local_endpoint_visitor_ec
306 : boost::static_visitor
<EndpointType
>
308 local_endpoint_visitor_ec(error_code
& ec_
)
313 EndpointType
operator()(T
const* p
) const
315 return p
->local_endpoint(ec
);
318 EndpointType
operator()(boost::blank
) const
320 return EndpointType();
326 template <class EndpointType
>
327 struct local_endpoint_visitor
328 : boost::static_visitor
<EndpointType
>
331 EndpointType
operator()(T
const* p
) const
333 return p
->local_endpoint();
336 EndpointType
operator()(boost::blank
) const
338 return EndpointType();
342 // -------------- async_read_some -----------
344 template <class Mutable_Buffers
, class Handler
>
345 struct async_read_some_visitor
346 : boost::static_visitor
<>
348 async_read_some_visitor(Mutable_Buffers
const& buffers
, Handler
const& handler
)
354 void operator()(T
* p
) const
356 p
->async_read_some(buffers
, handler
);
358 void operator()(boost::blank
) const
361 Mutable_Buffers
const& buffers
;
362 Handler
const& handler
;
365 // -------------- read_some -----------
367 template <class Mutable_Buffers
>
368 struct read_some_visitor
369 : boost::static_visitor
<std::size_t>
371 read_some_visitor(Mutable_Buffers
const& buffers
)
376 std::size_t operator()(T
* p
) const
377 { return p
->read_some(buffers
); }
379 std::size_t operator()(boost::blank
) const
382 Mutable_Buffers
const& buffers
;
385 template <class Mutable_Buffers
>
386 struct read_some_visitor_ec
387 : boost::static_visitor
<std::size_t>
389 read_some_visitor_ec(Mutable_Buffers
const& buffers
, error_code
& ec_
)
395 std::size_t operator()(T
* p
) const
396 { return p
->read_some(buffers
, ec
); }
398 std::size_t operator()(boost::blank
) const
401 Mutable_Buffers
const& buffers
;
405 // -------------- async_write_some -----------
407 template <class Const_Buffers
, class Handler
>
408 struct async_write_some_visitor
409 : boost::static_visitor
<>
411 async_write_some_visitor(Const_Buffers
const& buffers
, Handler
const& handler
)
417 void operator()(T
* p
) const
419 p
->async_write_some(buffers
, handler
);
422 void operator()(boost::blank
) const
425 Const_Buffers
const& buffers
;
426 Handler
const& handler
;
429 // -------------- in_avail -----------
431 struct in_avail_visitor_ec
432 : boost::static_visitor
<std::size_t>
434 in_avail_visitor_ec(error_code
& ec_
)
439 std::size_t operator()(T
const* p
) const
441 return p
->in_avail(ec
);
444 std::size_t operator()(boost::blank
) const
452 struct in_avail_visitor
453 : boost::static_visitor
<std::size_t>
456 std::size_t operator()(T
const* p
) const
458 return p
->in_avail();
461 void operator()(boost::blank
) const
465 // -------------- io_service -----------
467 template <class IOService
>
468 struct io_service_visitor
469 : boost::static_visitor
<IOService
&>
472 IOService
& operator()(T
* p
) const
474 return p
->get_io_service();
477 IOService
& operator()(boost::blank
) const
479 return *(IOService
*)0;
483 // -------------- lowest_layer -----------
485 template <class LowestLayer
>
486 struct lowest_layer_visitor
487 : boost::static_visitor
<LowestLayer
&>
490 LowestLayer
& operator()(T
* p
) const
492 return p
->lowest_layer();
495 LowestLayer
& operator()(boost::blank
) const
497 return *(LowestLayer
*)0;
504 BOOST_PP_ENUM_BINARY_PARAMS(
505 NETWORK_VARIANT_STREAM_LIMIT
, class S
, = boost::mpl::void_ BOOST_PP_INTERCEPT
508 class variant_stream
: boost::noncopyable
511 typedef BOOST_PP_CAT(boost::mpl::vector
, NETWORK_VARIANT_STREAM_LIMIT
)<
512 BOOST_PP_ENUM_PARAMS(NETWORK_VARIANT_STREAM_LIMIT
, S
)
515 typedef typename
boost::mpl::remove
<types0
, boost::mpl::void_
>::type types
;
517 typedef typename
boost::make_variant_over
<
518 typename
boost::mpl::push_back
<
519 typename
boost::mpl::transform
<
521 , boost::add_pointer
<boost::mpl::_
>
525 >::type variant_type
;
527 typedef typename
S0::lowest_layer_type lowest_layer_type
;
528 typedef typename
S0::endpoint_type endpoint_type
;
529 typedef typename
S0::protocol_type protocol_type
;
531 explicit variant_stream(io_service
& ios
)
532 : m_io_service(ios
), m_variant(boost::blank()) {}
535 void instantiate(io_service
& ios
)
537 TORRENT_ASSERT(&ios
== &m_io_service
);
538 std::auto_ptr
<S
> owned(new S(ios
));
539 boost::apply_visitor(aux::delete_visitor(), m_variant
);
540 m_variant
= owned
.get();
547 return *boost::get
<S
*>(m_variant
);
550 bool instantiated() const
552 return m_variant
.which() != boost::mpl::size
<types
>::value
;
557 boost::apply_visitor(aux::delete_visitor(), m_variant
);
560 template <class Mutable_Buffers
>
561 std::size_t read_some(Mutable_Buffers
const& buffers
, error_code
& ec
)
563 TORRENT_ASSERT(instantiated());
564 return boost::apply_visitor(
565 aux::read_some_visitor_ec
<Mutable_Buffers
>(buffers
, ec
)
570 template <class Mutable_Buffers
>
571 std::size_t read_some(Mutable_Buffers
const& buffers
)
573 TORRENT_ASSERT(instantiated());
574 return boost::apply_visitor(
575 aux::read_some_visitor
<Mutable_Buffers
>(buffers
)
580 template <class Mutable_Buffers
, class Handler
>
581 void async_read_some(Mutable_Buffers
const& buffers
, Handler
const& handler
)
583 TORRENT_ASSERT(instantiated());
584 boost::apply_visitor(
585 aux::async_read_some_visitor
<Mutable_Buffers
, Handler
>(buffers
, handler
)
590 template <class Const_Buffers
, class Handler
>
591 void async_write_some(Const_Buffers
const& buffers
, Handler
const& handler
)
593 TORRENT_ASSERT(instantiated());
594 boost::apply_visitor(
595 aux::async_write_some_visitor
<Const_Buffers
, Handler
>(buffers
, handler
)
600 template <class Handler
>
601 void async_connect(endpoint_type
const& endpoint
, Handler
const& handler
)
603 TORRENT_ASSERT(instantiated());
604 boost::apply_visitor(
605 aux::async_connect_visitor
<endpoint_type
, Handler
>(endpoint
, handler
), m_variant
609 template <class IO_Control_Command
>
610 void io_control(IO_Control_Command
& ioc
)
612 TORRENT_ASSERT(instantiated());
613 boost::apply_visitor(
614 aux::io_control_visitor
<IO_Control_Command
>(ioc
), m_variant
618 template <class IO_Control_Command
>
619 void io_control(IO_Control_Command
& ioc
, error_code
& ec
)
621 TORRENT_ASSERT(instantiated());
622 boost::apply_visitor(
623 aux::io_control_visitor_ec
<IO_Control_Command
>(ioc
, ec
)
628 void bind(endpoint_type
const& endpoint
)
630 TORRENT_ASSERT(instantiated());
631 boost::apply_visitor(aux::bind_visitor
<endpoint_type
>(endpoint
), m_variant
);
634 void bind(endpoint_type
const& endpoint
, error_code
& ec
)
636 TORRENT_ASSERT(instantiated());
637 boost::apply_visitor(
638 aux::bind_visitor_ec
<endpoint_type
>(endpoint
, ec
), m_variant
642 void open(protocol_type
const& p
)
644 TORRENT_ASSERT(instantiated());
645 boost::apply_visitor(aux::open_visitor
<protocol_type
>(p
), m_variant
);
648 void open(protocol_type
const& p
, error_code
& ec
)
650 TORRENT_ASSERT(instantiated());
651 boost::apply_visitor(
652 aux::open_visitor_ec
<protocol_type
>(p
, ec
), m_variant
658 return boost::apply_visitor(aux::is_open_visitor(), m_variant
);
663 if (!instantiated()) return;
664 boost::apply_visitor(aux::close_visitor(), m_variant
);
667 void close(error_code
& ec
)
669 if (!instantiated()) return;
670 boost::apply_visitor(
671 aux::close_visitor_ec(ec
), m_variant
675 std::size_t in_avail() const
677 TORRENT_ASSERT(instantiated());
678 return boost::apply_visitor(aux::in_avail_visitor(), m_variant
);
681 std::size_t in_avail(error_code
& ec
) const
683 TORRENT_ASSERT(instantiated());
684 return boost::apply_visitor(
685 aux::in_avail_visitor_ec(ec
), m_variant
689 endpoint_type
remote_endpoint() const
691 TORRENT_ASSERT(instantiated());
692 return boost::apply_visitor(aux::remote_endpoint_visitor
<endpoint_type
>(), m_variant
);
695 endpoint_type
remote_endpoint(error_code
& ec
) const
697 TORRENT_ASSERT(instantiated());
698 return boost::apply_visitor(
699 aux::remote_endpoint_visitor_ec
<endpoint_type
>(ec
), m_variant
703 template <class SettableSocketOption
>
704 void set_option(SettableSocketOption
const& opt
)
706 TORRENT_ASSERT(instantiated());
707 boost::apply_visitor(aux::set_option_visitor
<SettableSocketOption
>(opt
)
711 template <class SettableSocketOption
>
712 error_code
set_option(SettableSocketOption
const& opt
, error_code
& ec
)
714 TORRENT_ASSERT(instantiated());
715 return boost::apply_visitor(aux::set_option_visitor_ec
<SettableSocketOption
>(opt
, ec
)
719 endpoint_type
local_endpoint() const
721 TORRENT_ASSERT(instantiated());
722 return boost::apply_visitor(aux::local_endpoint_visitor
<endpoint_type
>(), m_variant
);
725 endpoint_type
local_endpoint(error_code
& ec
) const
727 TORRENT_ASSERT(instantiated());
728 return boost::apply_visitor(
729 aux::local_endpoint_visitor_ec
<endpoint_type
>(ec
), m_variant
733 io_service
& get_io_service()
738 lowest_layer_type
& lowest_layer()
740 TORRENT_ASSERT(instantiated());
741 return boost::apply_visitor(
742 aux::lowest_layer_visitor
<lowest_layer_type
>(), m_variant
747 io_service
& m_io_service
;
748 variant_type m_variant
;
751 } // namespace libtorrent
753 #endif // VARIANT_STREAM_070211_HPP