4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
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
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.
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.
19 // The Original Code is Fraunhofer FOKUS code.
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.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief PacketRegistry public header */
31 #ifndef HH_SENF_Packets_PacketRegistry_
32 #define HH_SENF_Packets_PacketRegistry_ 1
35 #include <boost/optional.hpp>
36 #include <boost/preprocessor/cat.hpp>
37 #include <senf/Utils/Exception.hh>
38 #include <senf/Utils/singleton.hh>
41 #include "PacketRegistry.ih"
42 //#include "PacketRegistry.mpp"
43 //-/////////////////////////////////////////////////////////////////////////////////////////////////
47 /** \brief %Packet registration facility
49 The %PacketRegistry provides a generic facility to associate an arbitrary key with
50 Packets. Example keys are Ethertype or IP protocols.
52 Every %PacketRegistry is identified by a type tag:
55 typedef some_key_type key_t;
58 The key type can be an arbitrary value type. The %PacketRegistry for this Tag can then be
59 accessed using <code>senf::PacketRegistry<SomeTag>::</code>.
61 The %PacketRegistry class has only static members and provides access to the packet
62 registry. It allows two-way lookup either by key or by packet type.
65 senf::Packet::factory_t factory (senf::PacketRegistry<SomeTag>::lookup(some_key).factory());
66 SomeTag::key_t key = PacketRegistry<SomeTag>::key<SomePacket>();
69 Packets can be registered either dynamically or statically. Dynamic:
71 // dynamic registration
72 senf::PacketRegistry<SomeTag>::registerPacket<SomePacket>(key_of_somePacket);
74 // static registration. 'registerSomePacket' is an arbitrary symbol name
75 SENF_PACKET_REGISTRY_REGISTER( SomeTag, key_of_somePacket, SomePacket );
78 SENF_PACKET_REGISTRY_REGISTER will declare an anonymous global variable which will ensure,
79 the packet is registered automatically during global initialization (as long as the object
80 file is linked into the final executable).
82 \section packet_registry_priority Multiple registration for a single key
84 Ordinarily, the PacketRegistry will reject registering the same key twice. However, the
85 registry supports an additional priority parameter when registering a packet. You may
86 register multiple Packets with the same \a key as long as the \a priority is unique. The
87 registration with the highest \a priority value will take precedence on key lookup.
89 \ingroup packet_module
93 : private senf::singleton< PacketRegistry<Tag> >
96 typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::iterator iterator;
97 typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::Entry Entry;
99 /** \brief Statically register a packet type in a PacketRegistry
101 This class is normally used via SENF_PACKET_REGISTRY_REGISTER. To use this class
102 directly, define a symbol in the following way:
105 senf::PacketRegistry<Tag>::ScopedRegistrationProxy<PacketType>
106 registerPacketType (key, optional_priority);
109 Here \a Tag is the type tag of the registry to register the packet in, \a
110 PacketType is the packet to register (this is the ConcretePacket of that packet) and \a
111 key is the key of type \c Tag::key_t under which the packet is to be registered. \a
112 registerPacketType is an arbitrary name for the global symbol.
114 The packet will be registered in the constructor and will be unregistered when the scope
115 of \c registerPacketType ends.
117 template <class PacketType>
118 struct ScopedRegistrationProxy
120 ScopedRegistrationProxy(typename Tag::key_t key, int priority=0);
121 ~ScopedRegistrationProxy();
124 /** \brief Register new packet type
126 Register \a PacketType in the packet registry \a Tag under the given \a key.
129 The given pair \a key, \a priority must be unique and not be assigned to any other
130 packet class in this registry. The %Packet must not already be registered in the
133 \tparam PacketType ConcretePacket instantiation of packet to register
134 \param[in] key The key of the packet
135 \param [in] priority Optional priority
137 template <class PacketType>
138 static void registerPacket(typename Tag::key_t key, int priority=0);
140 /** \brief Unregister packet by packet type
142 Removes \a PacketType from the packet registry. If the packet type is not registered,
145 \tparam PacketType ConcretePacket instantiation of packet to remove from registry
147 template <class PacketType>
148 static void unregisterPacket();
150 /** \brief Unregister packet by key
152 Removes the packet registration for \a key (and \a priority) from the registry. If no
153 packet is registered with the given pair \a key, \a priority, this operation is a
156 \param[in] key Key to remove from the registry
157 \param[in] priority Optional priority of the key to remove
159 static void unregisterPacket(typename Tag::key_t key, int priority=0);
161 /** \brief Find key of a packet type
163 Return the key of \a PacketType as registered in the \a Tag registry
165 \tparam PacketType packet of which the key is requested
166 \returns key of the packet
167 \throws PacketTypeNotRegistered if the packet type is not found in the registry.
169 template <class PacketType>
170 static typename Tag::key_t key();
172 /** \brief Find key of a packet type
174 Return the key of \a PacketType as registered in the \a Tag registry
176 \tparam PacketType packet of which the key is requested
177 \returns key of the packet wrapped in a <a
178 href="http://www.boost.org/doc/libs/release/libs/optional/index.html">boost::optional</a> or
179 an unbound optional, if the key is not found.
181 template <class PacketType>
182 static typename boost::optional<typename Tag::key_t> key(NoThrow_t);
184 /** \brief Find key of a packet
186 Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
188 \param packet The packet of which the key is requested
189 \returns key of the packet
190 \throws PacketTypeNotRegistered if the packet type is not found in the registry.
192 static typename Tag::key_t key(Packet const & packet);
194 /** \brief Find key of a packet
196 Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
198 \param packet The packet of which the key is requested
199 \returns key of the packet wrapped in a <a
200 href="http://www.boost.org/doc/libs/release/libs/optional/index.html">boost::optional</a> or
201 an unbound optional, if the key is not found.
203 static typename boost::optional<typename Tag::key_t> key(Packet const & packet, NoThrow_t);
205 /** \brief Lookup a packet by it's key
207 \throws PacketTypeNotRegistered if the \a key is not found in the registry
208 \return %Packet entry for given \a key
210 static Entry const & lookup(typename Tag::key_t key);
212 /** \brief Lookup a packet by it's key
213 \return Pointer to packet entry for given \a key or 0, if the key is not found in the
216 static Entry const * lookup(typename Tag::key_t key, NoThrow_t);
218 /** \brief Beginning iterator to list of registered entries
220 static iterator begin();
222 /** \brief End iterator to list of registered entries
224 static iterator end();
227 using singleton<PacketRegistry>::instance;
228 using singleton<PacketRegistry>::alive;
232 typedef detail::PacketRegistryImpl<typename Tag::key_t> Registry;
233 static Registry & registry();
236 friend class senf::singleton< PacketRegistry >;
239 /** \brief Statically add an entry to a packet registry
241 This macro will declare an anonymous global variable in such a way, that constructing this
242 variable will add a registration to the given packet registry.
244 \ingroup packet_module
247 # define SENF_PACKET_REGISTRY_REGISTER( registry, value, type ) \
249 senf::PacketRegistry< registry >::ScopedRegistrationProxy< type > \
250 BOOST_PP_CAT(packetRegistration_, __LINE__) ( value ); \
253 /** \brief Statically add an entry to a packet registry with explicit priority
255 This macro will declare an anonymous global variable in such a way, that constructing this
256 variable will add a registration to the given packet registry.
258 \ingroup packet_module
261 # define SENF_PACKET_REGISTRY_REGISTER_PRIORITY( registry, value, priority, type ) \
263 senf::PacketRegistry< registry >::ScopedRegistrationProxy< type > \
264 BOOST_PP_CAT(packetRegistration_, __LINE__) ( value, priority ); \
267 /** \brief Dump all packet registries
269 This command will dump all packet registries to the given stream. This is to help debugging
270 registration problems.
272 void dumpPacketRegistries(std::ostream & os);
274 /** \brief Entry not found in registry
276 This exception is signaled whenever a throwing lookup operation fails.
278 struct PacketTypeNotRegisteredException : public senf::Exception
279 { PacketTypeNotRegisteredException() : senf::Exception("packet type not registered") {} };
283 //-/////////////////////////////////////////////////////////////////////////////////////////////////
285 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketRegistry_i_)
286 #define HH_SENF_Packets_PacketRegistry_i_
287 #include "PacketRegistry.cci"
288 #include "PacketRegistry.ct"
289 #include "PacketRegistry.cti"
296 // c-file-style: "senf"
297 // indent-tabs-mode: nil
298 // ispell-local-dictionary: "american"
299 // compile-command: "scons -u test"
300 // comment-column: 40