1 #ifndef TRACE_CONTEXT_ELEMENT_H |
|
2 #define TRACE_CONTEXT_ELEMENT_H |
|
3 |
|
4 #include <string> |
|
5 #include <vector> |
|
6 |
|
7 #define NS_TRACE_CONTEXT_ELEMENT_ENSURE_REGISTERED(x) \ |
|
8 namespace { \ |
|
9 static class thisisaveryverylongclassname ##x \ |
|
10 { \ |
|
11 public: \ |
|
12 thisisaveryverylongclassname ##x () \ |
|
13 { uint32_t uid; uid = x::GetUid ();} \ |
|
14 } g_thisisanotherveryveryverylongname ##x ; \ |
|
15 } |
|
16 |
|
17 namespace ns3 { |
|
18 |
|
19 /** |
|
20 * \brief an item stored in a TraceContext |
|
21 * |
|
22 * To store trace context information in a TraceContext instance, |
|
23 * users must subclass this base class and store subclass instances |
|
24 * in a TraceContext with TraceContext::Add. |
|
25 * |
|
26 * Each subclass should define and implement: |
|
27 * - a public default constructor: it is used by the internals |
|
28 * of the implementation of TraceContext. |
|
29 * - a public destructor: it is also used by the internals of |
|
30 * the implementation of TraceContext. |
|
31 * - a public static method named GetUid which returns a 16 bit |
|
32 * integer. The integer returned from this method should be |
|
33 * allocated with the protected AllocatedUid method. |
|
34 * - a public Print method: this method is used by the |
|
35 * TraceContext::Print method to print the content of each |
|
36 * of the trace context element stored in the trace context. |
|
37 * This method takes a c++ output stream and argument and is |
|
38 * expected to write an ascii string describing its content |
|
39 * in this output stream. |
|
40 * |
|
41 * A typical subclass should look like this: |
|
42 * \code |
|
43 * class MyContext : public TraceContextElement |
|
44 * { |
|
45 * public: |
|
46 * // the _required_ public API |
|
47 * static uint16_t GetUid (void); |
|
48 * MyContext (); |
|
49 * ~MyContext (); |
|
50 * void Print (std::ostream &os) const; |
|
51 * |
|
52 * // the user-specific API to manipulate the context. |
|
53 * void SetData (uint8_t data); |
|
54 * uint8_t GetData (void) const; |
|
55 * private: |
|
56 * uint8_t m_myContextData; |
|
57 * }; |
|
58 * |
|
59 * uint16_t |
|
60 * MyContext::GetUid (void) |
|
61 * { |
|
62 * static uint16_t uid = AllocateUid<MyContext> ("MyContext"); |
|
63 * return uid; |
|
64 * } |
|
65 * MyContext::MyContext () |
|
66 * {} |
|
67 * MyContext::~MyContext () |
|
68 * {} |
|
69 * void |
|
70 * MyContext::Print (std::ostream &os) const |
|
71 * { |
|
72 * os << "mycontext=" << (uint32_t) m_myContextData; |
|
73 * } |
|
74 * void |
|
75 * MyContext::SetData (uint8_t data) |
|
76 * { |
|
77 * m_myContextData = data; |
|
78 * } |
|
79 * uint8_t |
|
80 * MyContext::GetData (void) const |
|
81 * { |
|
82 * return m_myContextData; |
|
83 * } |
|
84 * \endcode |
|
85 */ |
|
86 class TraceContextElement |
|
87 { |
|
88 protected: |
|
89 /** |
|
90 * \param name a string which uniquely identifies the type |
|
91 * of the subclass which is calling this method. |
|
92 * \returns a unique 32 bit integer associated to the |
|
93 * input string. |
|
94 * |
|
95 * Subclasses are expected to call this method from their |
|
96 * public static GetUid method. |
|
97 */ |
|
98 template <typename T> |
|
99 static uint16_t AllocateUid (std::string name); |
|
100 }; |
|
101 |
|
102 } // namespace ns3 |
|
103 |
|
104 namespace ns3 { |
|
105 |
|
106 /** |
|
107 * \brief a registry of TraceContextElement subclasses |
|
108 * \internal |
|
109 */ |
|
110 class ElementRegistry |
|
111 { |
|
112 public: |
|
113 template <typename T> |
|
114 static uint16_t AllocateUid (std::string name); |
|
115 |
|
116 static uint32_t GetSize (uint16_t uid); |
|
117 static void Print (uint16_t uid, uint8_t *instance, std::ostream &os); |
|
118 static void Destroy (uint16_t uid, uint8_t *instance); |
|
119 private: |
|
120 typedef void (*PrintCb) (uint8_t *instance, std::ostream &os); |
|
121 typedef void (*DestroyCb) (uint8_t *instance); |
|
122 struct Info { |
|
123 uint32_t size; |
|
124 std::string uidString; |
|
125 PrintCb print; |
|
126 DestroyCb destroy; |
|
127 }; |
|
128 typedef std::vector<struct Info> InfoVector; |
|
129 static InfoVector *GetInfoVector (void); |
|
130 template <typename T> |
|
131 static void DoPrint (uint8_t *instance, std::ostream &os); |
|
132 template <typename T> |
|
133 static void DoDestroy (uint8_t *instance); |
|
134 }; |
|
135 |
|
136 template <typename T> |
|
137 void |
|
138 ElementRegistry::DoPrint (uint8_t *instance, std::ostream &os) |
|
139 { |
|
140 static T obj; |
|
141 // make sure we are aligned. |
|
142 memcpy ((void*)&obj, instance, sizeof (T)); |
|
143 obj.Print (os); |
|
144 } |
|
145 template <typename T> |
|
146 void |
|
147 ElementRegistry::DoDestroy (uint8_t *instance) |
|
148 { |
|
149 static T obj; |
|
150 // make sure we are aligned. |
|
151 memcpy ((void*)&obj, instance, sizeof (T)); |
|
152 obj.~T (); |
|
153 } |
|
154 |
|
155 template <typename T> |
|
156 uint16_t |
|
157 ElementRegistry::AllocateUid (std::string name) |
|
158 { |
|
159 InfoVector *vec = GetInfoVector (); |
|
160 uint16_t uid = 1; |
|
161 for (InfoVector::iterator i = vec->begin (); i != vec->end (); i++) |
|
162 { |
|
163 if (i->uidString == name) |
|
164 { |
|
165 return uid; |
|
166 } |
|
167 uid++; |
|
168 } |
|
169 struct Info info; |
|
170 info.size = sizeof (T); |
|
171 info.uidString = name; |
|
172 info.print = &ElementRegistry::DoPrint<T>; |
|
173 info.destroy = &ElementRegistry::DoDestroy<T>; |
|
174 vec->push_back (info); |
|
175 return vec->size (); |
|
176 } |
|
177 |
|
178 |
|
179 |
|
180 template <typename T> |
|
181 uint16_t |
|
182 TraceContextElement::AllocateUid (std::string name) |
|
183 { |
|
184 return ElementRegistry::AllocateUid<T> (name); |
|
185 } |
|
186 |
|
187 } // namespace ns3 |
|
188 |
|
189 #endif /* TRACE_CONTEXT_ELEMENT_H */ |
|