[netlib] 0.8-beta now available!

Hi Everyone, advanced apologies for cross-posting. I've just tagged and uploaded archives of the cpp-netlib 0.8-beta which features: * An asynchronous server template, allowing for server-side streaming of data, asynchronous writing and reading facilities for server-side handlers, and a thread pool implementation that's temporarily using Boost.Asio's io_service for application-specific asynchronous handlers to run from. * A `ready(...)` wrapper to check for whether an asynchronous client's response is ready. The documentation has also been updated to feature a brand-new reference manual detailing the implementation, caveats, and public API of the HTTP client and server templates. You can go ahead and download the 0.8-beta and report issues you find either directly to me or through the mailing lists (Boost.User, Boost.Devel, and the cpp-netlib developers mailing lists). The target release for 0.8 will be this Friday, November 19, 2010. As usual, you can download the 0.8-beta package from GitHub at: https://github.com/cpp-netlib/cpp-netlib/downloads You can also check out the documentation for 0.8-beta at: http://cpp-netlib.github.com/0.8-beta Thanks everyone and I look forward to most appreciated feedback! -- Dean Michael Berris deanberris.com

On 11/15/2010 01:04 PM, Dean Michael Berris wrote:
Hi Everyone, advanced apologies for cross-posting.
I've just tagged and uploaded archives of the cpp-netlib 0.8-beta which features:
* An asynchronous server template, allowing for server-side streaming of data, asynchronous writing and reading facilities for server-side handlers, and a thread pool implementation that's temporarily using Boost.Asio's io_service for application-specific asynchronous handlers to run from. * A `ready(...)` wrapper to check for whether an asynchronous client's response is ready.
The documentation has also been updated to feature a brand-new reference manual detailing the implementation, caveats, and public API of the HTTP client and server templates.
It looks interesting on first sight. I'm wondering why you chose an active object pattern for implementing asynchronous clients, and not the proactor pattern as enabled by Asio. If someone wants to open many connections (e.g., a web crawler), one thread per connection probably isn't the way to go. This issue may be related to some of my concerns surrounding the current client API, where I am missing the (non-future) async_ methods. Wouldn't a name like http++ be covering better what the library does? Kind regards, Rutger

On Mon, Nov 15, 2010 at 8:55 PM, Rutger ter Borg <rutger@terborg.net> wrote:
On 11/15/2010 01:04 PM, Dean Michael Berris wrote:
The documentation has also been updated to feature a brand-new reference manual detailing the implementation, caveats, and public API of the HTTP client and server templates.
It looks interesting on first sight.
I'm wondering why you chose an active object pattern for implementing asynchronous clients, and not the proactor pattern as enabled by Asio.
The reason for this is to keep the same interface that is enabled by the synchronous implementation. Note that the client is an active object, but it doesn't create one thread per connection. A new client implementation in the next release will allow for adding a callback function and provide a thread pool to the client so that application-specific handlers can be invoked from that thread pool instead of on the I/O thread dedicated to Boost.Asio's io_service.
If someone wants to open many connections (e.g., a web crawler), one thread per connection probably isn't the way to go.
Yes, but you don't need to create one thread per connection. You can schedule a lot of requests on the same thread, put the responses on a container, and check if each response is ready -- and only process those responses that are ready. The response objects hide the fact that there are futures involved and the API remains in the "synchronous" domain, although the implementation underneath is asynchronous.
This issue may be related to some of my concerns surrounding the current client API, where I am missing the (non-future) async_ methods.
I just implemented as part of this release a 'ready(response)' function that allows you to check whether the response returned by the client in the asynchronous client implementation is ready. That should suffice for the meantime until I get to implement the callback supporting API.
Wouldn't a name like http++ be covering better what the library does?
Not really. This is not just an HTTP client/server, another maintainer is developing an XMPP implementation, and later I'll be developing an ESMTP client that follows the same API that the HTTP implementation does. The process being followed is as prescribed by "generic programming" where we start with a specific implementation and then lift the generic parts out from the specific implementations.
Kind regards,
Thanks very much for the feedback, it is very much appreciated! :) I hope this helps! -- Dean Michael Berris deanberris.com

Seg, 2010-11-15 às 21:40 +0800, Dean Michael Berris escreveu:
On Mon, Nov 15, 2010 at 8:55 PM, Rutger ter Borg <rutger@terborg.net> wrote:
On 11/15/2010 01:04 PM, Dean Michael Berris wrote:
The documentation has also been updated to feature a brand-new reference manual detailing the implementation, caveats, and public API of the HTTP client and server templates.
It looks interesting on first sight.
I'm wondering why you chose an active object pattern for implementing asynchronous clients, and not the proactor pattern as enabled by Asio.
The reason for this is to keep the same interface that is enabled by the synchronous implementation. Note that the client is an active object, but it doesn't create one thread per connection.
A new client implementation in the next release will allow for adding a callback function and provide a thread pool to the client so that application-specific handlers can be invoked from that thread pool instead of on the I/O thread dedicated to Boost.Asio's io_service.
If someone wants to open many connections (e.g., a web crawler), one thread per connection probably isn't the way to go.
Yes, but you don't need to create one thread per connection. You can schedule a lot of requests on the same thread, put the responses on a container, and check if each response is ready -- and only process those responses that are ready.
The response objects hide the fact that there are futures involved and the API remains in the "synchronous" domain, although the implementation underneath is asynchronous.
This issue may be related to some of my concerns surrounding the current client API, where I am missing the (non-future) async_ methods.
I just implemented as part of this release a 'ready(response)' function that allows you to check whether the response returned by the client in the asynchronous client implementation is ready. That should suffice for the meantime until I get to implement the callback supporting API.
Wouldn't a name like http++ be covering better what the library does?
Not really. This is not just an HTTP client/server, another maintainer is developing an XMPP implementation, and later I'll be developing an ESMTP client that follows the same API that the HTTP implementation does.
The process being followed is as prescribed by "generic programming" where we start with a specific implementation and then lift the generic parts out from the specific implementations.
Kind regards,
Thanks very much for the feedback, it is very much appreciated! :)
I hope this helps!
The thread pool is a BAD IDEA. I'm very interested in your library, I would like to use it with other async services I have implemented using Boost Asio. For this a need to specify which io_service your library is going to use and no threads whatsoever. I like the idea of boost Asio, having a single io_service where I can put as many threads to run as I would like (this would usually be a number of threads equal to the number of cores).

From: "Bruno Santos" <bsantos@av.it.pt>
The thread pool is a BAD IDEA. I'm very interested in your library, I would like to use it with other async services I have implemented using Boost Asio. For this a need to specify which io_service your library is going to use and no threads whatsoever. I like the idea of boost Asio, having a single io_service where I can put as many threads to run as I would like (this would usually be a number of threads equal to the number of cores).
I agree completely. I'm writing some thin "middle-ware" networking libraries and the threading (single, pool, etc) is left completely up to the higher layers. The constructors either use an internal io_service, or take an io_service by reference, allowing (if desired) the same io_service to be shared among multiple (other) libraries. There's too many libraries that encapsulate a whole threading subsystem, but one of the beauties of Asio is that it decouples networking from the threading strategy, and I would hope a good, general-use HTTP library would allow the same (in particular, one of the use cases I would expect a good general-use HTTP library to support is embedded systems with small footprints and minimal or no threading - I haven't looked at netlib in a while, so don't know how closely the HTTP portions meet this goal). Cliff

On Tue, Nov 16, 2010 at 1:30 AM, Cliff Green <cliffg@codewrangler.net> wrote:
I agree completely. I'm writing some thin "middle-ware" networking libraries and the threading (single, pool, etc) is left completely up to the higher layers. The constructors either use an internal io_service, or take an io_service by reference, allowing (if desired) the same io_service to be shared among multiple (other) libraries.
Cool! Maybe you'd like to contribute to cpp-netlib some of these thin networking libraries? :D We'd love to get more contributions and feedback as well. The design you describe is the same design that cpp-netlib's HTTP Server template follows. Although it currently owns the io_service it uses (for simplicity of the interface) I think taking an io_service by reference as an additional constructor overload is definitely a good idea -- something I'm going to take as a suggestion from you and will implement in the upcoming 0.8 release. Thanks for the idea! :)
There's too many libraries that encapsulate a whole threading subsystem, but one of the beauties of Asio is that it decouples networking from the threading strategy, and I would hope a good, general-use HTTP library would allow the same
I agree, and this is the same philosophy that the cpp-netlib tries to follow. However, in the interest of a simple interface, some balance has to be struck to offer a nice interface that makes sense and is not cumbersome to use and thus things like an active object implementation makes the library's interface significantly simple yet the implementation efficient and powerful. Currently the asynchronous client implementation is an active object. It's really trivial to change this to be just a normal io_service-playing implementation that doesn't have its own lifetime thread -- at the cost of a simple interface. The server implementation on the other hand values the simplicity of the handler -- any complexity should be necessary and only the complexity that comes with the user's application is the acceptable complexity at this time. The asynchronous server handler interface is already complex, but only because the use cases it's designed for is considerably complex -- where potentially long-running application specific routines will be running concurrently alongside the HTTP serving duties of the library.
(in particular, one of the use cases I would expect a good general-use HTTP library to support is embedded systems with small footprints and minimal or no threading - I haven't looked at netlib in a while, so don't know how closely the HTTP portions meet this goal).
I don't have access nor experience in dealing with embedded systems, but I'd venture a guess that if you can port the whole (or most) of Boost into the platform then cpp-netlib would certainly be usable there. The only worry at this time is the dependence on <iostream> which I've read before (but have not confirmed) causes a lot of bloat for these embedded systems. Binary sizes of debug builds is also an issue with cpp-netlib because of all the template metaprogramming going on. Also, now it requires GCC 4.4 at least to build applications that use it, making it near impossible to support embedded platforms that still use older versions of GCC (2.95, 4.1.x). At any rate, thanks very much Cliff for the feedback, I hope you can take a look at cpp-netlib and hopefully you can share more insights to help shape a hopefully boost-worthy network library implementation. :) Have a good one! -- Dean Michael Berris deanberris.com

