4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief PacketRegistry public header */
26 #ifndef HH_SENF_Packets_PacketRegistry_
27 #define HH_SENF_Packets_PacketRegistry_ 1
31 #include <boost/utility.hpp> // for boost::noncopyable
32 #include <boost/optional.hpp>
33 #include <boost/preprocessor/cat.hpp>
34 #include <senf/Utils/Exception.hh>
37 #include "PacketRegistry.ih"
38 //#include "PacketRegistry.mpp"
39 ///////////////////////////////hh.p////////////////////////////////////////
43 /** \brief %Packet registration facility
45 The %PacketRegistry provides a generic facility to associate an arbitrary key with
46 Packets. Example keys are Ethertype or IP protocols.
48 Every %PacketRegistry is identified by a type tag:
51 typedef some_key_type key_t;
54 The key type can be an arbitrary value type. The %PacketRegistry for this Tag can then be
55 accessed using <code>senf::PacketRegistry<SomeTag>::</code>.
57 The %PacketRegistry class has only static members and provides access to the packet
58 registry. It allows two-way lookup either by key or by packet type.
61 senf::Packet::factory_t factory (senf::PacketRegistry<SomeTag>::lookup(some_key).factory());
62 SomeTag::key_t key = PacketRegistry<SomeTag>::key<SomePacket>();
65 Packets can be registered either dynamically or statically. Dynamic:
67 // dynamic registration
68 senf::PacketRegistry<SomeTag>::registerPacket<SomePacket>(key_of_somePacket);
70 // static registration. 'registerSomePacket' is an arbitrary symbol name
71 SENF_PACKET_REGISTRY_REGISTER( SomeTag, key_of_somePacket, SomePacket );
74 SENF_PACKET_REGISTRY_REGISTER will declare an anonymous global variable which will ensure,
75 the packet is registered automatically during global initialization (as long as the object
76 file is linked into the final executable).
78 \section packet_registry_priority Multiple registration for a single key
80 Ordinarily, the PacketRegistry will reject registering the same key twice. However, the
81 registry supports an additional priority parameter when registering a packet. You may
82 register multiple Packets with the same \a key as long as the \a priority is unique. The
83 registration with the highest \a priority value will take precedence on key lookup.
85 \ingroup packet_module
91 typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::iterator iterator;
92 typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::Entry Entry;
94 /** \brief Statically register a packet type in a PacketRegistry
96 This class is normally used via SENF_PACKET_REGISTRY_REGISTER. To use this class
97 directly, define a symbol in the following way:
100 senf::PacketRegistry<Tag>::RegistrationProxy<PacketType>
101 registerPacketType (key, optional_priority);
104 Here \a Tag is the type tag of the registry to register the packet in, \a
105 PacketType is the packet to register (this is the ConcretePacket of that packet) and \a
106 key is the key of type \c Tag::key_t under which the packet is to be registered. \a
107 registerPacketType is an arbitrary name for the global symbol.
109 The packet will be registered in the constructor and will be unregistered when the scope
110 of \c registerPacketType ends.
112 template <class PacketType>
113 struct RegistrationProxy
115 RegistrationProxy(typename Tag::key_t key, int priority=0);
116 ~RegistrationProxy();
119 /** \brief Register new packet type
121 Register \a PacketType in the packet registry \a Tag under the given \a key.
124 The given pair \a key, \a priority must be unique and not be assigned to any other
125 packet class in this registry. The %Packet must not already be registered in the
128 \tparam PacketType ConcretePacket instantiation of packet to register
129 \param[in] key The key of the packet
130 \param [in] priority Optional priority
132 template <class PacketType>
133 static void registerPacket(typename Tag::key_t key, int priority=0);
135 /** \brief Unregister packet by packet type
137 Removes \a PacketType from the packet registry. If the packet type is not registered,
140 \tparam PacketType ConcretePacket instantiation of packet to remove from registry
142 template <class PacketType>
143 static void unregisterPacket();
145 /** \brief Unregister packet by key
147 Removes the packet registration for \a key (and \a priority) from the registry. If no
148 packet is registered with the given pair \a key, \a priority, this operation is a
151 \param[in] key Key to remove from the registry
152 \param[in] priority Optional priority of the key to remove
154 static void unregisterPacket(typename Tag::key_t key, int priority=0);
156 /** \brief Find key of a packet type
158 Return the key of \a PacketType as registered in the \a Tag registry
160 \tparam PacketType packet of which the key is requested
161 \returns key of the packet
162 \throws PacketTypeNotRegistered if the packet type is not found in the registry.
164 template <class PacketType>
165 static typename Tag::key_t key();
167 /** \brief Find key of a packet type
169 Return the key of \a PacketType as registered in the \a Tag registry
171 \tparam PacketType packet of which the key is requested
172 \returns key of the packet wrapped in a <a
173 href="http://www.boost.org/libs/optional/doc/optional.html">boost::optional</a> or
174 an unbound optional, if the key is not found.
176 template <class PacketType>
177 static typename boost::optional<typename Tag::key_t> key(NoThrow_t);
179 /** \brief Find key of a packet
181 Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
183 \param packet The packet of which the key is requested
184 \returns key of the packet
185 \throws PacketTypeNotRegistered if the packet type is not found in the registry.
187 static typename Tag::key_t key(Packet const & packet);
189 /** \brief Find key of a packet
191 Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
193 \param packet The packet of which the key is requested
194 \returns key of the packet wrapped in a <a
195 href="http://www.boost.org/libs/optional/doc/optional.html">boost::optional</a> or
196 an unbound optional, if the key is not found.
198 static typename boost::optional<typename Tag::key_t> key(Packet const & packet, NoThrow_t);
200 /** \brief Lookup a packet by it's key
202 \throws PacketTypeNotRegistered if the \a key is not found in the registry
203 \return %Packet entry for given \a key
205 static Entry const & lookup(typename Tag::key_t key);
207 /** \brief Lookup a packet by it's key
208 \return Pointer to packet entry for given \a key or 0, if the key is not found in the
211 static Entry const * lookup(typename Tag::key_t key, NoThrow_t);
213 /** \brief Beginning iterator to list of registered entries
215 static iterator begin();
217 /** \brief End iterator to list of registered entries
219 static iterator end();
222 typedef detail::PacketRegistryImpl<typename Tag::key_t> Registry;
223 static Registry & registry();
226 /** \brief Statically add an entry to a packet registry
228 This macro will declare an anonymous global variable in such a way, that constructing this
229 variable will add a registration to the given packet registry.
231 \ingroup packet_module
234 # define SENF_PACKET_REGISTRY_REGISTER( registry, value, type ) \
236 senf::PacketRegistry< registry >::RegistrationProxy< type > \
237 BOOST_PP_CAT(packetRegistration_, __LINE__) ( value ); \
240 /** \brief Statically add an entry to a packet registry with explicit priority
242 This macro will declare an anonymous global variable in such a way, that constructing this
243 variable will add a registration to the given packet registry.
245 \ingroup packet_module
248 # define SENF_PACKET_REGISTRY_REGISTER_PRIORITY( registry, value, priority, type ) \
250 senf::PacketRegistry< registry >::RegistrationProxy< type > \
251 BOOST_PP_CAT(packetRegistration_, __LINE__) ( value, priority ); \
254 /** \brief Dump all packet registries
256 This command will dump all packet registries to the given stream. This is to help debugging
257 registration problems.
259 void dumpPacketRegistries(std::ostream & os);
261 /** \brief Entry not found in registry
263 This exception is signaled whenever a throwing lookup operation fails.
265 struct PacketTypeNotRegisteredException : public senf::Exception
266 { PacketTypeNotRegisteredException() : senf::Exception("packet type not registered") {} };
270 ///////////////////////////////hh.e////////////////////////////////////////
272 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketRegistry_i_)
273 #define HH_SENF_Packets_PacketRegistry_i_
274 #include "PacketRegistry.cci"
275 #include "PacketRegistry.ct"
276 #include "PacketRegistry.cti"
283 // c-file-style: "senf"
284 // indent-tabs-mode: nil
285 // ispell-local-dictionary: "american"
286 // compile-command: "scons -u test"
287 // comment-column: 40