Skip to content

Commit 09cccd8

Browse files
committed
Enhancing Message Concept Documentation
This documentation update discusses the difference between directives, modifiers, and wrappers. It also enhances the definition of the Message Concept in preparation for the possible simplification of the basic_request and basic_response implementations to turn them into POD types similar to the POD types used by the HTTP server implementation.
1 parent a7c6b43 commit 09cccd8

File tree

1 file changed

+119
-13
lines changed

1 file changed

+119
-13
lines changed

libs/network/doc/message.rst

Lines changed: 119 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,16 @@ properties of messages.
4343
:m,n: An instance of **M**.
4444
:S: A string type.
4545
:s,k,v: An instance of **S**.
46+
:O: The source type.
47+
:D: The destination type.
48+
:B: The body type.
49+
:T: The Tag type.
4650

4751
+----------------------------+----------------------+-----------------------------------------+
4852
| Construct | Result | Description |
4953
+============================+======================+=========================================+
54+
| ``typename M::tag`` | T | The nested tag type. |
55+
+----------------------------+----------------------+-----------------------------------------+
5056
| ``M()`` | Instance of M | Default constructible. |
5157
+----------------------------+----------------------+-----------------------------------------+
5258
| ``M(m)`` | Instance of M | Copy constructible. |
@@ -55,33 +61,34 @@ properties of messages.
5561
+----------------------------+----------------------+-----------------------------------------+
5662
| ``swap(m, n);`` | ``void`` | Swappable. |
5763
+----------------------------+----------------------+-----------------------------------------+
58-
| ``source(m);`` | unspecified | Retrieve the source of ``m``. |
64+
| ``source(m);`` | Convertible to O | Retrieve the source of ``m``. |
5965
+----------------------------+----------------------+-----------------------------------------+
60-
| ``destination(m);`` | unspecified | Retrieve the destination of ``m``. |
66+
| ``destination(m);`` | Convertible to D | Retrieve the destination of ``m``. |
6167
+----------------------------+----------------------+-----------------------------------------+
62-
| ``headers(m);`` | unspecified | Get the range of headers of ``m``. The |
63-
| | | result should be convertible to ``H`` |
68+
| ``headers(m);`` | Convertible to H | Retrieve the headers of ``m``. |
6469
+----------------------------+----------------------+-----------------------------------------+
65-
| ``body(m);`` | unspecified | Retrieve the body of ``m``. |
70+
| ``body(m);`` | Convertible to B | Retrieve the body of ``m``. |
6671
+----------------------------+----------------------+-----------------------------------------+
6772
| ``m << source(s);`` | ``M &`` | Set the source of ``m``. |
6873
+----------------------------+----------------------+-----------------------------------------+
69-
| ``source(m,s);`` | ``M &`` | Set the source of ``m``. |
70-
+----------------------------+----------------------+-----------------------------------------+
7174
| ``m << destination(s);`` | ``M &`` | Set the destination of ``m``. |
7275
+----------------------------+----------------------+-----------------------------------------+
73-
| ``destination(m,s);`` | ``M &`` | Set the destination of ``m``. |
74-
+----------------------------+----------------------+-----------------------------------------+
7576
| ``m << header(k, v);`` | ``M &`` | Add a header to ``m``. |
7677
+----------------------------+----------------------+-----------------------------------------+
77-
| ``add_header(m, k, v);`` | ``M &`` | Add a header to ``m``. |
78-
+----------------------------+----------------------+-----------------------------------------+
7978
| ``m << remove_header(k);`` | ``M &`` | Remove a header from ``m``. |
8079
+----------------------------+----------------------+-----------------------------------------+
81-
| ``remove_header(m, k);`` | ``M &`` | Remove a header from ``m``. |
82-
+----------------------------+----------------------+-----------------------------------------+
8380
| ``m << body(s);`` | ``M &`` | Set the body of ``m``. |
8481
+----------------------------+----------------------+-----------------------------------------+
82+
| ``source(m,s);`` | ``void`` | Set the source of ``m``. |
83+
+----------------------------+----------------------+-----------------------------------------+
84+
| ``destination(m,s);`` | ``void`` | Set the destination of ``m``. |
85+
+----------------------------+----------------------+-----------------------------------------+
86+
| ``add_header(m, k, v);`` | ``void`` | Add a header to ``m``. |
87+
+----------------------------+----------------------+-----------------------------------------+
88+
| ``remove_header(m, k);`` | ``void`` | Remove a header from ``m``. |
89+
+----------------------------+----------------------+-----------------------------------------+
90+
| ``clear_headers(m);`` | ``void`` | Clear the headers of ``m``. |
91+
+----------------------------+----------------------+-----------------------------------------+
8592
| ``body(m,s);`` | ``M &`` | Set the body of ``m``. |
8693
+----------------------------+----------------------+-----------------------------------------+
8794

