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