switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Socket / SocketPolicy.hh
1 // $Id:SocketPolicy.hh 218 2007-03-20 14:39:32Z tho $
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief Policy Framework public header
30
31     \idea Creating a new Socket will create 3 new instances (The handle, the body, the policy) of
32         which 2 (argh) (body, policy) live on the heap. This is expensive. We should convert all the
33         policy classes to singletons and assign the same instance to all socket bodies with the same
34         policy. This would reduce the number of heap allocations per socket handle to one (which is
35         already optimized using the pool_alloc_mixin)
36  */
37
38 /** \defgroup policy_group The Policy Framework
39
40     \diaimage SocketPolicy.dia
41
42     \section policy_group_introduction Introduction to the Policy Framework
43
44     The policy framework conceptually implements a list of parallel inheritance hierarchies each
45     covering a specific interface aspect of the socket handle. The socket handle itself only
46     provides minimal functionality. All further functionality is relayed to a policy class, or more
47     precisely, to a group of policy classes, one for each policy axis. The policy axis are
48
49     <dl><dt><em>addressingPolicy</em></dt><dd>configures, whether a socket is addressable and if
50     so, configures the address type</dd>
51
52     <dt><em>framingPolicy</em></dt> <dd>configures the type of framing the socket provides: either
53     no framing providing a simple i/o stream or packet framing</dd>
54
55     <dt><em>communicationPolicy</em></dt><dd>configures,if and how the communication partner is
56     selected</dd>
57
58     <dt><em>readPolicy</em></dt><dd>configures the readability of the socket</dd>
59
60     <dt><em>writePolicy</em></dt><dd>configures the writability of the socket</dd></dl>
61
62     The template senf::SocketPolicy combines these policy axis to form a concrete socket policy. In
63     a concrete policy, each of these policy axis is assigned a value, the policy value. This value
64     is identified by a class type, a policy class. E.g. possible values for <em>framingPolicy</em>
65     are <tt>DatagramFramingPolicy</tt> or <tt>StreamFramingPolicy</tt> which are classes derived
66     from the axis base class <tt>FramingPolicyBase</tt>. This base class also doubles as
67     <tt>UnspecifiedFramingPolicy</tt> (which is just a typedef alias).  If a policy axis is assigned
68     this Unspecified type, the axis is left unspecified, the concrete policy will be incomplete.
69
70     The senf::SocketPolicy template defines the behavior of a socket handle. The socket handle
71     instances do not implement any socket functionality themselves instead deferring the
72     implementation to the policy classes. The SocketHandle interface is therefore \e not implemented
73     using virtual members, all important socket functions can be inlined by the compiler to create
74     highly efficient code.
75
76     A senf::SocketPolicy instance can be incomplete. In this case it does \e not completely specify
77     the socket interface, it leaves some aspects open by assigning the Unspecified value to one or
78     more of the policy axis. A senf::SocketHandle based on such a policy will have a reduced
79     interface: It will only support those members for which the corresponding policies are defined.
80
81     To build a senf::SocketPolicy instance the senf::MakeSocketPolicy helper is provided. This
82     helper template takes any number (it is really limited to 6 Arguments but more arguments don't
83     make sense) of policy classes as it's argument. The MakeSocketPolicy helper will take the
84     arguments in the order they are specified and for each argument will check to which axis the
85     policy class belongs (by checking the base classes of that class) and assign it to the correct
86     policy axis in the senf::SocketPolicy template. If any policy axis are not specified, they are
87     defaulted to their corresponding Unspecified value. This helper frees you to specify the policy
88     classes in any order. An additional feature is, that you may specify a complete policy as a
89     first argument. This policy will then be used to provide default values for unspecified axis.
90
91     Two senf::SocketHandle's with different policies can be \e compatible. If they are, the more
92     specific SocketHandle can be converted (assigned to) the more basic SocketHandle. A SocketHandle
93     is more specific then another SocketHandle if the policy of the former is more specific then
94     that of the latter which means, that for each policy axis separately, the value of that axis of
95     the more specific policy is derived from or the same as the value of that axis in the more basic
96     policy. This is like converting a derived class pointer to a base class pointer, only it happens
97     separately but at the same time for each policy axis:
98
99     \code
100     // This defines an incomplete policy where addressingPolicy and writePolicy
101     // are unspecified
102     typedef senf::MakeSocketPolicy<
103         senf::StreamFramingPolicy,
104         senf::ConnectedCommunicationPolicy,
105         senf::ReadablePolicy
106         >::policy MyReadableSocketPolicy
107
108     typedef senf::ClientSocketHandle<MyReadableSocketPolicy> MyReadableHandle;
109
110     // TCPv4ClientSocketHandle is a socket handle with the policy equivalent to
111     // senf::MakeSocketPolicy<
112     //     INet4AddressingPolicy,
113     //     StreamFramingPolicy,
114     //     ConnectedCommunicationPolicy,
115     //     ReadablePolicy,
116     //     WritablePolicy>::policy
117     senf::TCPv4ClientSocketHandle tcpHandle (...);
118
119     MyReadableHandle myHandle (tcpHandle); // Conversion to more basic socket handle
120     \endcode
121
122     \section policy_group_details The Policy Framework Classes
123
124     In the following discussion, deeper insight into C++ and especially the concepts of template
125     meta-programming are needed. However, this information is only needed if you want to write new
126     policy classes or want to use the policy framework explicitly for your own involved
127     optimizations ... or if you are just plain curious :-)
128
129     In the following discussion we will use the following conventions:
130     \li \e Axis is one or \c AddressingPolicy, \c FramingPolicy, \c CommunicationPolicy, \c
131         ReadPolicy or \c WritePolicy
132     \li \e socketPolicy is any socket policy (that is, an instantiation of the SocketPolicy
133         template)
134     \li \e trait is an any policy class (that is, any class derived from one of the axis base
135         classes)
136
137     Each axis is comprised of a number of classes and templates (all in namespace senf of course):
138
139     <dl><dt>\e Axis \c Base (ex: AddressingPolicyBase)</dt><dd>Baseclass of all policies in this
140     axis</dd>
141
142     <dt>\c Unspecified \e Axis (ex: \ref UnspecifiedAddressingPolicy)</dt> <dd>An alias (typedef)
143     for \e Axis \c Base</dd>
144
145     <dt>\e Axis \c Is < \e socketPolicy, \e trait > (ex: AddressingPolicyIs)</dt> <dd>A template
146     metafunction returning \c boost::true_type, if \e trait (any class derived from \e Axis \c
147     Base) is a compatible policy value of the given \e socketPolicy</dd>
148
149     <dt>\c If \e Axis \c Is < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIs)</dt> <dd>This
150     is a combination of \e Axis \c Is and \c boost::enable_if</dd>
151
152     <dt>\c If \e Axis \c IsNot < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIsNot)</dt>
153     <dd>The inverse of above</dd> </dl>
154
155     These classes form the basis of the policy framework. To bind the policy axis together, there
156     are some more classes and templates.
157
158     <dl><dt>\c class \c SocketPolicyBase</dt> <dd>This class is the base class of the SocketPolicy
159     template. It is used to validate, that a class is really a SocketPolicy (by checking, that it
160     derives from SocketPolicyBase. This is simpler than checking the template directly).</dd>
161
162     <dt>\c template \c SocketPolicy < \e addressingPolicy, \e framingPolicy, \e communicationPolicy,
163     \e readPolicy, \e writePolicy ></dt> <dd>This is the central SocketPolicy
164     template. It combines a complete set of policy classes, one for each axis.</dd>
165
166     <dt>\c template \c MakeSocketPolicy < \e args ></dt> <dd>\c MakeSocketPolicy is a template
167     metafunction which simplifies building SocketPolicy instantiations. It takes any number (ok, up
168     to a maximum of 6) of policy classes as an argument (in any order). It will sort these arguments
169     into the SocketPolicy template arguments. If for some axis no class is specified, it's slot will
170     be filled with \c Unspecified \e Axis. Additionally, the first Argument may optionally be an
171     arbitrary SocketPolicy. It will provide default values for unspecified axis</dd>
172
173     <dt>\c template \c SocketPolicyIsBaseOf < \e base, \e derived ></dt> <dd>This template
174     metafunction will check, whether the socket policy \e derived is convertible to \e base. This
175     means, that for each axis, the corresponding policy class in \e derived must be derived or be
176     the same as the one on \e base.</dd> </dl>
177
178     \implementation All these classes are created automatically. The \c SENF_SOCKET_POLICIES macro
179     is a Boost.Preprocessor style sequence listing all policy axis. The Boost.Preprocessor library
180     is then used to generate the respective classes.
181
182     \section policy_implement Implementing Policy Classes
183
184     To define a new policy class, derive from the corresponding base class for your policy axes. The
185     only policy axis which might possibly need to be extended is the addressing policy
186     (AddressingPolicyBase). See the Documentation of these classes for more information on which
187     members can be implemented.
188
189     All members you define must be static. For any of the policy classes, you must only define those
190     members which are supported by your implementation. If you leave out a member you automatically
191     disable the corresponding functionality in the ClientSocketHandle/ServerSocketHandle interface.
192
193     The member prototypes given in the base class documentation only specify the call signature not
194     the way, the member must be defined (FileHandle really is not a FileHandle but an arbitrary
195     SocketHandle).
196
197     If the existence of a member depends on other policies, you should use the
198     <code>If</code><i>SomePolicy</i><code>Is</code> and
199     <code>If</code><i>SomePolicy</i><code>IsNot</code> templates to dynamically enable/disable the
200     member depending on some other policy:
201
202     \code
203       struct ExampleAddressingPolicy
204       {
205           template <class SPolicy>
206           void connect(senf::SocketHandle<SPolicy> handle, Address & addr,
207                        typename senf::IfCommmunicationPolicyIs<
208                            SPolicy, senf::ConnectedCommunicationPolicy>::type * = 0);
209       };
210     \endcode
211
212     The \c connect member in this example will only be enabled, it the communication policy of the
213     socket handle is ConnectedCommunicationPolicy (or a derived type). See <a
214     href="http://www.boost.org/doc/libs/release/libs/utility/enable_if.html">Boost.Enable_If</a>
215     for a discussion of the third argument (\c senf::ConnectedCommunicationPolicyIs is based on
216     the \c boost::enable_if template).
217
218     \see \ref extend_policy \n
219          <a href="http://www.boost.org/doc/libs/release/libs/utility/enable_if.html">The Boost enable_if utility</a> \n
220          <a href="http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html">The Boost.MPL library</a> \n
221          <a href="http://www.boost.org/doc/libs/release/libs/preprocessor/doc/index.html">The Boost.Preprocessor library</a>
222
223     \idea We could combine all the \e Axis \c Is templates into a single template. Since the \e
224     trait argument will automatically specify the axis to be used, it is not necessary to specify
225     that axis in the template functor's name. We could even combine this with \c
226     SocketPolicyIsBaseOf.
227  */
228
229 /** \defgroup policy_impl_group Policy Implementation classes
230     \ingroup policy_group
231
232     Here you will find all policy classes. Also included are some supporting classes which are used
233     as base classes to build other policy classes.
234  */
235
236 #ifndef HH_SENF_Socket_SocketPolicy_
237 #define HH_SENF_Socket_SocketPolicy_ 1
238
239 // Custom includes
240
241 //#include "SocketPolicy.mpp"
242 //-/////////////////////////////////////////////////////////////////////////////////////////////////
243
244 namespace senf {
245
246     /// \addtogroup policy_group
247     //\{
248
249     // This may be adapted to change the supported policies (however, ClientSocketHandle and
250     // ServerSocketHandle will probably have to be adjusted accordingly)
251
252     /** \brief List all policy axis
253
254         \internal
255
256         This define symbol is used to configure the policy axis. The base class for each of these
257         axis must be defined explicitly (e.g. AddressingPolicyBase). The implementation files will
258         then automatically generate all the other classes from this list.
259
260         \see policy_group
261      */
262 #   define SENF_SOCKET_POLICIES                 \
263         (AddressingPolicy)                      \
264         (FramingPolicy)                         \
265         (CommunicationPolicy)                   \
266         (ReadPolicy)                            \
267         (WritePolicy)
268
269     // Wer define these classes explicitly (and not with some macro
270     // magic) because
271     // a) AddressingPolicyBase is different from all the others
272     // b) We want to document each one explicitly
273
274     /** \brief Policy defining socket addressing
275
276         AddressingPolicyBase is the baseclass of all addressing policy classes. When defining a new
277         addressing policy, the following members can be defined. All methods must be static.
278
279         <table class="senf">
280         <tr><td>typedef</td> <td><tt>Address</tt></td>                                   <td>Address type</td></tr>
281         <tr><td>method</td>  <td><tt>void local(FileHandle, Address &)</tt></td>         <td>Get local socket address</td></tr>
282         <tr><td>method</td>  <td><tt>void peer(FileHandle, Address &)</tt></td>          <td>Get remote socket address</td></tr>
283         <tr><td>method</td>  <td><tt>void bind(FileHandle, Address const &)</tt></td>    <td>Bind socket to local address</td></tr>
284         <tr><td>method</tr>  <td><tt>void connect(FileHandle, Address const &)</tt></td> <td>Connect to remote address</td></tr>
285         </table>
286
287         \see policy_group
288      */
289     struct AddressingPolicyBase
290     {
291         virtual ~AddressingPolicyBase();
292
293         class Address { Address(); };
294     };
295
296     /** \brief Policy defining the framing format
297
298         This policy does not define any operations since it does have no influence on any method
299         signature. It does however affect the semantics of the \c read() and \c write() operations.
300
301         \note This policy axis probably only has two sensible states: StreamFramingPolicy and
302         DatagramFramingPolicy.
303
304         \see policy_group
305      */
306     struct FramingPolicyBase
307     {
308         virtual ~FramingPolicyBase();
309     };
310
311     /** \brief Policy defining, how peers are selected
312
313         The CommunicationPolicy may define two members:
314
315         <table class="senf">
316         <tr><td>method</td> <td><tt>void listen(FileHandle, unsigned backlog)</tt></td> <td>Switch socket into listening state</td></tr>
317         <tr><td>method</td> <td><tt>int accept(FileHandle, Address &)</tt></td>         <td>Accept a new connection</td></tr>
318         <tr><td>method</td> <td><tt>int accept(FileHandle)</tt></td>                    <td>Accept a new connection</td></tr>
319         </table>
320
321         The \c listen member is straight forward. The \c accept() member must return a new file
322         descriptor (which will be used to create a new SocketHandle of the correct
323         type).
324
325         \note This Policy only has two meaningful states: ConnectedCommunicationPolicy and
326         UnconnectedCommunicationPolicy. It is probably not sensible to define a new
327         CommunicationPolicy type.
328
329         \see policy_group
330      */
331     struct CommunicationPolicyBase
332     {
333         virtual ~CommunicationPolicyBase();
334     };
335
336     /** \brief Policy defining the readability
337
338         The ReadPolicy defines, whether the socket is readable. It may define two members:
339
340         <table class="senf">
341         <tr><td>method</td> <td><tt>unsigned read(FileHandle, char * buffer, unsigned size)</tt></td>                <td>read data from socket</td></tr>
342         <tr><td>method</td> <td><tt>unsigned readfrom(FileHandle, char * buffer, unsigned size, Address &)</tt></td> <td>read data from unconnected socket</td></tr>
343         </table>
344
345         The second member should only be enabled if the communication policy is
346         UnconnectedCommunicationPolicy (otherwise it does not make sense since the communication partner
347         is fixed) (see AddressingPolicyBase on how to do this).
348
349         \note This Policy only has two meaningful states: ReadablePolicy and NotReadablePolicy. It
350         probably does not make sense to define new read policy types.
351
352         \see policy_group
353      */
354     struct ReadPolicyBase
355     {
356         virtual ~ReadPolicyBase();
357     };
358
359     /** \brief Policy defining the writability
360
361         The WritePolicy defines, whether the socket is writable. It may define two members:
362
363         <table class="senf">
364         <tr><td>method</td> <td><tt>unsigned write(FileHandle, char * buffer, unsigned size)</tt></td>              <td>read data from socket</td></tr>
365         <tr><td>method</td> <td><tt>unsigned writeto(FileHandle, char * buffer, unsigned size, Address &)</tt></td> <td>read data from unconnected socket</td></tr>
366         </table>
367
368         The second member should only be enabled if the communication policy is
369         UnconnectedCommunicationPolicy (otherwise it does not make sense since the communication partner
370         is fixed) (see AddressingPolicyBase on how to do this).
371
372         \note This Policy only has two meaningful states: WritablePolicy and NotWritablePolicy. It
373         probably does not make sense to define new write policy types.
374
375         \see policy_group
376      */
377     struct WritePolicyBase
378     {
379         virtual ~WritePolicyBase();
380     };
381
382     // The implementation file will for each Policy declared above
383     // define the following (SomePolicy is one of the above):
384     //
385     // struct SomePolicyBase;
386     // typedef UndefinedSomePolicy;
387     // template SomePolicyIs< SocketPolicy, Axis >
388     // template IfSomePolicyIs< SocketPolicy, Axis >
389     // template IfSomePolicyIsNot< SocketPolicy, Axis >
390     //
391     // Additionally the following are defined:
392     //
393     // class SocketPolicyBase
394     // template SocketPolicy< ..policies.. >
395     // template MakeSocketPolicy< ..args.. >
396     // template SocketPolicyIsBaseOf< Base, Derived >
397
398 #   ifdef DOXYGEN
399
400     // The following stub definitions are only visible to doxygen
401
402     /** \brief Alias of AddressingPolicyBase for better readability
403         \see \ref policy_group
404      */
405     typedef AddressingPolicyBase UnspecifiedAddressingPolicy;
406
407     /** \brief Check single policy axis
408
409         This template is an example of the \e Axis \c Is family of template metafunctions. It will
410         check, whether \c Trait is a valid compatible Policy class of \c SocketPolicy. \c Trait must
411         be derived from AddressingPolicyBase (respectively \c Policy \c Base).
412
413         \see \ref policy_group
414      */
415     template <class SocketPolicy, class Trait>
416     struct AddressingPolicyIs
417     {};
418
419     /** \brief Enable template overload depending on policy value
420
421         This template is an example of the \c If \e Axis \c Is family of templates. It is used like
422         <a href="http://www.boost.org/doc/libs/release/libs/utility/enable_if.html">Boost.enable_if</a>
423         to enable a templated overload only, if the AddressingPolicy of \e Axis is compatible with
424         \c Trait (that is the AddressingPolicy of \c Policy is derived from \c Trait).
425
426         \see policy_group
427      */
428     template <class SocketPolicy, class Trait>
429     struct IfAddressingPolicyIs
430     {};
431
432     /** \brief Inversion of \c IfAddressingPolicyIs
433         \see policy_group
434      */
435     template <class SocketPolicy, class Trait>
436     struct IfAddressingPolicyIsNot
437     {};
438
439     /** \brief Baseclass of all SocketPolicies
440
441         \internal
442
443         This class provides the baseclass of all socket policies (bundles). It serves two purposes:
444         \li It allows us to easily identify a socket policy bundle by checking a classes baseclass.
445         \li It provides an abstract (virtual) interface to access the policy axes
446
447         \see policy_group
448      */
449     struct SocketPolicyBase
450     {
451         /** \brief Polymorphic access to policy axes
452
453             This is an example of a policy axes accessor. It returns a reference to the policy axes
454             used by the concrete protocol bundle. This reference can then be checked using RTTI
455             information.
456          */
457         AddressingPolicyBase const & theAddressingPolicy() const = 0;
458
459         virtual ~SocketPolicyBase();
460     };
461
462     /** \brief Collection of policy classes
463
464         The SocketPolicy template defines the complete Policy used by the socket library. It
465         contains one policy class for each policy axis. This template takes one policy from each
466         axis as it's template arguments (this example implementation only has AddressingPolicy as an
467         argument).
468
469         A SocketPolicy can be complete or incomplete. An incomplete SocketPolicy will have at least
470         one axis set to \c Undefined \e Axis (or a generic derived class which is used to group some
471         other policies but does not (completely) define the policy behavior). A complete
472         SocketPolicy will have a concrete definition of the desired behavior for each policy axis.
473
474         \see policy_group
475      */
476     template < class AddressingPolicy >
477     struct SocketPolicy
478     {
479         /** \brief Check dynamic policy compatibility
480
481             This check will validate, that a socket with \a other as it's policy is convertible to a
482             socket with the current SocketPolicy as it's policy. This is true, if for each policy
483             axis, the policy class of that axis as defined in the \a other policy is convertible to
484             the policy class of that same axis in the current SocketPolicy instance (as is defined
485             by the template arguments). This again is true, if the \a other policy class is derived
486             from (or is the same as) the policy class taken from the current SocketPolicy instance.
487
488             In other words, this call checks, that the current SocketPolicy (as defined via the
489             template arguments) is more generic than the \a other socket policy.
490
491             \param[in] other SocketPolicy to check
492             \throws std::bad_cast if \a other is not a compatible policy
493          */
494         static void checkBaseOf(SocketPolicyBase const & other);
495     };
496
497     /** \brief Metafunction to create SocketPolicy
498
499         This template metafunction simplifies the creation of a SocketPolicy instantiation. It takes
500         any number (that is up to 6) of Policy classes as arguments in any Order. It will create a
501         SocketPolicy from these policy classes. Any axis not specified will be left as \c
502         Unspecified \e Axis.
503
504         \see policy_group
505      */
506     template <class Arg1, class Arg2, class ArgN>
507     struct MakeSocketPolicy
508     {};
509
510     /** \brief Check policy compatibility
511
512         This template metafunction checks, whether the SocketPolicy \c Derived is more specialized
513         than \c Base (and therefore a SocketHandle with policy \c Derived is convertible to a
514         SocketHandle with policy \c Base).
515
516         The metafunction will return true (that is inherits from \c boost::true_type, see the <a
517         href="http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html">Boost.MPL</a> library documentation for
518         more information) if each policy class in \c Base is a baseclass of (or the same as) the
519         corresponding policy class in \c Derived.
520
521         \see policy_group
522      */
523     template <class Base, class Derived>
524     struct SocketPolicyIsBaseOf
525     {};
526
527 #   endif
528
529     //\}
530 }
531
532 //-/////////////////////////////////////////////////////////////////////////////////////////////////
533 #include "SocketPolicy.ih"
534 //#include "SocketPolicy.cci"
535 #include "SocketPolicy.ct"
536 //#include "SocketPolicy.cti"
537 #endif
538
539 \f
540 // Local Variables:
541 // mode: c++
542 // fill-column: 100
543 // c-file-style: "senf"
544 // indent-tabs-mode: nil
545 // ispell-local-dictionary: "american"
546 // compile-command: "scons -u test"
547 // comment-column: 40
548 // End: