PacketImpl.ih
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
14 /** \file
15  \brief PacketImpl internal header */
16 
17 #ifndef IH_SENF_senf_Packets_PacketImpl_
18 #define IH_SENF_senf_Packets_PacketImpl_ 1
19 
20 // Custom includes
21 #include <map>
22 #include <string>
23 #include <ext/functional>
24 #include <boost/iterator/transform_iterator.hpp>
25 #include <boost/type_traits/is_convertible.hpp>
26 #include <boost/mpl/sizeof.hpp>
27 #include <boost/mpl/int.hpp>
28 #include <boost/mpl/or.hpp>
29 #include <boost/mpl/greater.hpp>
30 #include <boost/ptr_container/ptr_map.hpp>
31 #include <senf/Utils/TypeInfo.hh>
32 #include <senf/Utils/singleton.hh>
33 #include <senf/config.hh>
34 #include <senf/Utils/IgnoreValue.hh>
35 
36 //-/////////////////////////////////////////////////////////////////////////////////////////////////
37 
38 namespace senf {
39 
40  struct ComplexAnnotation;
41 
42 namespace detail {
43 
44  template <class Annotation>
45  struct IsComplexAnnotation
46  : public boost::mpl::or_< boost::is_convertible<Annotation*, ComplexAnnotation*>,
47  boost::mpl::greater<
48  boost::mpl::sizeof_<Annotation>,
49  boost::mpl::int_<SENF_PACKET_ANNOTATION_SLOTSIZE> > >
50  {};
51 
52  class AnnotationRegistry
53  : public senf::singleton<AnnotationRegistry>
54  {
55  public:
56  typedef int key_type;
57 
58  private:
59  struct RegistrationBase
60  {
61  virtual ~RegistrationBase () {};
62  key_type key;
63  virtual void v_dump(std::ostream & os, void * annotation) const = 0;
64  virtual std::string v_name() const = 0;
65  virtual bool v_isComplex() const = 0;
66  virtual unsigned v_size() const = 0;
67  };
68 
69  template <class Annotation>
70  struct Registration
71  : public RegistrationBase
72  {
73  void v_dump(std::ostream & os, void * annotation) const
74  { os << * static_cast<Annotation*>(annotation); }
75  std::string v_name() const
76  { return prettyName(typeid(Annotation)); }
77  bool v_isComplex() const
78  { return boost::is_convertible<Annotation*, ComplexAnnotation*>::value; }
79  unsigned v_size() const
80  { return sizeof(Annotation); }
81  };
82 
83  typedef boost::ptr_map<key_type, RegistrationBase> Registry;
84  // Index must be a multi-map since two identically named classes
85  // both in the anonymous namespace both have the same demangled name.
86  // we could sort on the mangled name instead ...
87  typedef std::multimap<std::string, key_type> Index;
88 
89  public:
90  typedef boost::transform_iterator< ::__gnu_cxx::select2nd<Index::value_type>,
91  Index::const_iterator > iterator;
92 
93  using senf::singleton<AnnotationRegistry>::instance;
94 
95  template <class Annotation> class RegistrationProxy;
96 
97  class EntryBase;
98  template <class Annotation> class Entry;
99 
100  template <class Annotation>
101  key_type registerAnnotation();
102 
103  void dump(key_type key, std::ostream & os, void * annotation) const;
104  std::string name(key_type key) const;
105  bool isComplex(key_type key) const;
106  unsigned size(key_type key) const;
107 
108  template <class Annotation>
109  static key_type lookup();
110 
111  iterator begin() const;
112  iterator end() const;
113 
114  void dumpRegistrations(std::ostream & os) const;
115 
116  private:
117  AnnotationRegistry();
118 
119  key_type simpleAnnotationCount_;
120 #ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
121  key_type complexAnnotationCount_;
122 #endif
123 
124  Registry registry_;
125  // The index is needed to ensure a persistent and reproducible
126  // ordering of the annotations when dumping
127  Index index_;
128 
129  friend class senf::singleton<AnnotationRegistry>;
130  };
131 
132  template <class Annotation>
133  class AnnotationRegistry::RegistrationProxy
134  {
135  public:
136  RegistrationProxy()
137  {
138  AnnotationRegistry::Entry<Annotation>::key_ =
139  AnnotationRegistry::instance().registerAnnotation<Annotation>();
140  }
141  };
142 
143  class AnnotationRegistry::EntryBase
144  {
145  public:
146  virtual ~EntryBase() {}
147 
148  virtual void * get() = 0;
149 
150  typedef EntryBase * ptr;
151  virtual ptr clone() const = 0;
152  };
153 
154  inline AnnotationRegistry::EntryBase::ptr new_clone( AnnotationRegistry::EntryBase const & entry)
155  {
156  return entry.clone();
157  }
158 
159  template <class Annotation>
160  class AnnotationRegistry::Entry
161  : public AnnotationRegistry::EntryBase
162  {
163  static RegistrationProxy<Annotation> proxy_;
164  static AnnotationRegistry::key_type key_;
165  public:
166  // We use this member to force instantiation of proxy_ ...
167  static AnnotationRegistry::key_type key()
168  { senf::IGNORE(&proxy_); return key_; }
169 
170  virtual void * get() { return & annotation_; }
171  virtual EntryBase::ptr clone() const { return new Entry<Annotation>( *this); }
172 
173  private:
174  Annotation annotation_;
175 
176  friend class AnnotationRegistry::RegistrationProxy<Annotation>;
177  };
178 
179 }}
180 
181 //-/////////////////////////////////////////////////////////////////////////////////////////////////
182 #endif
183 
184 
185 // Local Variables:
186 // mode: c++
187 // fill-column: 100
188 // comment-column: 40
189 // c-file-style: "senf"
190 // indent-tabs-mode: nil
191 // ispell-local-dictionary: "american"
192 // compile-command: "scons -u test"
193 // End: