A Discrete-Event Network Simulator
API
callback.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2005,2006 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18  * Stefano Avallone <stavallo@unina.it>
19  */
20 
21 #ifndef CALLBACK_H
22 #define CALLBACK_H
23 
24 #include "attribute-helper.h"
25 #include "attribute.h"
26 #include "fatal-error.h"
27 #include "ptr.h"
28 #include "simple-ref-count.h"
29 
30 #include <functional>
31 #include <memory>
32 #include <typeinfo>
33 #include <utility>
34 #include <vector>
35 
42 namespace ns3
43 {
44 
45 // Define the doxygen subgroups all at once,
46 // since the implementations are interleaved.
47 
80 class CallbackImplBase : public SimpleRefCount<CallbackImplBase>
81 {
82  public:
85  {
86  }
87 
94  virtual bool IsEqual(Ptr<const CallbackImplBase> other) const = 0;
99  virtual std::string GetTypeid() const = 0;
100 
101  protected:
106  static std::string Demangle(const std::string& mangled);
107 
114  template <typename T>
115  static std::string GetCppTypeid()
116  {
117  std::string typeName;
118  try
119  {
120  typeName = typeid(T).name();
121  typeName = Demangle(typeName);
122  }
123  catch (const std::bad_typeid& e)
124  {
125  typeName = e.what();
126  }
127  return typeName;
128  }
129 };
130 
137 {
138  public:
141  {
142  }
143 
150  virtual bool IsEqual(std::shared_ptr<const CallbackComponentBase> other) const = 0;
151 };
152 
162 template <typename T, bool isComparable = true>
164 {
165  public:
171  CallbackComponent(const T& t)
172  : m_comp(t)
173  {
174  }
175 
182  bool IsEqual(std::shared_ptr<const CallbackComponentBase> other) const override
183  {
184  auto p = std::dynamic_pointer_cast<const CallbackComponent<T>>(other);
185 
186  // other must have the same type and value as ours
187  if (p == nullptr || p->m_comp != m_comp)
188  {
189  return false;
190  }
191 
192  return true;
193  }
194 
195  private:
196  T m_comp;
197 };
198 
210 template <typename T>
211 class CallbackComponent<T, false> : public CallbackComponentBase
212 {
213  public:
219  CallbackComponent(const T& t)
220  {
221  }
222 
229  bool IsEqual(std::shared_ptr<const CallbackComponentBase> other) const override
230  {
231  return false;
232  }
233 };
234 
236 typedef std::vector<std::shared_ptr<CallbackComponentBase>> CallbackComponentVector;
237 
245 template <typename R, typename... UArgs>
247 {
248  public:
255  CallbackImpl(std::function<R(UArgs...)> func, const CallbackComponentVector& components)
256  : m_func(func),
257  m_components(components)
258  {
259  }
260 
265  const std::function<R(UArgs...)>& GetFunction() const
266  {
267  return m_func;
268  }
269 
275  {
276  return m_components;
277  }
278 
285  R operator()(UArgs... uargs) const
286  {
287  return m_func(uargs...);
288  }
289 
290  bool IsEqual(Ptr<const CallbackImplBase> other) const override
291  {
292  const CallbackImpl<R, UArgs...>* otherDerived =
293  dynamic_cast<const CallbackImpl<R, UArgs...>*>(PeekPointer(other));
294 
295  if (otherDerived == nullptr)
296  {
297  return false;
298  }
299 
300  // if the two callback implementations are made of a distinct number of
301  // components, they are different
302  if (m_components.size() != otherDerived->GetComponents().size())
303  {
304  return false;
305  }
306 
307  // the two functions are equal if they compare equal or the shared pointers
308  // point to the same locations
309  if (!m_components.at(0)->IsEqual(otherDerived->GetComponents().at(0)) &&
310  m_components.at(0) != otherDerived->GetComponents().at(0))
311  {
312  return false;
313  }
314 
315  // check if the remaining components are equal one by one
316  for (std::size_t i = 1; i < m_components.size(); i++)
317  {
318  if (!m_components.at(i)->IsEqual(otherDerived->GetComponents().at(i)))
319  {
320  return false;
321  }
322  }
323 
324  return true;
325  }
326 
327  std::string GetTypeid() const override
328  {
329  return DoGetTypeid();
330  }
331 
333  static std::string DoGetTypeid()
334  {
335  static std::vector<std::string> vec = {GetCppTypeid<R>(), GetCppTypeid<UArgs>()...};
336 
337  static std::string id("CallbackImpl<");
338  for (auto& s : vec)
339  {
340  id.append(s + ",");
341  }
342  if (id.back() == ',')
343  {
344  id.pop_back();
345  }
346  id.push_back('>');
347 
348  return id;
349  }
350 
351  private:
353  std::function<R(UArgs...)> m_func;
354 
356  std::vector<std::shared_ptr<CallbackComponentBase>> m_components;
357 };
358 
365 {
366  public:
368  : m_impl()
369  {
370  }
371 
374  {
375  return m_impl;
376  }
377 
378  protected:
384  : m_impl(impl)
385  {
386  }
387 
389 };
390 
441 template <typename R, typename... UArgs>
442 class Callback : public CallbackBase
443 {
444  template <typename ROther, typename... UArgsOther>
445  friend class Callback;
446 
447  public:
449  {
450  }
451 
458  : CallbackBase(impl)
459  {
460  }
461 
469  template <typename... BArgs>
470  Callback(const Callback<R, BArgs..., UArgs...>& cb, BArgs... bargs)
471  {
472  auto f = cb.DoPeekImpl()->GetFunction();
473 
474  CallbackComponentVector components(cb.DoPeekImpl()->GetComponents());
475  components.insert(components.end(), {std::make_shared<CallbackComponent<BArgs>>(bargs)...});
476 
477  m_impl = Create<CallbackImpl<R, UArgs...>>(
478  [f, bargs...](auto&&... uargs) -> R {
479  return f(bargs..., std::forward<decltype(uargs)>(uargs)...);
480  },
481  components);
482  }
483 
496  template <typename T,
497  std::enable_if_t<!std::is_base_of_v<CallbackBase, T>, int> = 0,
498  typename... BArgs>
499  Callback(T func, BArgs... bargs)
500  {
501  // store the function in a std::function object
502  std::function<R(BArgs..., UArgs...)> f(func);
503 
504  // The original function is comparable if it is a function pointer or
505  // a pointer to a member function or a pointer to a member data.
506  constexpr bool isComp =
507  std::is_function_v<std::remove_pointer_t<T>> || std::is_member_pointer_v<T>;
508 
509  CallbackComponentVector components({std::make_shared<CallbackComponent<T, isComp>>(func),
510  std::make_shared<CallbackComponent<BArgs>>(bargs)...});
511 
512  m_impl = Create<CallbackImpl<R, UArgs...>>(
513  [f, bargs...](auto&&... uargs) -> R {
514  return f(bargs..., std::forward<decltype(uargs)>(uargs)...);
515  },
516  components);
517  }
518 
519  private:
531  template <std::size_t... INDEX, typename... BoundArgs>
532  auto BindImpl(std::index_sequence<INDEX...> seq, BoundArgs&&... bargs)
533  {
534  Callback<R, std::tuple_element_t<sizeof...(bargs) + INDEX, std::tuple<UArgs...>>...> cb;
535 
536  const auto f = DoPeekImpl()->GetFunction();
537 
538  CallbackComponentVector components(DoPeekImpl()->GetComponents());
539  components.insert(components.end(),
540  {std::make_shared<CallbackComponent<BoundArgs>>(bargs)...});
541 
542  cb.m_impl = Create<std::remove_pointer_t<decltype(cb.DoPeekImpl())>>(
543  [f, bargs...](auto&&... uargs) mutable {
544  return f(bargs..., std::forward<decltype(uargs)>(uargs)...);
545  },
546  components);
547 
548  return cb;
549  }
550 
551  public:
559  template <typename... BoundArgs>
560  auto Bind(BoundArgs&&... bargs)
561  {
562  static_assert(sizeof...(UArgs) > 0);
563  return BindImpl(std::make_index_sequence<sizeof...(UArgs) - sizeof...(BoundArgs)>{},
564  std::forward<BoundArgs>(bargs)...);
565  }
566 
572  bool IsNull() const
573  {
574  return (DoPeekImpl() == nullptr);
575  }
576 
578  void Nullify()
579  {
580  m_impl = nullptr;
581  }
582 
589  R operator()(UArgs... uargs) const
590  {
591  return (*(DoPeekImpl()))(uargs...);
592  }
593 
600  bool IsEqual(const CallbackBase& other) const
601  {
602  return m_impl->IsEqual(other.GetImpl());
603  }
604 
611  bool CheckType(const CallbackBase& other) const
612  {
613  return DoCheckType(other.GetImpl());
614  }
615 
622  bool Assign(const CallbackBase& other)
623  {
624  auto otherImpl = other.GetImpl();
625  if (!DoCheckType(otherImpl))
626  {
627  std::string othTid = otherImpl->GetTypeid();
628  std::string myTid = CallbackImpl<R, UArgs...>::DoGetTypeid();
629  NS_FATAL_ERROR_CONT("Incompatible types. (feed to \"c++filt -t\" if needed)"
630  << std::endl
631  << "got=" << othTid << std::endl
632  << "expected=" << myTid);
633  return false;
634  }
635  m_impl = const_cast<CallbackImplBase*>(PeekPointer(otherImpl));
636  return true;
637  }
638 
639  private:
641  CallbackImpl<R, UArgs...>* DoPeekImpl() const
642  {
643  return static_cast<CallbackImpl<R, UArgs...>*>(PeekPointer(m_impl));
644  }
645 
653  {
654  if (other && dynamic_cast<const CallbackImpl<R, UArgs...>*>(PeekPointer(other)) != nullptr)
655  {
656  return true;
657  }
658  else if (!other)
659  {
660  return true;
661  }
662  else
663  {
664  return false;
665  }
666  }
667 };
668 
679 template <typename R, typename... Args>
680 bool
682 {
683  return !a.IsEqual(b);
684 }
685 
705 template <typename T, typename OBJ, typename R, typename... Args>
706 Callback<R, Args...>
707 MakeCallback(R (T::*memPtr)(Args...), OBJ objPtr)
708 {
709  return Callback<R, Args...>(memPtr, objPtr);
710 }
711 
712 template <typename T, typename OBJ, typename R, typename... Args>
713 Callback<R, Args...>
714 MakeCallback(R (T::*memPtr)(Args...) const, OBJ objPtr)
715 {
716  return Callback<R, Args...>(memPtr, objPtr);
717 }
718 
731 template <typename R, typename... Args>
732 Callback<R, Args...>
733 MakeCallback(R (*fnPtr)(Args...))
734 {
735  return Callback<R, Args...>(fnPtr);
736 }
737 
748 template <typename R, typename... Args>
749 Callback<R, Args...>
751 {
752  return Callback<R, Args...>();
753 }
754 
766 template <typename R, typename... Args, typename... BArgs>
767 auto
768 MakeBoundCallback(R (*fnPtr)(Args...), BArgs&&... bargs)
769 {
770  return Callback<R, Args...>(fnPtr).Bind(std::forward<BArgs>(bargs)...);
771 }
772 
787 template <typename T, typename OBJ, typename R, typename... Args, typename... BArgs>
788 auto
789 MakeCallback(R (T::*memPtr)(Args...), OBJ objPtr, BArgs... bargs)
790 {
791  return Callback<R, Args...>(memPtr, objPtr).Bind(bargs...);
792 }
793 
794 template <typename T, typename OBJ, typename R, typename... Args, typename... BArgs>
795 auto
796 MakeCallback(R (T::*memPtr)(Args...) const, OBJ objPtr, BArgs... bargs)
797 {
798  return Callback<R, Args...>(memPtr, objPtr).Bind(bargs...);
799 }
800 
803 } // namespace ns3
804 
805 namespace ns3
806 {
807 
809 {
810  public:
812  CallbackValue();
817  CallbackValue(const CallbackBase& base);
819  ~CallbackValue() override;
821  void Set(CallbackBase base);
822  /* Documented by print-introspected-doxygen.cc */
823  template <typename T>
824  bool GetAccessor(T& value) const;
826  Ptr<AttributeValue> Copy() const override;
832  std::string SerializeToString(Ptr<const AttributeChecker> checker) const override;
840  bool DeserializeFromString(std::string value, Ptr<const AttributeChecker> checker) override;
841 
842  private:
843  /* Documented by print-introspected-doxygen.cc */
845 };
846 
849 
850 } // namespace ns3
851 
852 namespace ns3
853 {
854 
855 template <typename T>
856 bool
858 {
859  if (value.CheckType(m_value))
860  {
861  if (!value.Assign(m_value))
862  {
864  }
865  return true;
866  }
867  return false;
868 }
869 
870 } // namespace ns3
871 
872 #endif /* CALLBACK_H */
double f(double x, void *params)
Definition: 80211b.c:71
Attribute helper (ATTRIBUTE_ )macros definition.
ns3::AttributeValue, ns3::AttributeAccessor and ns3::AttributeChecker declarations.
Hold a value for an Attribute.
Definition: attribute.h:70
Base class for Callback class.
Definition: callback.h:365
CallbackBase(Ptr< CallbackImplBase > impl)
Construct from a pimpl.
Definition: callback.h:383
Ptr< CallbackImplBase > GetImpl() const
Definition: callback.h:373
Ptr< CallbackImplBase > m_impl
the pimpl
Definition: callback.h:388
bool IsEqual(std::shared_ptr< const CallbackComponentBase > other) const override
Equality test between functions.
Definition: callback.h:229
CallbackComponent(const T &t)
Constructor.
Definition: callback.h:219
Abstract base class for CallbackComponent.
Definition: callback.h:137
virtual bool IsEqual(std::shared_ptr< const CallbackComponentBase > other) const =0
Equality test.
virtual ~CallbackComponentBase()
Virtual destructor.
Definition: callback.h:140
Stores a component of a callback, i.e., the callable object or a bound argument.
Definition: callback.h:164
CallbackComponent(const T &t)
Constructor.
Definition: callback.h:171
T m_comp
the value of the callback component
Definition: callback.h:196
bool IsEqual(std::shared_ptr< const CallbackComponentBase > other) const override
Equality test between the values of two components.
Definition: callback.h:182
Callback template class.
Definition: callback.h:443
Callback(const Ptr< CallbackImpl< R, UArgs... >> &impl)
Construct from a CallbackImpl pointer.
Definition: callback.h:457
bool IsEqual(const CallbackBase &other) const
Equality test.
Definition: callback.h:600
bool DoCheckType(Ptr< const CallbackImplBase > other) const
Check for compatible types.
Definition: callback.h:652
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:578
bool IsNull() const
Check for null implementation.
Definition: callback.h:572
R operator()(UArgs... uargs) const
Functor with varying numbers of arguments.
Definition: callback.h:589
auto Bind(BoundArgs &&... bargs)
Bind a variable number of arguments.
Definition: callback.h:560
auto BindImpl(std::index_sequence< INDEX... > seq, BoundArgs &&... bargs)
Implementation of the Bind method.
Definition: callback.h:532
Callback(T func, BArgs... bargs)
Construct from a function and bind some arguments (if any)
Definition: callback.h:499
Callback(const Callback< R, BArgs..., UArgs... > &cb, BArgs... bargs)
Construct from another callback and bind some arguments (if any)
Definition: callback.h:470
CallbackImpl< R, UArgs... > * DoPeekImpl() const
Definition: callback.h:641
bool CheckType(const CallbackBase &other) const
Check for compatible types.
Definition: callback.h:611
bool Assign(const CallbackBase &other)
Adopt the other's implementation, if type compatible.
Definition: callback.h:622
Abstract base class for CallbackImpl Provides reference counting and equality test.
Definition: callback.h:81
virtual bool IsEqual(Ptr< const CallbackImplBase > other) const =0
Equality test.
static std::string GetCppTypeid()
Helper to get the C++ typeid as a string.
Definition: callback.h:115
virtual ~CallbackImplBase()
Virtual destructor.
Definition: callback.h:84
static std::string Demangle(const std::string &mangled)
Definition: callback.cc:142
virtual std::string GetTypeid() const =0
Get the name of this object type.
CallbackImpl class with varying numbers of argument types.
Definition: callback.h:247
std::vector< std::shared_ptr< CallbackComponentBase > > m_components
Stores the original callable object and the bound arguments, if any.
Definition: callback.h:356
std::function< R(UArgs...)> m_func
Stores the callable object associated with this callback (as a lambda)
Definition: callback.h:353
R operator()(UArgs... uargs) const
Function call operator.
Definition: callback.h:285
static std::string DoGetTypeid()
Definition: callback.h:333
const CallbackComponentVector & GetComponents() const
Get the vector of callback components.
Definition: callback.h:274
const std::function< R(UArgs...)> & GetFunction() const
Get the stored function.
Definition: callback.h:265
CallbackImpl(std::function< R(UArgs...)> func, const CallbackComponentVector &components)
Constructor.
Definition: callback.h:255
std::string GetTypeid() const override
Get the name of this object type.
Definition: callback.h:327
bool IsEqual(Ptr< const CallbackImplBase > other) const override
Equality test.
Definition: callback.h:290
AttributeValue implementation for Callback.
Definition: callback.h:809
bool DeserializeFromString(std::string value, Ptr< const AttributeChecker > checker) override
Deserialize from string (not implemented)
Definition: callback.cc:76
std::string SerializeToString(Ptr< const AttributeChecker > checker) const override
Serialize to string.
Definition: callback.cc:67
void Set(CallbackBase base)
Definition: callback.cc:52
CallbackValue()
Constructor.
Definition: callback.cc:35
bool GetAccessor(T &value) const
Access the Callback value as type T.
Definition: callback.h:857
Ptr< AttributeValue > Copy() const override
Definition: callback.cc:60
~CallbackValue() override
Destructor.
Definition: callback.cc:46
CallbackBase m_value
The stored Callback instance.
Definition: callback.h:844
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
A template-based reference counting class.
NS_FATAL_x macro definitions.
#define ATTRIBUTE_ACCESSOR_DEFINE(type)
Define the attribute accessor functions MakeTypeAccessor for class type.
#define ATTRIBUTE_CHECKER_DEFINE(type)
Declare the AttributeChecker class typeChecker and the MaketypeChecker function for class type.
Callback< R, Args... > MakeNullCallback()
Definition: callback.h:750
#define NS_FATAL_ERROR_CONT(msg)
Report a fatal error with a message, deferring termination.
Definition: fatal-error.h:195
#define NS_FATAL_ERROR_NO_MSG()
Report a fatal error and terminate.
Definition: fatal-error.h:142
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:768
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition: ptr.h:481
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool operator!=(Callback< R, Args... > a, Callback< R, Args... > b)
Inequality test.
Definition: callback.h:681
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:707
std::vector< std::shared_ptr< CallbackComponentBase > > CallbackComponentVector
Vector of callback components.
Definition: callback.h:236
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:488
value
Definition: second.py:41
ns3::Ptr smart pointer declaration and implementation.
ns3::SimpleRefCount declaration and template implementation.