From: "Dean Michael Berris" <mikhailberis@gmail.com>
Cool! Maybe you'd like to contribute to cpp-netlib some of these thin networking libraries? :D We'd love to get more contributions and feedback as well.
Maybe - mostly depends on work restrictions (the library is completely generic, though, so there's nothing specifically proprietary about the code, just that it's developed as a work project). Let me run it against my boss (worst case, I could re-develop using the same concepts, but would rather not have to re-write everything).
Currently the asynchronous client implementation is an active object. It's really trivial to change this to be just a normal io_service-playing implementation that doesn't have its own lifetime thread -- at the cost of a simple interface.
It might be possible to have both - I'll have to share some design ideas with you (although for more complex protocols like HTTP it might be difficult). Again, it's been a while since I've looked at netlib, so let me review the latest. In any case, it's nice to be able to package up functionality that a lot of users need, but it's also nice to be able to decouple.
Also, now it requires GCC 4.4 at least to build applications that use it, making it near impossible to support embedded platforms that still use older versions of GCC (2.95, 4.1.x).
GCC 4.4? Really? What is driving that? I can understand not supporting a really ancient GCC such as 2.95, or even 3.x versions, but no support for 4.12 (for example)?
At any rate, thanks very much Cliff for the feedback, I hope you can take a look at cpp-netlib and hopefully you can share more insights to help shape a hopefully boost-worthy network library implementation. :)
I'll be glad to help however I can (mostly just depends on available time, as is usually the case :) ). Cliff

On Tue, Nov 16, 2010 at 3:37 AM, Cliff Green <cliffg@codewrangler.net> wrote:
From: "Dean Michael Berris" <mikhailberis@gmail.com>
Cool! Maybe you'd like to contribute to cpp-netlib some of these thin networking libraries? :D We'd love to get more contributions and feedback as well.
Maybe - mostly depends on work restrictions (the library is completely generic, though, so there's nothing specifically proprietary about the code, just that it's developed as a work project). Let me run it against my boss (worst case, I could re-develop using the same concepts, but would rather not have to re-write everything).
Cool, I'll look forward to see your pull requests! :)
Currently the asynchronous client implementation is an active object. It's really trivial to change this to be just a normal io_service-playing implementation that doesn't have its own lifetime thread -- at the cost of a simple interface.
It might be possible to have both - I'll have to share some design ideas with you (although for more complex protocols like HTTP it might be difficult). Again, it's been a while since I've looked at netlib, so let me review the latest.
Yep, it is possible to have both. I use a tag dispatch mechanism to define the interface and implementation of the basic_client<> -- right now it's just a tag that determines whether a basic_client<> is an active object. Adding a number of tags to support an externally-provided io_service on the client side is entirely possible.
In any case, it's nice to be able to package up functionality that a lot of users need, but it's also nice to be able to decouple.
I agree 100%.
Also, now it requires GCC 4.4 at least to build applications that use it, making it near impossible to support embedded platforms that still use older versions of GCC (2.95, 4.1.x).
GCC 4.4? Really? What is driving that?
That's just the lowest version I've been developing with and am willing to test.
I can understand not supporting a really ancient GCC such as 2.95, or even 3.x versions, but no support for 4.12 (for example)?
4.1.2 might be supported after a few tweaks in a few places. Some users have already reported that 4.1.2 on RHEL/CentOS is not immediately supported. Until I get a chance to debug that, I'm not confident that cpp-netlib can be built with 4.1.2. ;)
At any rate, thanks very much Cliff for the feedback, I hope you can take a look at cpp-netlib and hopefully you can share more insights to help shape a hopefully boost-worthy network library implementation. :)
I'll be glad to help however I can (mostly just depends on available time, as is usually the case :) ).
I understand completely, nonetheless I'll look forward to more feedback not just from you but also from others on the list interested in the development of the library. Have a great one and thanks again! -- Dean Michael Berris deanberris.com

Seg, 2010-11-15 às 09:30 -0800, Cliff Green escreveu:
From: "Bruno Santos" <bsantos@av.it.pt>
The thread pool is a BAD IDEA. I'm very interested in your library, I would like to use it with other async services I have implemented using Boost Asio. For this a need to specify which io_service your library is going to use and no threads whatsoever. I like the idea of boost Asio, having a single io_service where I can put as many threads to run as I would like (this would usually be a number of threads equal to the number of cores).
I agree completely. I'm writing some thin "middle-ware" networking libraries and the threading (single, pool, etc) is left completely up to the higher layers. The constructors either use an internal io_service, or take an io_service by reference, allowing (if desired) the same io_service to be shared among multiple (other) libraries.
There's too many libraries that encapsulate a whole threading subsystem, but one of the beauties of Asio is that it decouples networking from the threading strategy, and I would hope a good, general-use HTTP library would allow the same (in particular, one of the use cases I would expect a good general-use HTTP library to support is embedded systems with small footprints and minimal or no threading - I haven't looked at netlib in a while, so don't know how closely the HTTP portions meet this goal).
Cliff
Which is the whole point, thanks! Cheers

On Tue, Nov 16, 2010 at 1:04 AM, Bruno Santos <bsantos@av.it.pt> wrote:
The thread pool is a BAD IDEA.
Interesting. I've found a group of users that want to have a separate pool of threads for performing heavy lifting tasks from the server side, who have requested explicitly to have a dedicated thread pool for application-specific (potentially long-running synchronous IO bound) tasks so it doesn't hold up the I/O threads that are bound to a single io_service instance. The idea is to have a separate thread pool (with a configurable number of threads) that simply allows for doing application-specific computation. This makes sense on the server side, but the client side I don't see much of a benefit of it -- except for potentially holding up the I/O and handlers queued up for other connections being serviced by the io_service. This made sense especially for things like streaming music over HTTP, where the client will not want the DSP code to hold up the I/O of a potentially large amount of data coming down the wire. Another use case for this would be for a crawler to be able to offload the parsing/processing of content from multiple connections to a pool of threads dedicated to just doing the work, and not holding up all the queued handlers associated with an io_service. That said, the interface can be made to not require a thread pool to be supplied in the constructor of the client, and in which case it will just use the io_service that it owns.
I'm very interested in your library, I would like to use it with other async services I have implemented using Boost Asio. For this a need to specify which io_service your library is going to use and no threads whatsoever.
The way it is done right now, if you look at the examples, is that the HTTP server and HTTP client objects own their own io_service instances. It can be modified to take in an io_service as a parameter by reference, and if that constructor is used it will use that provided io_service instead of creating its own. I suppose this can be done with a pointer to a boost::asio::io_service and a flag that says whether the io_service is owned or provided by reference. It is doable and I'd add that to the things to add for me to support before I release on Friday version 0.8, thanks for the suggestion. :)
I like the idea of boost Asio, having a single io_service where I can put as many threads to run as I would like (this would usually be a number of threads equal to the number of cores).
I've found though that in some cases especially where your service actually does something significant other than constructing a string and then piping that string out (think graph algorithms, SQL queries, map/reduce, etc.) then having an application-specific thread pool actually helps with scalability (not necessarily the performance) of the service to handle more connections and get the data out smoothly through a separate set of threads doing the I/O (or at least running the lightweight I/O event handler functions). The simple use case for the HTTP server already allows you to run the server instance on multiple threads, which really just wraps the Boost.Asio io_stream::run() that gets spread out into however many threads you want. If you look at http://cpp-netlib.github.com/0.8-beta/hello_world_server.html and the note at the bottom, it's basically the same as io_service::run() being invoked on multiple threads. Thanks for the feedback and I hope this helps too. :) -- Dean Michael Berris deanberris.com

From: "Dean Michael Berris" <mikhailberis@gmail.com>
... I suppose this can be done with a pointer to a boost::asio::io_service and a flag that says whether the io_service is owned or provided by reference.
Unless I'm missing something, no flag is needed (warning - uncompiled code, but based on real compilable code): class some_net_lib { public: // use internal io_service some_net_lib() : io_service_ptr(new boost::asio::io_service), io_service_(*io_service_ptr) { } // use io_service provided by user some_net_lib(boost::asio::io_service& ios) : io_service_ptr(), io_service_(ios) { } private: // careful - declaration order of these two is very important std::auto_ptr<boost::asio::ios_service> io_service_ptr; boost::asio::ios_service& io_service_; }; Obviously, all of the internal / implementation code will use io_service_. Cliff

