1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006,2007 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #ifndef TRACED_CALLBACK_H
22 #define TRACED_CALLBACK_H
23 
24 #include <list>
25 #include "callback.h"
26 
27 /**
28  * \file
29  * \ingroup tracing
30  * ns3::TracedCallback declaration and template implementation.
31  */
32 
33 namespace ns3 {
34 
35 /**
36  * \ingroup tracing
37  * \brief Forward calls to a chain of Callback
38  *
39  * A TracedCallback has almost exactly the same API as a normal
40  * Callback but instead of forwarding calls to a single function
41  * (as a Callback normally does), it forwards calls to a chain
42  * of Callback.  Connect adds a Callback at the end of the chain
43  * of callbacks.  Disconnect removes a Callback from the chain of callbacks.
44  *
45  * This is a functor: the chain of Callbacks is invoked by
46  * calling the \c operator() form with the appropriate
47  * number of arguments.
48  *
49  * \tparam Ts \explicit Types of the functor arguments.
50  */
51 template<typename... Ts>
52 class TracedCallback
53 {
54 public:
55   /** Constructor. */
56   TracedCallback ();
57   /**
58    * Append a Callback to the chain (without a context).
59    *
60    * \param [in] callback Callback to add to chain.
61    */
62   void ConnectWithoutContext (const CallbackBase & callback);
63   /**
64    * Append a Callback to the chain with a context.
65    *
66    * The context string will be provided as the first argument
67    * to the Callback.
68    *
69    * \param [in] callback Callback to add to chain.
70    * \param [in] path Context string to provide when invoking the Callback.
71    */
72   void Connect (const CallbackBase & callback, std::string path);
73   /**
74    * Remove from the chain a Callback which was connected without a context.
75    *
76    * \param [in] callback Callback to remove from the chain.
77    */
78   void DisconnectWithoutContext (const CallbackBase & callback);
79   /**
80    * Remove from the chain a Callback which was connected with a context.
81    *
82    * \param [in] callback Callback to remove from the chain.
83    * \param [in] path Context path which was used to connect the Callback.
84    */
85   void Disconnect (const CallbackBase & callback, std::string path);
86   /**
87    * \brief Functor which invokes the chain of Callbacks.
88    * \tparam Ts \deduced Types of the functor arguments.
89    * \param [in] args The arguments to the functor
90    */
91   void operator() (Ts... args) const;
92   /**
93    * \brief Checks if the Callbacks list is empty.
94    * \return true if the Callbacks list is empty.
95    */
96   bool IsEmpty () const;
97 
98   /**
99    *  TracedCallback signature for POD.
100    *
101    * \param [in] value Value of the traced variable.
102    * @{
103    */
104   // Uint32Callback appears to be the only one used at the moment.
105   // Feel free to add typedef's for any other POD you need.
106   typedef void (* Uint32Callback)(const uint32_t value);
107   /**@}*/
108 
109 private:
110   /**
111    * Container type for holding the chain of Callbacks.
112    *
113    * \tparam Ts \deduced Types of the functor arguments.
114    */
115   typedef std::list<Callback<void,Ts...> > CallbackList;
116   /** The chain of Callbacks. */
117   CallbackList m_callbackList;
118 };
119 
120 } // namespace ns3
121 
122 
123 /********************************************************************
124  *  Implementation of the templates declared above.
125  ********************************************************************/
126 
127 namespace ns3 {
128 
129 template<typename... Ts>
TracedCallback()130 TracedCallback<Ts...>::TracedCallback ()
131   : m_callbackList ()
132 {}
133 template<typename... Ts>
134 void
ConnectWithoutContext(const CallbackBase & callback)135 TracedCallback<Ts...>::ConnectWithoutContext (const CallbackBase & callback)
136 {
137   Callback<void,Ts...> cb;
138   if (!cb.Assign (callback))
139     {
140       NS_FATAL_ERROR_NO_MSG ();
141     }
142   m_callbackList.push_back (cb);
143 }
144 template<typename... Ts>
145 void
Connect(const CallbackBase & callback,std::string path)146 TracedCallback<Ts...>::Connect (const CallbackBase & callback, std::string path)
147 {
148   Callback<void,std::string,Ts...> cb;
149   if (!cb.Assign (callback))
150     {
151       NS_FATAL_ERROR ("when connecting to " << path);
152     }
153   Callback<void,Ts...> realCb = cb.Bind (path);
154   m_callbackList.push_back (realCb);
155 }
156 template<typename... Ts>
157 void
DisconnectWithoutContext(const CallbackBase & callback)158 TracedCallback<Ts...>::DisconnectWithoutContext (const CallbackBase & callback)
159 {
160   for (typename CallbackList::iterator i = m_callbackList.begin ();
161        i != m_callbackList.end (); /* empty */)
162     {
163       if ((*i).IsEqual (callback))
164         {
165           i = m_callbackList.erase (i);
166         }
167       else
168         {
169           i++;
170         }
171     }
172 }
173 template<typename... Ts>
174 void
Disconnect(const CallbackBase & callback,std::string path)175 TracedCallback<Ts...>::Disconnect (const CallbackBase & callback, std::string path)
176 {
177   Callback<void,std::string,Ts...> cb;
178   if (!cb.Assign (callback))
179     {
180       NS_FATAL_ERROR ("when disconnecting from " << path);
181     }
182   Callback<void,Ts...> realCb = cb.Bind (path);
183   DisconnectWithoutContext (realCb);
184 }
185 template<typename... Ts>
186 void
operator()187 TracedCallback<Ts...>::operator() (Ts... args) const
188 {
189   for (typename CallbackList::const_iterator i = m_callbackList.begin ();
190        i != m_callbackList.end (); i++)
191     {
192       (*i)(args...);
193     }
194 }
195 
196 template <typename... Ts>
197 bool
IsEmpty()198 TracedCallback<Ts...>::IsEmpty () const
199 {
200   return m_callbackList.empty ();
201 }
202 
203 } // namespace ns3
204 
205 #endif /* TRACED_CALLBACK_H */
206