asio-users Mailing List for asio C++ library (Page 260)
Brought to you by:
chris_kohlhoff
You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(6) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
|
Feb
|
Mar
(1) |
Apr
(3) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(5) |
Oct
(7) |
Nov
(8) |
Dec
(11) |
2006 |
Jan
(11) |
Feb
(14) |
Mar
(8) |
Apr
(3) |
May
(27) |
Jun
(15) |
Jul
(43) |
Aug
(64) |
Sep
(19) |
Oct
(44) |
Nov
(69) |
Dec
(82) |
2007 |
Jan
(79) |
Feb
(153) |
Mar
(169) |
Apr
(148) |
May
(181) |
Jun
(114) |
Jul
(152) |
Aug
(104) |
Sep
(77) |
Oct
(128) |
Nov
(185) |
Dec
(215) |
2008 |
Jan
(100) |
Feb
(116) |
Mar
(115) |
Apr
(74) |
May
(152) |
Jun
(107) |
Jul
(117) |
Aug
(115) |
Sep
(141) |
Oct
(75) |
Nov
(31) |
Dec
(47) |
2009 |
Jan
(51) |
Feb
(65) |
Mar
(54) |
Apr
(60) |
May
(6) |
Jun
(107) |
Jul
(82) |
Aug
(133) |
Sep
(144) |
Oct
(11) |
Nov
(54) |
Dec
(26) |
2010 |
Jan
(30) |
Feb
(17) |
Mar
(93) |
Apr
(47) |
May
(93) |
Jun
(73) |
Jul
(32) |
Aug
(60) |
Sep
(59) |
Oct
(58) |
Nov
(71) |
Dec
(28) |
2011 |
Jan
(58) |
Feb
(65) |
Mar
(38) |
Apr
(83) |
May
(45) |
Jun
(70) |
Jul
(71) |
Aug
(7) |
Sep
(33) |
Oct
(65) |
Nov
(33) |
Dec
(16) |
2012 |
Jan
(13) |
Feb
(32) |
Mar
(30) |
Apr
(67) |
May
(57) |
Jun
(59) |
Jul
(8) |
Aug
(61) |
Sep
(48) |
Oct
(23) |
Nov
(29) |
Dec
(8) |
2013 |
Jan
(37) |
Feb
(20) |
Mar
(11) |
Apr
(11) |
May
(9) |
Jun
(26) |
Jul
(6) |
Aug
(18) |
Sep
(7) |
Oct
(29) |
Nov
(2) |
Dec
(17) |
2014 |
Jan
(11) |
Feb
(12) |
Mar
(6) |
Apr
(26) |
May
(17) |
Jun
(12) |
Jul
(12) |
Aug
|
Sep
(6) |
Oct
(3) |
Nov
|
Dec
(7) |
2015 |
Jan
(3) |
Feb
(3) |
Mar
(7) |
Apr
(23) |
May
|
Jun
(1) |
Jul
(2) |
Aug
(33) |
Sep
(16) |
Oct
(2) |
Nov
(2) |
Dec
(13) |
2016 |
Jan
(7) |
Feb
(22) |
Mar
(11) |
Apr
|
May
(10) |
Jun
(2) |
Jul
(3) |
Aug
(2) |
Sep
(1) |
Oct
(29) |
Nov
(3) |
Dec
(21) |
2017 |
Jan
(4) |
Feb
(31) |
Mar
(8) |
Apr
(4) |
May
(1) |
Jun
(4) |
Jul
(32) |
Aug
(28) |
Sep
(2) |
Oct
(11) |
Nov
(1) |
Dec
|
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(10) |
Oct
|
Nov
(4) |
Dec
(20) |
2019 |
Jan
(3) |
Feb
|
Mar
(1) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2020 |
Jan
(2) |
Feb
(1) |
Mar
|
Apr
(2) |
May
(1) |
Jun
|
Jul
(11) |
Aug
(2) |
Sep
(6) |
Oct
|
Nov
|
Dec
|
2021 |
Jan
|
Feb
(1) |
Mar
(1) |
Apr
|
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
(1) |
2022 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
(4) |
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(1) |
Dec
|
2023 |
Jan
(3) |
Feb
|
Mar
(5) |
Apr
(3) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(4) |
2024 |
Jan
|
Feb
(3) |
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
(1) |
Aug
(6) |
Sep
|
Oct
|
Nov
|
Dec
|
From: Arvid N. <c9...@cs...> - 2006-01-17 20:33:25
|
On Jan 17, 2006, at 13:29, Christopher Kohlhoff wrote: > You may notice quite a bit has changed when you do try it - I'm > in the middle of implementing some of the changes suggested in > the boost review. Here's a quick guide to some things you may need > to do to your code: > > - Replace demuxer with io_service > > - Replace stream_socket with ipv4::tcp::socket > > - Replace socket_acceptor with ipv4::tcp::acceptor > > - Replace datagram_socket with ipv4::udp::socket Thanks! I'm using cvs head now. I didn't notice any difference until I found out that I was forgetting to call reset() on the demuxer (io_service), maybe there could be an assert for that? So, anyway, sorry for bothering the list. -- Arvid Norberg |
From: Christopher K. <ch...@ko...> - 2006-01-17 12:29:10
|
Hi Arvid, --- Arvid Norberg <c9...@cs...> wrote: > Ok, I will try with the cvs version then. You may notice quite a bit has changed when you do try it - I'm in the middle of implementing some of the changes suggested in the boost review. Here's a quick guide to some things you may need to do to your code: - Replace demuxer with io_service - Replace stream_socket with ipv4::tcp::socket - Replace socket_acceptor with ipv4::tcp::acceptor - Replace datagram_socket with ipv4::udp::socket Cheers, Chris |
From: Arvid N. <c9...@cs...> - 2006-01-17 12:09:46
|
On Jan 17, 2006, at 06:17, Christopher Kohlhoff wrote: > Hi Arvid, > > --- Arvid Norberg <c9...@cs...> wrote: >> I was a bit surprised that waiting for an >> async_get_host_by_name() on a host_resolver wouldn't be >> considered as "work" by the demuxer::run () function. i.e. it >> returned when the only operation I had pending was a name >> lookup. >> >> I find this to be a bit unexpected. > > Hmm, sounds like a bug. There is a demuxer::work member variable > inside the asio::ipv4::detail::host_resolver_service's nested > class get_host_by_name_handler, so I'm not sure why it should've > returned early. > >> Anyway, my attempt to work around this was to us a >> demuxer::work instance to pass along with my handler (by >> value) for the async_get_host_by_name() operation. That's >> when I encountered the second problem. >> >> From what I can understand (didn't investigate too >> thoroughly), it looks like asio deadlocks when the handler >> object is being copied, and the work instance is destructed. >> >> The destructor will lock the demuxer/reactor before it >> decrements the work counter, but the lock is already held by >> that thread, and it is not a recursive mutex. > > Can you show me the callstack when the deadlock occurs? I have > already fixed another couple of deadlock bugs since 0.3.6 that > were a side effect of adding the demuxer::work class. Maybe this > one is related. Ok, I will try with the cvs version then. Here's the callstack at least, and when I think of it, I'm not sure my first analysis was correct, since the construction of the work object also locks the service, but it didn't deadlock. What I do here is that I create the name lookup operation and the work object from within a timer event. #0 0x9002b8a8 in semaphore_wait_signal_trap () #1 0x900019cc in pthread_mutex_lock () #2 0x00108b4c in boost::asio::detail::posix_mutex::lock (this=0xb02affb8) at ../../boost_1_33_0_asio/boost/asio/detail/ posix_mutex.hpp:65 #3 0x001148bc in boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex>::scop ed_lock (this=0xf007fff8, m=@0xb02affb8) at ../../boost_1_33_0_asio/ boost/asio/detail/scoped_lock.hpp:36 #4 0x0011ff40 in boost::asio::detail::task_demuxer_service<boost::asio::detail::kqueue_re actor<false> >::work_finished (this=0xb02affb8) at ../../ boost_1_33_0_asio/boost/asio/detail/task_demuxer_service.hpp:195 #5 0x0011fff0 in boost::asio::demuxer_service<std::allocator<void> >::work_finished (this=0xb02abff8) at ../../boost_1_33_0_asio/boost/ asio/demuxer_service.hpp:110 #6 0x00120040 in boost::asio::basic_demuxer<boost::asio::demuxer_service<std::allocator<v oid> > >::work::~work (this=0xf0080224) at ../../boost_1_33_0_asio/ boost/asio/basic_demuxer.hpp:291 #7 0x001968a4 in boost::_bi::value<boost::asio::basic_demuxer<boost::asio::demuxer_servic e<std::allocator<void> > >::work>::~value (this=0xf0080224) at /Users/ arvid/Documents/dev/libtorrent/client_test/../src/ http_tracker_connection.cpp:233 #8 0x00196a20 in boost::_bi::list3<boost::_bi::value<boost::intrusive_ptr<libtorrent::htt p_tracker_connection> >, boost::arg<1>, boost::_bi::value<boost::asio::basic_demuxer<boost::asio::demuxer_servic e<std::allocator<void> > >::work> >::~list3 (this=0xf008021c) at / Users/arvid/Documents/dev/libtorrent/client_test/../src/ http_tracker_connection.cpp:233 #9 0x00196d0c in boost::_bi::bind_t<void, boost::_mfi::mf2<void, libtorrent::http_tracker_connection, boost::asio::error const&, boost::asio::basic_demuxer<boost::asio::demuxer_service<std::allocator<v oid> > >::work>, boost::_bi::list3<boost::_bi::value<boost::intrusive_ptr<libtorrent::htt p_tracker_connection> >, boost::arg<1>, boost::_bi::value<boost::asio::basic_demuxer<boost::asio::demuxer_servic e<std::allocator<void> > >::work> > >::~bind_t (this=0xf0080214) at / Users/arvid/Documents/dev/libtorrent/client_test/../src/ http_tracker_connection.cpp:233 #10 0x0005fdd8 in libtorrent::http_tracker_connection::http_tracker_connection (this=0xb5b0bf1c, d=@0xbffff2ac, man=@0xbffff1dc, req=@0xf0080580, hostname=@0xf0080470, port=80, request=@0xf0080444, c=@0xf008043c, stn=@0xbffff304, auth=@0xf008057c) at /Users/arvid/Documents/dev/ libtorrent/client_test/../src/http_tracker_connection.cpp:233 #11 0x0002bdc8 in libtorrent::tracker_manager::queue_request (this=0xbffff1dc, d=@0xbffff2ac, req=@0xf0080580, auth=@0xf008057c, c=@0xf0080574) at /Users/arvid/Documents/dev/libtorrent/ client_test/../src/tracker_manager.cpp:480 #12 0x00035c74 in libtorrent::detail::session_impl::second_tick (this=0xbffff1ac, e=@0xb5af3ff4) at /Users/arvid/Documents/dev/ libtorrent/client_test/../src/session.cpp:803 #13 0x00159268 in boost::_mfi::mf1<void, libtorrent::detail::session_impl, boost::asio::error const&>::operator () (this=0xb5af3fe4, p=0xbffff1ac, a1=@0xb5af3ff4) at ../../ boost_1_33_0_asio/boost/bind/mem_fn_template.hpp:149 #14 0x00159300 in boost::_bi::list2<boost::_bi::value<libtorrent::detail::session_impl*>, boost::arg<1> >::operator()<boost::_mfi::mf1<void, libtorrent::detail::session_impl, boost::asio::error const&>, boost::_bi::list1<boost::asio::error&> > (this=0xb5af3fec, f=@0xb5af3fe4, a=@0xf008094c) at ../../boost_1_33_0_asio/boost/ bind.hpp:286 #15 0x0015937c in boost::_bi::bind_t<void, boost::_mfi::mf1<void, libtorrent::detail::session_impl, boost::asio::error const&>, boost::_bi::list2<boost::_bi::value<libtorrent::detail::session_impl*>, boost::arg<1> > >::operator()<boost::asio::error> (this=0xb5af3fe4, a1=@0xb5af3ff4) at ../../boost_1_33_0_asio/boost/bind/ bind_template.hpp:32 #16 0x001593d4 in boost::asio::detail::binder1<boost::_bi::bind_t<void, boost::_mfi::mf1<void, libtorrent::detail::session_impl, boost::asio::error const&>, boost::_bi::list2<boost::_bi::value<libtorrent::detail::session_impl*>, boost::arg<1> > >, boost::asio::error>::operator() (this=0xb5af3fe4) at ../../boost_1_33_0_asio/boost/asio/detail/bind_handler.hpp:43 #17 0x0015943c in boost::asio::detail::task_demuxer_service<boost::asio::detail::kqueue_re actor<false> >::handler_wrapper<boost::asio::detail::binder1<boost::_bi::bind_t<void , boost::_mfi::mf1<void, libtorrent::detail::session_impl, boost::asio::error const&>, boost::_bi::list2<boost::_bi::value<libtorrent::detail::session_impl*>, boost::arg<1> > >, boost::asio::error> >::do_call (base=0xb5af3fdc) at ../../boost_1_33_0_asio/boost/asio/detail/task_demuxer_service.hpp: 331 #18 0x00145b74 in boost::asio::detail::task_demuxer_service<boost::asio::detail::kqueue_re actor<false> >::handler_base::call (this=0xb5af3fdc) at ../../ boost_1_33_0_asio/boost/asio/detail/task_demuxer_service.hpp:300 #19 0x001568a8 in boost::asio::detail::task_demuxer_service<boost::asio::detail::kqueue_re actor<false> >::run (this=0xb02affb8) at ../../boost_1_33_0_asio/ boost/asio/detail/task_demuxer_service.hpp:99 #20 0x00156b84 in boost::asio::demuxer_service<std::allocator<void> >::run (this=0xb02abff8) at ../../boost_1_33_0_asio/boost/asio/ demuxer_service.hpp:86 #21 0x00156bd4 in boost::asio::basic_demuxer<boost::asio::demuxer_service<std::allocator<v oid> > >::run (this=0xbffff2ac) at ../../boost_1_33_0_asio/boost/asio/ basic_demuxer.hpp:106 #22 0x0003750c in libtorrent::detail::session_impl::operator() (this=0xbffff1ac) at /Users/arvid/Documents/dev/libtorrent/ client_test/../src/session.cpp:879 #23 0x0015cd04 in boost::detail::function::void_function_obj_invoker0<libtorrent::detail:: session_impl, void>::invoke (function_obj_ptr={obj_ptr = <incomplete type>, const_obj_ptr = 0xbffff1ac, func_ptr = 0xbffff1ac, data = "\277"}) at ../../boost_1_33_0_asio/boost/function/ function_template.hpp:136 #24 0x001b3200 in boost::function0<void, std::allocator<boost::function_base> >::operator() (this=0xf0080e2c) at ../../boost_1_33_0_asio/boost/function/function_template.hpp:576 #25 0x00065a48 in thread_proxy (param=<incomplete type>) at /Users/ arvid/Documents/dev/libtorrent/client_test/../../boost_1_33_0_asio/ libs/thread/src/thread.cpp:113 #26 0x9002b200 in _pthread_body () -- Arvid Norberg |
From: Christopher K. <ch...@ko...> - 2006-01-17 06:47:03
|
Hi Arvid, --- Arvid Norberg <c9...@cs...> wrote: > I was a bit surprised that waiting for an > async_get_host_by_name() on a host_resolver wouldn't be > considered as "work" by the demuxer::run () function. i.e. it > returned when the only operation I had pending was a name > lookup. > > I find this to be a bit unexpected. BTW, I haven't been able to reproduce this problem with the CVS version of asio using a simple test program, so there might be something else going on. Cheers, Chris |
From: Christopher K. <ch...@ko...> - 2006-01-17 05:17:24
|
Hi Arvid, --- Arvid Norberg <c9...@cs...> wrote: > I was a bit surprised that waiting for an > async_get_host_by_name() on a host_resolver wouldn't be > considered as "work" by the demuxer::run () function. i.e. it > returned when the only operation I had pending was a name > lookup. > > I find this to be a bit unexpected. Hmm, sounds like a bug. There is a demuxer::work member variable inside the asio::ipv4::detail::host_resolver_service's nested class get_host_by_name_handler, so I'm not sure why it should've returned early. > Anyway, my attempt to work around this was to us a > demuxer::work instance to pass along with my handler (by > value) for the async_get_host_by_name() operation. That's > when I encountered the second problem. > > From what I can understand (didn't investigate too > thoroughly), it looks like asio deadlocks when the handler > object is being copied, and the work instance is destructed. > > The destructor will lock the demuxer/reactor before it > decrements the work counter, but the lock is already held by > that thread, and it is not a recursive mutex. Can you show me the callstack when the deadlock occurs? I have already fixed another couple of deadlock bugs since 0.3.6 that were a side effect of adding the demuxer::work class. Maybe this one is related. Cheers, Chris |
From: Arvid N. <c9...@cs...> - 2006-01-17 04:18:11
|
Hi. I was a bit surprised that waiting for an async_get_host_by_name() on a host_resolver wouldn't be considered as "work" by the demuxer::run () function. i.e. it returned when the only operation I had pending was a name lookup. I find this to be a bit unexpected. Anyway, my attempt to work around this was to us a demuxer::work instance to pass along with my handler (by value) for the async_get_host_by_name() operation. That's when I encountered the second problem. From what I can understand (didn't investigate too thoroughly), it looks like asio deadlocks when the handler object is being copied, and the work instance is destructed. The destructor will lock the demuxer/reactor before it decrements the work counter, but the lock is already held by that thread, and it is not a recursive mutex. I found this a bit strange too, considering the text from the manual: "The work class is copy-constructible so that it may be used as a data member in a handler class. It is not assignable." So, am I doing something wrong? My use case is simply to: 1. look up name 2. connect 3. send data 4. receive data where each step is an async operation. I'm using MacOS X with the boost review version of asio. thanks. -- Arvid Norberg |
From: Arvid N. <c9...@cs...> - 2005-12-15 23:24:14
|
On Dec 15, 2005, at 13:21, Christopher Kohlhoff wrote: > Hi Arvid, > > Sorry for the delayed reply on this one. I'm spending a lot of time > reading and answering emails at the moment ;) > > --- Arvid Norberg <c9...@cs...> wrote: >> I have a stream_socket, and I want to throttle the bandwidth >> it uses for the data I send and receive on that socket. Right >> now I have implemented this as a per second quota. When the >> socket runs out of quota it won't receive anything until the >> next second, when it's restored again. > <snip> >> And, btw, is this a stupid way of throttling the download >> speed? (assuming there's no protocol support that can tell >> the other side to throttle its send rate). > > How about this for an idea, although not sure if it fits your > use case exactly: develop a stream template (similar to > ssl::stream or buffered_stream) that embargoes data until the > quota would not be exceeded. Thanks! That's a very nice solution. > For example: > [...] -- Arvid Norberg |
From: Christopher K. <ch...@ko...> - 2005-12-15 12:21:23
|
Hi Arvid, Sorry for the delayed reply on this one. I'm spending a lot of time reading and answering emails at the moment ;) --- Arvid Norberg <c9...@cs...> wrote: > I have a stream_socket, and I want to throttle the bandwidth > it uses for the data I send and receive on that socket. Right > now I have implemented this as a per second quota. When the > socket runs out of quota it won't receive anything until the > next second, when it's restored again. <snip> > And, btw, is this a stupid way of throttling the download > speed? (assuming there's no protocol support that can tell > the other side to throttle its send rate). How about this for an idea, although not sure if it fits your use case exactly: develop a stream template (similar to ssl::stream or buffered_stream) that embargoes data until the quota would not be exceeded. For example: template <typename Next_Layer> class throttling_stream { public: ... void async_write_some(const Const_Buffers& b, Handler h) { if (quota_would_be_exceeded) { // Can't send yet. Delay write until back within quota. write_timer_.expires_from_now(...); write_timer_.async_wait(boost::bind( &throttling_stream::handle_write_timer, b, h)); } else { // We can write now without exceeding quota. next_layer_.async_write_some(b, h); } } void handle_write_timer(const Const_Buffers& b, Handler h) { // We are now allowed to write the data. next_layer_.async_write_some(b, h); } private: deadline_timer write_timer_; Next_Layer next_layer_; }; That way there's no need for a flag to indicate whether a read or write is already in progress. From the point of view of the caller, the asynchronous operation simply takes a little longer to ensure that the quota is not exceeded. Cheers, Chris |
From: Christopher K. <ch...@ko...> - 2005-12-14 05:01:56
|
Hi Arvid, --- Arvid Norberg <c9...@cs...> wrote: > Hope you don't mind me putting this back in the list. No worries. I should change the list settings to make replies go to the list by default anyway. > I looked into this and I can't understand where you actually > needs the compile-time polymorphism. If I understand > correctly, the native type returned by the data() function on > an endpoint is the same for all endpoints, both udp and tcp. > So, the only reason I can see is that you want it to be > possible to pass both a tcp::endpoint and a udp::endpoint to > the function. Is that correct? No. The ipv4::tcp::endpoint and ipv4::udp::endpoints are the only endpoint types implemented right now, but in the future there could be endpoint types for IPv6 (both for TCP and UDP), UNIX domain sockets, bluetooth, infrared and so on. These can all use different sockaddr* structures. The get_*_endpoint functions need to work with all of these types. What's supported is determined by the operating system you're running on. Cheers, Chris |
From: Arvid N. <c9...@cs...> - 2005-12-14 01:59:46
|
Hi. I have a stream_socket, and I want to throttle the bandwidth it uses for the data I send and receive on that socket. Right now I have implemented this as a per second quota. When the socket runs out of quota it won't receive anything until the next second, when it's restored again. The use pattern for receiving seems to be: main() { socket.async_read_some(handler, ...); demuxer.run(); } void handler(...) { // process received data socket.async_read_some(handler, ...); } Something like that. Now that I want to throttle the download speed; at the end of the handler I sometimes don't want to call async_read_some(), because the download quota for this second is already used up. But in some situations, where the quota is much bigger than the actual transfer rate, it will always call async_read_some() at the end. Now, every time I reset the receive quota, I will have to check: "am I currently waiting for data or should I call async_read_some() now?" This would be pretty easy to know, just by storing that state with my connection, but maybe it could be useful to be able to query the socket for that too. I'm not sure if it's really a good idea, since the interface is pretty big as it is though, but at least it would make the invariance of my connection class easier to maintain. And, btw, is this a stupid way of throttling the download speed? (assuming there's no protocol support that can tell the other side to throttle its send rate). thanks. -- Arvid Norberg |
From: Arvid N. <c9...@cs...> - 2005-12-14 01:43:56
|
Hope you don't mind me putting this back in the list. On Dec 2, 2005, at 20:38, Christopher Kohlhoff wrote: > --- Arvid Norberg <c9...@cs...> wrote: > [...] >> What's the rationale behind having >> basic_stream_socket::get_remote_endpoint() not return an endpoint, >> but take a reference to one? It makes it much more cumbersome to use >> because I have to have named temporaries. If there's a good reason, I > > It's because a return type does not allow compile-time polymorphism on > the endpoint type. I looked into this and I can't understand where you actually needs the compile-time polymorphism. If I understand correctly, the native type returned by the data() function on an endpoint is the same for all endpoints, both udp and tcp. So, the only reason I can see is that you want it to be possible to pass both a tcp::endpoint and a udp::endpoint to the function. Is that correct? If you call get_remote_endpoint() on a stream_socket, would it be a limitation to just accept tcp::endpoint? >> think it should be stated in the documentation. I also think it >> should just be called remote_endpoint(). > > I use the get_ in the name here because it's a socket operation (which > can fail with an error) rather than a simple property accessor. thanks. -- Arvid Norberg |
From: Christopher K. <ch...@ko...> - 2005-12-10 22:14:53
|
Hello all, A review of the asio library for possible inclusion in Boost has just started and runs until December 23rd. Review feedback and discussion, both good and bad, would be much appreciated! See: http://article.gmane.org/gmane.comp.lib.boost.devel/135486 for more information. Please note that all review discussion should take place on the boost developer mailing list, or be sent directly to the review manager. Cheers, Chris |
From: Christopher K. <ch...@ko...> - 2005-12-10 22:11:02
|
asio version 0.3.6 has been released. It may be downloaded from the asio sourceforge page at http://asio.sourceforge.net. This release is focused on cleaning up the code and improving the documentation. The major changes in this version include a new system_exception class to report serious OS errors, a Boost.Serialization example, a custom socket service example, and greater detail in the reference and design documentation. The changes since asio 0.3.5 include: - A new asio::system_exception class used to report serious OS errors, such as a failure to create a mutex or a thread. - The asio::error::what() function now returns a string that describes the error. - The asio::socket_option::* helper templates have been moved to the detail namespace. - The asio::io_control::* helper templates have been moved to the detail namespace. - Win32 implementation now uses AcceptEx to perform asynchronous accept operations. - A new asio::buffer() overload for std::string. - The asio::socket_base::send_timeout and asio::socket_base::receive_timeout options have been removed as they are not portable. - New example showing how to use Boost.Serialization with asio. - New example demonstrating how to develop custom services. - New design documentation, including notes on how the backend is implemented on specific platforms. - General documentation improvements, including inheritance diagrams and example code snippets in the reference. - General code cleanup, including improved exception safety and error handling. |
From: Christopher K. <ch...@ko...> - 2005-12-10 21:58:30
|
Hi Arvid, Following up on my earlier (off-list) reply... --- Arvid Norberg <c9...@cs...> wrote: > I have a few comments/questions. > I think asio::error should derive from std::exception and > implement a what() member function. Right now I can't find > any way to convert an error code into a descriptive string, > and I think a what() function would be a good candidate for > doing that. For 0.3.6 I've changed asio::error::what() to return the string associated with the error, and also changed the doxygen options to make it clear that asio::error inherits from std::exception. Cheers, Chris |
From: Christopher K. <ch...@ko...> - 2005-12-09 21:29:24
|
Hi Eugene, --- "Alterman, Eugene" <Eugene.Alterman@Staples.com> wrote: > Exposing a lower layer via a public method is IMHO a flaw in the > design that > violates layering. My guess is that it is only used for connection > establishment (connect/accept). Also to allow access to socket options, to get the remote and local endpoints, bind the socket to a specific interface, etc. I see access to these as essential. > After a connection has been > established a > lower layer is not supposed to be accessed directly, and > providing unrestricted access to it is potentially unsafe. The stack of layers design is designed as a compile-time equivalent of ACE's ACE_Task/ACE_Module/ACE_Stream idea. The next_layer()/lowest_layer() functions and associated typedefs are provided to allow efficient access to the various layers. In this sense it's not really intended as an information-hiding abstraction. Is there a way to reconcile both safety and the need to access some of the socket's functionality directly? I don't know, so it may be worth bringing up in the boost review. Cheers, Chris |
From: Alterman, E. <Eugene.Alterman@Staples.com> - 2005-12-09 21:08:13
|
Exposing a lower layer via a public method is IMHO a flaw in the design that violates layering. My guess is that it is only used for connection establishment (connect/accept). After a connection has been established a lower layer is not supposed to be accessed directly, and providing unrestricted access to it is potentially unsafe. |
From: Arvid N. <c9...@cs...> - 2005-12-02 12:47:19
|
I have a few comments/questions. I think asio::error should derive from std::exception and implement a what() member function. Right now I can't find any way to convert an error code into a descriptive string, and I think a what() function would be a good candidate for doing that. What's the rationale behind having basic_stream_socket::get_remote_endpoint() not return an endpoint, but take a reference to one? It makes it much more cumbersome to use because I have to have named temporaries. If there's a good reason, I think it should be stated in the documentation. I also think it should just be called remote_endpoint(). Personally, I also consider the headers-only to be a show-stopper for boost acceptance. I think this should be fixed, preferably before the review start. -- Arvid Norberg |
From: Alterman, E. <Eugene.Alterman@Staples.com> - 2005-11-22 21:49:26
|
Hi Chris, Thank you for reply. > -----Original Message----- > From: Christopher Kohlhoff [mailto:ch...@ko...] > Sent: Monday, November 21, 2005 8:09 PM > To: Alterman, Eugene; 'asi...@li...' > Subject: Re: [asio-users] ..._buffer_container_1 > > > Hi Eugene, > > --- "Alterman, Eugene" <Eugene.Alterman@Staples.com> wrote: > > > I think it is better to have (mutable_/const_)buffer_conteiner_1 > > derived > > from boost::array<..._buffer, 1>. Then the only thing you need to do > > is to add construction from a buffer: > > > > class mutable_buffer_container_1 > > : public boost::array<mutable_buffer, 1> > > { > > public: > > /// Construct to represent a single modifiable buffer. > > explicit mutable_buffer_container_1(const mutable_buffer& b) > > { > > *begin() = b; > > } > > }; > > The problem was that I also wanted the return value of asio::buffer() to be > assignable directly into a const_buffer or mutable_buffer, e.g.: > > asio::const_buffer b = asio::buffer(data, size); > > or > > asio::mutable_buffer b = asio::buffer(data, size); > > Furthermore, in the case of asio::buffer() returning a > mutable_buffer_container_1, I want the "conversion" to mutable_buffer to be > a better conversion than to const_buffer. > > Otherwise you get ambiguities with code like: > > void foo(const mutable_buffer&); > void foo(const const_buffer&); > > char data[1024]; > foo(asio::buffer(data)); > > Using the inheritance here was the only way I could find to make this the > "better" conversion. I'd be happy to know about alternative ways of doing > it. I see. I think you can use Andrei Alexandrescu's mojo trick: Have mutable_buffer derived from const_buffer, and in mutable_buffer_container_1 declare operators: operator const_buffer() const; operator mutable_buffer(); This will give you the desired effect. See the discussion: http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/ c6fe15957ab6a261 > > Aside from more code, there is another problem with the current > > approach - 'end()' is defined as 'begin() + 1', but you can use > > pointer arithmetic > > legally only within an array. > > According to the C++ standard, in section 5.7/4 which discusses pointer > arithmetic: > > "For the purposes of these operators, a pointer to a nonarray object behaves > the same as a pointer to the first element of an aray of length one with the > type of the object as its element type." > > which i took to mean it was legal. I could be wrong though :) Of course I was wrong here :( Eugene. P.S. Great library! Thanks. |
From: Christopher K. <ch...@ko...> - 2005-11-22 01:08:51
|
Hi Eugene, --- "Alterman, Eugene" <Eugene.Alterman@Staples.com> wrote: > I think it is better to have (mutable_/const_)buffer_conteiner_1 > derived > from boost::array<..._buffer, 1>. Then the only thing you need to do > is to > add construction from a buffer: > > class mutable_buffer_container_1 > : public boost::array<mutable_buffer, 1> > { > public: > /// Construct to represent a single modifiable buffer. > explicit mutable_buffer_container_1(const mutable_buffer& b) > { > *begin() = b; > } > }; The problem was that I also wanted the return value of asio::buffer() to be assignable directly into a const_buffer or mutable_buffer, e.g.: asio::const_buffer b = asio::buffer(data, size); or asio::mutable_buffer b = asio::buffer(data, size); Furthermore, in the case of asio::buffer() returning a mutable_buffer_container_1, I want the "conversion" to mutable_buffer to be a better conversion than to const_buffer. Otherwise you get ambiguities with code like: void foo(const mutable_buffer&); void foo(const const_buffer&); char data[1024]; foo(asio::buffer(data)); Using the inheritance here was the only way I could find to make this the "better" conversion. I'd be happy to know about alternative ways of doing it. > Aside from more code, there is another problem with the current > approach - > 'end()' is defined as 'begin() + 1', but you can use pointer > arithmetic > legally only within an array. According to the C++ standard, in section 5.7/4 which discusses pointer arithmetic: "For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an aray of length one with the type of the object as its element type." which i took to mean it was legal. I could be wrong though :) Cheers, Chris |
From: Alterman, E. <Eugene.Alterman@Staples.com> - 2005-11-21 23:56:25
|
I think it is better to have (mutable_/const_)buffer_conteiner_1 derived from boost::array<..._buffer, 1>. Then the only thing you need to do is to add construction from a buffer: class mutable_buffer_container_1 : public boost::array<mutable_buffer, 1> { public: /// Construct to represent a single modifiable buffer. explicit mutable_buffer_container_1(const mutable_buffer& b) { *begin() = b; } }; Aside from more code, there is another problem with the current approach - 'end()' is defined as 'begin() + 1', but you can use pointer arithmetic legally only within an array. Eugene. |
From: Christopher K. <ch...@ko...> - 2005-11-18 11:27:00
|
asio version 0.3.5 has been released. It may be downloaded from the asio sourceforge page at http://asio.sourceforge.net. This release is focused on cleaning up and refining the interface. The most significant changes include consolidation and renaming of read and write functions, and the removal of the buffers() function in favour of just buffer(). Code that uses asio will need to be updated. The changes since asio 0.3.4 include: - Consolidated the free functions read(), read_n() and read_at_least_n() into a function named read(); write(), write_n() and write_at_least_n() into just write(); and likewise for their asynchronous counterparts. The default behaviour of read() and write() is now to attempt to transfer all of the data (i.e. equivalent to old read_n() and write_n()). The _at_least_n() behaviour can be obtained by passing a Completion_Condition function object: asio::read(s, bufs, asio::transfer_at_least(32)); - Renamed the Stream concept's read(), async_read(), write() and async_write() functions to read_some(), async_read_some(), write_some() and async_write_some() respectively. This was done to make it obvious to a library user that the operation can result in a short read or write. The name write() in particular was found to be error prone, since most of the time it will successfully transfer all of the data. Only occasional calls would result in a short write, leading to hard to find bugs. - Graceful connection closure now causes a read to complete with an error code (asio::error::eof) rather than returning 0. This removes the need for separate total_bytes_transferred and last_bytes_transferred handler parameters. It allows a function, such as asio::read() and asio::write(), to return an error to indicate that it is unable to fulfil its contract due to EOF. - Removed the asio::buffers() function and the ability to automatically chain buffer objects together. Instead, the asio::buffer() function now returns a type that meets the Const_Buffers or Mutable_Buffers concepts as appropriate. Scatter-gather I/O should now be performed by explicitly placing const_buffer or mutable_buffer objects into a container (such as std::vector, std::list or boost::array). To read into a single buffer you would now write: sock.read(asio::buffer(data, length)); To send multiple buffers you would use something like: std::vector<asio::const_buffer> bufs; bufs.push_back(asio::buffer(data1, length1)); bufs.push_back(asio::buffer(data2, length2)); sock.write(bufs); - Added comparison operators to the asio::ipv4::tcp::endpoint and asio::ipv4::udp::endpoint classes. - Removed the error handling expression templates. This functionality is better covered by a library such as Boost.Lambda. - Removed the fixed_buffer class from the library's public interface. The underlying buffer storage is no longer a template parameter on the buffered*_stream classes. - Removed the wrapped_handler class from the library's public interface. - Removed the consuming_buffers class from the libary's public interface. - Added new certificates for the SSL example, as the original ones expired after one month. - Used implementation-defined types rather than void* in the Socket_Option and IO_Control_Command concepts to avoid losing type safety. - Various code cleanup and bug fixes. - Added support for MSVC 8.0. - Documentation improvements. |
From: Christopher K. <ch...@ko...> - 2005-11-11 03:21:44
|
Hello all, As part of cleaning up asio's interface I am pondering the utility of the read_at_least_n/write_at_least_n free functions. I'd appreciate hearing from anyone who actually uses these functions (or their async counterparts), and anyone else who has an opinion on the matter :) The rationale for their existence is the use case where you want to ensure that a minimum number of bytes are transferred, but are willing to receive more than that minimum in order to minimise the number of system calls. However I have never used them in practice, and suspect that an application that needed that level of control might prefer to use the lower level (i.e. partial-read/write) functions directly. I'm considering taking them out for now on the following basis: - I want to simplify the asio interface to improve clarity and ease-of-use. - I want to get asio ready for a boost review asap. Including the functionality requires much more thought on how to make it elegant. - asio is obviously useful without them. So essentially I am proposing that the version of asio submitted for boost review does not include this functionality. If a compelling use case emerges in practice then the functionality can be added back after more careful consideration of the design (and with, I believe, no impact on other functionality). If somebody has a need right now, then I'll look at keeping them in, but it will delay getting a version ready for boost review submission. Cheers, Chris |
From: Christopher K. <ch...@ko...> - 2005-11-02 23:24:11
|
Hi Jose, Since you're using gcc 4.0.1, it's odd that it didn't show up for me when i tried with 4.0.2 (and i normally use 4.0). Anyway, I believe the problem is a side-effect of the change to use the boost unit test framework. Can you please try the following diff to see if it fixes the problem: Index: is_read_buffered_test.cpp =================================================================== RCS file: /cvsroot/asio/asio/src/tests/unit/is_read_buffered_test.cpp,v retrieving revision 1.2 diff -u -u -r1.2 is_read_buffered_test.cpp --- is_read_buffered_test.cpp 18 Sep 2005 11:42:35 -0000 1.2 +++ is_read_buffered_test.cpp 2 Nov 2005 23:20:28 -0000 @@ -85,24 +85,24 @@ { BOOST_CHECK(!asio::is_read_buffered<asio::stream_socket>::value); - BOOST_CHECK(asio::is_read_buffered< + BOOST_CHECK(!!asio::is_read_buffered< asio::buffered_read_stream<asio::stream_socket> >::value); BOOST_CHECK(!asio::is_read_buffered< asio::buffered_write_stream<asio::stream_socket> >::value); - BOOST_CHECK(asio::is_read_buffered< + BOOST_CHECK(!!asio::is_read_buffered< asio::buffered_stream<asio::stream_socket> >::value); BOOST_CHECK(!asio::is_read_buffered<test_stream>::value); - BOOST_CHECK(asio::is_read_buffered< + BOOST_CHECK(!!asio::is_read_buffered< asio::buffered_read_stream<test_stream> >::value); BOOST_CHECK(!asio::is_read_buffered< asio::buffered_write_stream<test_stream> >::value); - BOOST_CHECK(asio::is_read_buffered< + BOOST_CHECK(!!asio::is_read_buffered< asio::buffered_stream<test_stream> >::value); } Index: is_write_buffered_test.cpp =================================================================== RCS file: /cvsroot/asio/asio/src/tests/unit/is_write_buffered_test.cpp,v retrieving revision 1.2 diff -u -u -r1.2 is_write_buffered_test.cpp --- is_write_buffered_test.cpp 18 Sep 2005 11:42:35 -0000 1.2 +++ is_write_buffered_test.cpp 2 Nov 2005 23:20:28 -0000 @@ -88,10 +88,10 @@ BOOST_CHECK(!asio::is_write_buffered< asio::buffered_read_stream<asio::stream_socket> >::value); - BOOST_CHECK(asio::is_write_buffered< + BOOST_CHECK(!!asio::is_write_buffered< asio::buffered_write_stream<asio::stream_socket> >::value); - BOOST_CHECK(asio::is_write_buffered< + BOOST_CHECK(!!asio::is_write_buffered< asio::buffered_stream<asio::stream_socket> >::value); BOOST_CHECK(!asio::is_write_buffered<test_stream>::value); @@ -99,10 +99,10 @@ BOOST_CHECK(!asio::is_write_buffered< asio::buffered_read_stream<test_stream> >::value); - BOOST_CHECK(asio::is_write_buffered< + BOOST_CHECK(!!asio::is_write_buffered< asio::buffered_write_stream<test_stream> >::value); - BOOST_CHECK(asio::is_write_buffered< + BOOST_CHECK(!!asio::is_write_buffered< asio::buffered_stream<test_stream> >::value); } Cheers, Chris |
From: Christopher K. <ch...@ko...> - 2005-11-02 19:40:01
|
Hi Jose, --- jose <jj...@ya...> wrote: > tests/unit/is_read_buffered_test.cpp: In function > 'void is_read_buffered_test()': > tests/unit/is_read_buffered_test.cpp:88: error: > 'asio::is_read_buffered<asio::buffered_read_stream<asio::stream_socket, > asio::fixed_buffer<8192> > >::<anonymous enum>' > is/uses anonymous type I presume you are using g++, but what version are you using? Cheers, Chris |
From: jose <jj...@ya...> - 2005-11-02 19:19:00
|
Hi Chris, I'm trying to build the examples in 0.34 and I get the following error below. Thank you for continuing to improve asio Regards Jose ==================== tests/unit/is_read_buffered_test.cpp: In function 'void is_read_buffered_test()': tests/unit/is_read_buffered_test.cpp:88: error: 'asio::is_read_buffered<asio::buffered_read_stream<asio::stream_socket, asio::fixed_buffer<8192> > >::<anonymous enum>' is/uses anonymous type tests/unit/is_read_buffered_test.cpp:88: error: trying to instantiate 'template<class BoolConvertable> boost::test_tools::predicate_result::predicate_result(const BoolConvertable&)' tests/unit/is_read_buffered_test.cpp:94: error: 'asio::is_read_buffered<asio::buffered_stream<asio::stream_socket, asio::fixed_buffer<8192> > >::<anonymous enum>' is/uses anonymous type tests/unit/is_read_buffered_test.cpp:94: error: trying to instantiate 'template<class BoolConvertable> boost::test_tools::predicate_result::predicate_result(const BoolConvertable&)' tests/unit/is_read_buffered_test.cpp:99: error: 'asio::is_read_buffered<asio::buffered_read_stream<test_stream, asio::fixed_buffer<8192> > >::<anonymous enum>' is/uses anonymous type tests/unit/is_read_buffered_test.cpp:99: error: trying to instantiate 'template<class BoolConvertable> boost::test_tools::predicate_result::predicate_result(const BoolConvertable&)' tests/unit/is_read_buffered_test.cpp:105: error: 'asio::is_read_buffered<asio::buffered_stream<test_stream, asio::fixed_buffer<8192> > >::<anonymous enum>' is/uses anonymous type tests/unit/is_read_buffered_test.cpp:105: error: trying to instantiate 'template<class BoolConvertable> boost::test_tools::predicate_result::predicate_result(const BoolConvertable&)' make[2]: *** [tests/unit/is_read_buffered_test.o] Error 1 make[2]: Leaving directory `/root/dev/asio-0.3.4/src' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/root/dev/asio-0.3.4/src' make: *** [all-recursive] Error 1 ______________________________________________ Renovamos el Correo Yahoo! Nuevos servicios, más seguridad http://correo.yahoo.es |