On Tue, Nov 16, 2010 at 3:27 AM, Cliff Green <cliffg@codewrangler.net> wrote:
From: "Dean Michael Berris" <mikhailberis@gmail.com>
... I suppose this can be done with a pointer to a boost::asio::io_service and a flag that says whether the io_service is owned or provided by reference.
Unless I'm missing something, no flag is needed (warning - uncompiled code, but based on real compilable code):
class some_net_lib { public: // use internal io_service some_net_lib() : io_service_ptr(new boost::asio::io_service), io_service_(*io_service_ptr) { } // use io_service provided by user some_net_lib(boost::asio::io_service& ios) : io_service_ptr(), io_service_(ios) { } private: // careful - declaration order of these two is very important std::auto_ptr<boost::asio::ios_service> io_service_ptr; boost::asio::ios_service& io_service_; };
Obviously, all of the internal / implementation code will use io_service_.
Interesting. I was thinking that a unique_ptr would be more appropriate, but as it currently stands using auto_ptr might make sense in this case. It's worth a shot, thanks for the tip Cliff! -- Dean Michael Berris deanberris.com

On Tue, Nov 16, 2010 at 1:49 PM, Dean Michael Berris <mikhailberis@gmail.com> wrote:
On Tue, Nov 16, 2010 at 3:27 AM, Cliff Green <cliffg@codewrangler.net> wrote:
Obviously, all of the internal / implementation code will use io_service_.
Interesting. I was thinking that a unique_ptr would be more appropriate, but as it currently stands using auto_ptr might make sense in this case. It's worth a shot, thanks for the tip Cliff!
And because it's so interesting, I just committed a set of changes to implement this. It's now on the cpp-netlib master and is going to be part of the 0.8 release on Friday. Here's the commit: https://github.com/cpp-netlib/cpp-netlib/commit/ff26d2d2aad5c9bd642fc6d93448... Thanks for the idea again, I hope this helps! :D -- Dean Michael Berris deanberris.com

Dean Michael Berris wrote:
On Tue, Nov 16, 2010 at 1:49 PM, Dean Michael Berris <mikhailberis@gmail.com> wrote:
On Tue, Nov 16, 2010 at 3:27 AM, Cliff Green <cliffg@codewrangler.net> wrote:
Obviously, all of the internal / implementation code will use io_service_.
Interesting. I was thinking that a unique_ptr would be more appropriate, but as it currently stands using auto_ptr might make sense in this case. It's worth a shot, thanks for the tip Cliff!
And because it's so interesting, I just committed a set of changes to implement this. It's now on the cpp-netlib master and is going to be part of the 0.8 release on Friday.
I don't know whether you chose auto_ptr or unique_ptr, but in this case you should choose based upon which is less likely to increase application size since both otherwise suffice. Using unique_ptr for io_service will increase code size unless the client already does the same, but as that is more likely than their using auto_ptr for io_service, at least in the future, using unique_ptr is probably wiser. (If any standard library implementation were to use a void * implementation to share non-dependent code in unique_ptr, the code size could still be reduced if the client uses unique_ptr but not for io_service.) _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On Tue, Nov 16, 2010 at 10:07 PM, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Dean Michael Berris wrote:
And because it's so interesting, I just committed a set of changes to implement this. It's now on the cpp-netlib master and is going to be part of the 0.8 release on Friday.
I don't know whether you chose auto_ptr or unique_ptr, but in this case you should choose based upon which is less likely to increase application size since both otherwise suffice. Using unique_ptr for io_service will increase code size unless the client already does the same, but as that is more likely than their using auto_ptr for io_service, at least in the future, using unique_ptr is probably wiser. (If any standard library implementation were to use a void * implementation to share non-dependent code in unique_ptr, the code size could still be reduced if the client uses unique_ptr but not for io_service.)
My thinking was more guided by what's generally available now. Barring a Boost.Unique_ptr, I'm sticking with std::auto_ptr in the meantime. Once a Boost.Unique_ptr is generally distributed with Boost, I'll switch to that instead. :) So far all tests seem to be unaffacted -- those that matter pass -- and I'm going to be adding more tests to see if the user-provided io_service works as expected. HTH -- Dean Michael Berris deanberris.com
participants (5)
-
Bruno Santos
-
Cliff Green
-
Dean Michael Berris
-
Rutger ter Borg
-
Stewart, Robert