@@ -93,6 +100,105 @@ Concept, a message can be implemented as a POD type and have all
93100
manipulations performed in the directive implementations, as well as
94101
value transformations done in the accessors.
95102

103+
Directives, Modifiers, and Wrappers
104+
```````````````````````````````````
105+
106+
In the Message Concept definition there are three basic constructs that follow a
107+
certain pattern. These patterns are Directives_, Modifiers_, and Wrappers_.
108+
109+
Directives
110+
~~~~~~~~~~
111+
112+
A directive is a function object that is applied to a Message. Directives
113+
encapsulate a set of operations that apply to messages. The general requirement
114+
for a Directive is that it should apply these operations on a message.
115+
116+
A directive may dispatch on the type of the message passed to it at the point of
117+
the function call. Typically, directives are generated using a factory function
118+
that returns the correct directive type.
119+
120+
For a given directive ``foo_directive`` a generator function called ``foo`` is
121+
typically implemented:
122+
123+
.. code-block:: c++
124+
125+
struct foo_directive {
126+
template <class Message>
127+
Message & operator()(Message & m) const {
128+
// do something to m
129+
return m;
130+
}
131+
};
132+
133+
foo_directive const foo() {
134+
return foo_directive();
135+
}
136+
137+
// to apply a directive, we use the << operator
138+
message m;
139+
m << foo();
140+
141+
Modifiers
142+
~~~~~~~~~
143+
144+
A modifier is generally defined as a free function that takes a reference to a
145+
non-const lvalue message as the first parameter, and any number of parameters.
146+
In the concept definition of the Message Concept, a modifier follows the form:
147+
148+
.. code-block:: c++
149+
150+
modifier(message, ...)
151+
152+
Modifiers are meant to imply modifications on a message, which also allows for
153+
easier dispatch based on Argument Dependent Lookup (ADL_) on the type of the
154+
message. Note that Directives_ can be implemented in terms of Modifiers and
155+
vice versa, although that is not required nor specified.
156+
157+
.. _ADL: http://en.wikipedia.org/wiki/Argument-dependent_name_lookup
158+
159+
Wrappers
160+
~~~~~~~~
161+
162+
A Wrapper is basically an implementation detail that ensures that a given
163+
message, when wrapped, can be converted to the associated part of the message. A
164+
wrapper has a type that encapsulates the conversion logic from a message to a
165+
given type.
166+
167+
An example of a Wrapper would be ``source_wrapper`` which would be returned by a
168+
call to the wrapper generator function ``source``. An example implementation of
169+
the ``source_wrapper`` would look like:
170+
171+
.. code-block:: c++
172+
173+
template <class Tag, template <class> class Message>
174+
struct source_wrapper {
175+
Message<Tag> const & m;
176+
explicit source_wrapper(Message<Tag> const & m)
177+
: m(m) {}
178+
typedef typename source<Tag>::type source_type;
179+
operator source_type const & () {
180+
return m.source;
181+
}
182+
operator source_type const () {
183+
return m.source;
184+
}
185+
operator source_type () {
186+
return m.source;
187+
}
188+
};
189+
190+
template <class Tag, template <class> class Message>
191+
source_wrapper<Tag, Message> const
192+
source(Message<Tag> const & message) {
193+
return source_wrapper<Tag, Message>(message);
194+
}
195+
196+
This pattern is similar to an adapter, but the specific notion of wrapping a
197+
data type (in this case, an object of a type that models the Message Concept)
198+
using an intermediary wrapper is what is pertained to by the Wrapper pattern.
199+
In this case, the Wrapper is ``source_wrapper`` while ``source`` is merely a
200+
wrapper generator function.
201+
96202
``basic_message``
97203
`````````````````
98204

0 commit comments

Comments
 (0)