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>
35 #include <senf/Utils/singleton.hh>
38 #include "PacketRegistry.ih"
39 //#include "PacketRegistry.mpp"
40 ///////////////////////////////hh.p////////////////////////////////////////
44 /** \brief %Packet registration facility
46 The %PacketRegistry provides a generic facility to associate an arbitrary key with
47 Packets. Example keys are Ethertype or IP protocols.
49 Every %PacketRegistry is identified by a type tag:
52 typedef some_key_type key_t;
55 The key type can be an arbitrary value type. The %PacketRegistry for this Tag can then be
56 accessed using <code>senf::PacketRegistry<SomeTag>::</code>.
58 The %PacketRegistry class has only static members and provides access to the packet
59 registry. It allows two-way lookup either by key or by packet type.
62 senf::Packet::factory_t factory (senf::PacketRegistry<SomeTag>::lookup(some_key).factory());
63 SomeTag::key_t key = PacketRegistry<SomeTag>::key<SomePacket>();
66 Packets can be registered either dynamically or statically. Dynamic:
68 // dynamic registration
69 senf::PacketRegistry<SomeTag>::registerPacket<SomePacket>(key_of_somePacket);
71 // static registration. 'registerSomePacket' is an arbitrary symbol name
72 SENF_PACKET_REGISTRY_REGISTER( SomeTag, key_of_somePacket, SomePacket );
75 SENF_PACKET_REGISTRY_REGISTER will declare an anonymous global variable which will ensure,
76 the packet is registered automatically during global initialization (as long as the object
77 file is linked into the final executable).
79 \section packet_registry_priority Multiple registration for a single key
81 Ordinarily, the PacketRegistry will reject registering the same key twice. However, the
82 registry supports an additional priority parameter when registering a packet. You may
83 register multiple Packets with the same \a key as long as the \a priority is unique. The
84 registration with the highest \a priority value will take precedence on key lookup.
86 \ingroup packet_module
90 : private senf::singleton< PacketRegistry<Tag> >
93 typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::iterator iterator;
94 typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::Entry Entry;
96 /** \brief Statically register a packet type in a PacketRegistry
98 This class is normally used via SENF_PACKET_REGISTRY_REGISTER. To use this class
99 directly, define a symbol in the following way:
102 senf::PacketRegistry<Tag>::ScopedRegistrationProxy<PacketType>
103 registerPacketType (key, optional_priority);
106 Here \a Tag is the type tag of the registry to register the packet in, \a
107 PacketType is the packet to register (this is the ConcretePacket of that packet) and \a
108 key is the key of type \c Tag::key_t under which the packet is to be registered. \a
109 registerPacketType is an arbitrary name for the global symbol.
111 The packet will be registered in the constructor and will be unregistered when the scope
112 of \c registerPacketType ends.
114 template <class PacketType>
115 struct ScopedRegistrationProxy
117 ScopedRegistrationProxy(typename Tag::key_t key, int priority=0);
118 ~ScopedRegistrationProxy();
121 /** \brief Register new packet type
123 Register \a PacketType in the packet registry \a Tag under the given \a key.
126 The given pair \a key, \a priority must be unique and not be assigned to any other
127 packet class in this registry. The %Packet must not already be registered in the
130 \tparam PacketType ConcretePacket instantiation of packet to register
131 \param[in] key The key of the packet
132 \param [in] priority Optional priority
134 template <class PacketType>
135 static void registerPacket(typename Tag::key_t key, int priority=0);
137 /** \brief Unregister packet by packet type
139 Removes \a PacketType from the packet registry. If the packet type is not registered,
142 \tparam PacketType ConcretePacket instantiation of packet to remove from registry
144 template <class PacketType>
145 static void unregisterPacket();
147 /** \brief Unregister packet by key
149 Removes the packet registration for \a key (and \a priority) from the registry. If no
150 packet is registered with the given pair \a key, \a priority, this operation is a
153 \param[in] key Key to remove from the registry
154 \param[in] priority Optional priority of the key to remove
156 static void unregisterPacket(typename Tag::key_t key, int priority=0);
158 /** \brief Find key of a packet type
160 Return the key of \a PacketType as registered in the \a Tag registry
162 \tparam PacketType packet of which the key is requested
163 \returns key of the packet
164 \throws PacketTypeNotRegistered if the packet type is not found in the registry.
166 template <class PacketType>
167 static typename Tag::key_t key();
169 /** \brief Find key of a packet type
171 Return the key of \a PacketType as registered in the \a Tag registry
173 \tparam PacketType packet of which the key is requested
174 \returns key of the packet wrapped in a <a
175 href="http://www.boost.org/doc/libs/release/libs/optional/index.html">boost::optional</a> or
176 an unbound optional, if the key is not found.
178 template <class PacketType>
179 static typename boost::optional<typename Tag::key_t> key(NoThrow_t);
181 /** \brief Find key of a packet
183 Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
185 \param packet The packet of which the key is requested
186 \returns key of the packet
187 \throws PacketTypeNotRegistered if the packet type is not found in the registry.
189 static typename Tag::key_t key(Packet const & packet);
191 /** \brief Find key of a packet
193 Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
195 \param packet The packet of which the key is requested
196 \returns key of the packet wrapped in a <a
197 href="http://www.boost.org/doc/libs/release/libs/optional/index.html">boost::optional</a> or
198 an unbound optional, if the key is not found.
200 static typename boost::optional<typename Tag::key_t> key(Packet const & packet, NoThrow_t);
202 /** \brief Lookup a packet by it's key
204 \throws PacketTypeNotRegistered if the \a key is not found in the registry
205 \return %Packet entry for given \a key
207 static Entry const & lookup(typename Tag::key_t key);
209 /** \brief Lookup a packet by it's key
210 \return Pointer to packet entry for given \a key or 0, if the key is not found in the
213 static Entry const * lookup(typename Tag::key_t key, NoThrow_t);
215 /** \brief Beginning iterator to list of registered entries
217 static iterator begin();
219 /** \brief End iterator to list of registered entries
221 static iterator end();
224 using singleton<PacketRegistry>::instance;
225 using singleton<PacketRegistry>::alive;
229 typedef detail::PacketRegistryImpl<typename Tag::key_t> Registry;
230 static Registry & registry();
233 friend class senf::singleton< PacketRegistry >;
236 /** \brief Statically add an entry to a packet registry
238 This macro will declare an anonymous global variable in such a way, that constructing this
239 variable will add a registration to the given packet registry.
241 \ingroup packet_module
244 # define SENF_PACKET_REGISTRY_REGISTER( registry, value, type ) \
246 senf::PacketRegistry< registry >::ScopedRegistrationProxy< type > \
247 BOOST_PP_CAT(packetRegistration_, __LINE__) ( value ); \
250 /** \brief Statically add an entry to a packet registry with explicit priority
252 This macro will declare an anonymous global variable in such a way, that constructing this
253 variable will add a registration to the given packet registry.
255 \ingroup packet_module
258 # define SENF_PACKET_REGISTRY_REGISTER_PRIORITY( registry, value, priority, type ) \
260 senf::PacketRegistry< registry >::ScopedRegistrationProxy< type > \
261 BOOST_PP_CAT(packetRegistration_, __LINE__) ( value, priority ); \
264 /** \brief Dump all packet registries
266 This command will dump all packet registries to the given stream. This is to help debugging
267 registration problems.
269 void dumpPacketRegistries(std::ostream & os);
271 /** \brief Entry not found in registry
273 This exception is signaled whenever a throwing lookup operation fails.
275 struct PacketTypeNotRegisteredException : public senf::Exception
276 { PacketTypeNotRegisteredException() : senf::Exception("packet type not registered") {} };
280 ///////////////////////////////hh.e////////////////////////////////////////
282 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketRegistry_i_)
283 #define HH_SENF_Packets_PacketRegistry_i_
284 #include "PacketRegistry.cci"
285 #include "PacketRegistry.ct"
286 #include "PacketRegistry.cti"
293 // c-file-style: "senf"
294 // indent-tabs-mode: nil
295 // ispell-local-dictionary: "american"
296 // compile-command: "scons -u test"
297 // comment-column: 40