makes all tracker requests 'stopped' when aborting
[libtorrent.git] / include / libtorrent / variant_stream.hpp
blob3551f5c9ea1bf68b50edeb4569be76711d00854d
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>
26 #else
27 #include <boost/asio/io_service.hpp>
28 #endif
30 # define NETWORK_VARIANT_STREAM_LIMIT 5
32 namespace libtorrent {
34 namespace aux
37 struct delete_visitor
38 : boost::static_visitor<>
40 template <class T>
41 void operator()(T* p) const
43 delete p;
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_) {}
58 template <class T>
59 void operator()(T* p) const
61 p->io_control(ioc, ec);
64 void operator()(boost::blank) const
67 IO_Control_Command& ioc;
68 error_code& ec;
71 template<class IO_Control_Command>
72 struct io_control_visitor
73 : boost::static_visitor<>
75 io_control_visitor(IO_Control_Command& ioc)
76 : ioc(ioc) {}
78 template <class T>
79 void operator()(T* p) const
81 p->io_control(ioc);
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)
96 : endpoint(endpoint)
97 , handler(handler)
100 template <class T>
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_)
120 : endpoint(ep)
121 , ec(ec_)
124 template <class T>
125 void operator()(T* p) const
126 { p->bind(endpoint, ec); }
128 void operator()(boost::blank) const {}
130 EndpointType const& endpoint;
131 error_code& ec;
134 template <class EndpointType>
135 struct bind_visitor
136 : boost::static_visitor<>
138 bind_visitor(EndpointType const& ep)
139 : endpoint(ep)
142 template <class T>
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_)
158 : proto(p)
159 , ec(ec_)
162 template <class T>
163 void operator()(T* p) const
164 { p->open(proto, ec); }
166 void operator()(boost::blank) const {}
168 Protocol const& proto;
169 error_code& ec;
172 template <class Protocol>
173 struct open_visitor
174 : boost::static_visitor<>
176 open_visitor(Protocol const& p)
177 : proto(p)
180 template <class T>
181 void operator()(T* p) const
182 { p->open(proto); }
184 void operator()(boost::blank) const {}
186 Protocol const& proto;
189 // -------------- is_open -----------
191 struct is_open_visitor
192 : boost::static_visitor<bool>
194 is_open_visitor() {}
196 template <class T>
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_)
209 : ec(ec_)
212 template <class T>
213 void operator()(T* p) const
214 { p->close(ec); }
216 void operator()(boost::blank) const {}
218 error_code& ec;
221 struct close_visitor
222 : boost::static_visitor<>
224 template <class T>
225 void operator()(T* p) const
226 { p->close(); }
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_)
238 : ec(ec_)
241 template <class T>
242 EndpointType operator()(T const* p) const
243 { return p->remote_endpoint(ec); }
245 EndpointType operator()(boost::blank) const
246 { return EndpointType(); }
248 error_code& ec;
251 template <class EndpointType>
252 struct remote_endpoint_visitor
253 : boost::static_visitor<EndpointType>
255 template <class T>
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)
270 : opt_(opt)
273 template <class T>
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)
287 : opt_(opt)
288 , ec_(ec)
291 template <class T>
292 error_code operator()(T* p) const
293 { return p->set_option(opt_, ec_); }
295 error_code operator()(boost::blank) const
296 { return ec_; }
298 SettableSocketOption const& opt_;
299 error_code& ec_;
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_)
309 : ec(ec_)
312 template <class T>
313 EndpointType operator()(T const* p) const
315 return p->local_endpoint(ec);
318 EndpointType operator()(boost::blank) const
320 return EndpointType();
323 error_code& ec;
326 template <class EndpointType>
327 struct local_endpoint_visitor
328 : boost::static_visitor<EndpointType>
330 template <class T>
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)
349 : buffers(buffers)
350 , handler(handler)
353 template <class T>
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)
372 : buffers(buffers)
375 template <class T>
376 std::size_t operator()(T* p) const
377 { return p->read_some(buffers); }
379 std::size_t operator()(boost::blank) const
380 { return 0; }
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_)
390 : buffers(buffers)
391 , ec(ec_)
394 template <class T>
395 std::size_t operator()(T* p) const
396 { return p->read_some(buffers, ec); }
398 std::size_t operator()(boost::blank) const
399 { return 0; }
401 Mutable_Buffers const& buffers;
402 error_code& ec;
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)
412 : buffers(buffers)
413 , handler(handler)
416 template <class T>
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_)
435 : ec(ec_)
438 template <class T>
439 std::size_t operator()(T const* p) const
441 return p->in_avail(ec);
444 std::size_t operator()(boost::blank) const
446 return 0;
449 error_code& ec;
452 struct in_avail_visitor
453 : boost::static_visitor<std::size_t>
455 template <class 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&>
471 template <class T>
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&>
489 template <class T>
490 LowestLayer& operator()(T* p) const
492 return p->lowest_layer();
495 LowestLayer& operator()(boost::blank) const
497 return *(LowestLayer*)0;
501 } // namespace aux
503 template <
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
510 public:
511 typedef BOOST_PP_CAT(boost::mpl::vector, NETWORK_VARIANT_STREAM_LIMIT)<
512 BOOST_PP_ENUM_PARAMS(NETWORK_VARIANT_STREAM_LIMIT, S)
513 > types0;
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<
520 types
521 , boost::add_pointer<boost::mpl::_>
522 >::type
523 , boost::blank
524 >::type
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()) {}
534 template <class S>
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();
541 owned.release();
544 template <class S>
545 S& get()
547 return *boost::get<S*>(m_variant);
550 bool instantiated() const
552 return m_variant.which() != boost::mpl::size<types>::value;
555 ~variant_stream()
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)
566 , m_variant
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)
576 , m_variant
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)
586 , m_variant
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)
596 , m_variant
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)
624 , m_variant
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
656 bool is_open() const
658 return boost::apply_visitor(aux::is_open_visitor(), m_variant);
661 void close()
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)
708 , m_variant);
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)
716 , m_variant);
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()
735 return m_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
746 private:
747 io_service& m_io_service;
748 variant_type m_variant;
751 } // namespace libtorrent
753 #endif // VARIANT_STREAM_070211_HPP