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
|