From: Dean M. B. <mik...@gm...> - 2010-10-19 14:04:28
|
Hi Everyone, I just wanted to shed some light into the new tag system that came out in cpp-netlib 0.7 and will be enhanced as 0.8-devel prorgesses. Earlier I did a quick refactor and move out of the HTTP specific tags from boost/network/tags.hpp into boost/network/protocol/http/tags.hpp -- this change (http://goo.gl/O0zF) is a singular change that affects a lot of files and applies cleanly to 0.7 as well. The new tag system relies on Boost.MPL to aid with what I'd like to call "Tag Calculus". Let me elaborate on this a little. First, tags are now defined using an inheritance structure. There are what I'd like to call "root tags" from which all meaningful tags derive their meaning from. To model this inheritance structure we use Boost.MPL vectors to determine which root tags a given tag derives from. An example from the library is the `http_default_8bit_udp_resolve` tag. The ingredients for this tag are as follows: typedef mpl::vector<http, default_string, simple, udp, sync> http_default_8bit_udp_resolve_tags; BOOST_NETWORK_DEFINE_TAG(http_default_8bit_udp_resolve); The macro BOOST_NETWORK_DEFINE_TAG does two things: 1. It creates a typedef to the inheritance structure as `http_default_8bit_udp_resolve`. This uses Boost.MPL's inherit_linearly algorithm and the default inheritance metafunction that comes with Boost.MPL. 2. It also specializes the `components` metafunction that maps the tag back to the root tags from which it derives. This means a call to: http::tags::components<http_default_8bit_udp_resolve>::type Will yield the mpl::vector that is `http_default_8bit_udp_resolve_tags`. This is handy especially if you want to make decisions at compile time based on the composition of a tag -- for example, an asynchronous keepalive connection implementation may be different from an asynchronous simple connection in the HTTP sense. There are also some support metafunctions which allows for easy querying of a given tag. Metafunctions like `is_sync` or `is_async` would normally be used as part of an mpl::if_ to choose which implementation/type should be yielded by a metafunction that is parametric on whether a tag derives from synchronous or asynchronous. If you notice that the compile times are growing long, this may be explained by the tag calculus that's now in place in cpp-netlib. In the coming couple of weeks I look to being able to address the compile-time issue with precompiled headers and other tricks to make cpp-netlib not that much of a pain to use as far as compile time goes, but there's definitely room for optimization there. Also, the tag calculus may be greatly simplified if we kept the tags as mpl::vectors instead of using the inheritance structure, although tag dispatching based on the root tags might be affected. At this time we don't use tag dispatch based on root tags (yet) but it's something that's worth expanding and exploring as development goes on. Another reason for this increase in compile times is the introduction of the Concept Checks which cause a lot more template instantiations than if concept checking was turned off. I'm not sure if there's a way to selectively turn off concept checking but I'm not opposed to introducing a preprocessor macro for that. That's it for now guys tomorrow I'll be working on the connection<> interface and the thread pool concept/implementation to be supported by the server implementation. Let me know if you need any more clarification on the tag system before I proceed to changing it yet again. :D Have a good one everyone and I hope this helps! -- Dean Michael Berris deanberris.com |