src/common/trace-context-element.h
changeset 1334 e8e07f44359f
parent 1333 c0d66de933e9
child 1335 d0e45d84f9c6
equal deleted inserted replaced
1333:c0d66de933e9 1334:e8e07f44359f
     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 */