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  return !(p == nullptr || p->m_comp != m_comp);
188  }
189 
190  private:
191  T m_comp;
192 };
193 
205 template <typename T>
206 class CallbackComponent<T, false> : public CallbackComponentBase
207 {
208  public:
214  CallbackComponent(const T& t)
215  {
216  }
217 
224  bool IsEqual(std::shared_ptr<const CallbackComponentBase> other) const override
225  {
226  return false;
227  }
228 };
229 
231 typedef std::vector<std::shared_ptr<CallbackComponentBase>> CallbackComponentVector;
232 
240 template <typename R, typename... UArgs>
242 {
243  public:
250  CallbackImpl(std::function<R(UArgs...)> func, const CallbackComponentVector& components)
251  : m_func(func),
252  m_components(components)
253  {
254  }
255 
260  const std::function<R(UArgs...)>& GetFunction() const
261  {
262  return m_func;
263  }
264 
270  {
271  return m_components;
272  }
273 
280  R operator()(UArgs... uargs) const
281  {
282  return m_func(uargs...);
283  }
284 
285  bool IsEqual(Ptr<const CallbackImplBase> other) const override
286  {
287  const auto otherDerived =
288  dynamic_cast<const CallbackImpl<R, UArgs...>*>(PeekPointer(other));
289 
290  if (otherDerived == nullptr)
291  {
292  return false;
293  }
294 
295  // if the two callback implementations are made of a distinct number of
296  // components, they are different
297  if (m_components.size() != otherDerived->GetComponents().size())
298  {
299  return false;
300  }
301 
302  // the two functions are equal if they compare equal or the shared pointers
303  // point to the same locations
304  if (!m_components.at(0)->IsEqual(otherDerived->GetComponents().at(0)) &&
305  m_components.at(0) != otherDerived->GetComponents().at(0))
306  {
307  return false;
308  }
309 
310  // check if the remaining components are equal one by one
311  for (std::size_t i = 1; i < m_components.size(); i++)
312  {
313  if (!m_components.at(i)->IsEqual(otherDerived->GetComponents().at(i)))
314  {
315  return false;
316  }
317  }
318 
319  return true;
320  }
321 
322  std::string GetTypeid() const override
323  {
324  return DoGetTypeid();
325  }
326 
328  static std::string DoGetTypeid()
329  {
330  static std::vector<std::string> vec = {GetCppTypeid<R>(), GetCppTypeid<UArgs>()...};
331 
332  static std::string id("CallbackImpl<");
333  for (auto& s : vec)
334  {
335  id.append(s + ",");
336  }
337  if (id.back() == ',')
338  {
339  id.pop_back();
340  }
341  id.push_back('>');
342 
343  return id;
344  }
345 
346  private:
348  std::function<R(UArgs...)> m_func;
349 
351  std::vector<std::shared_ptr<CallbackComponentBase>> m_components;
352 };
353 
360 {
361  public:
363  : m_impl()
364  {
365  }
366 
369  {
370  return m_impl;
371  }
372 
373  protected:
379  : m_impl(impl)
380  {
381  }
382 
384 };
385 
436 template <typename R, typename... UArgs>
437 class Callback : public CallbackBase
438 {
439  template <typename ROther, typename... UArgsOther>
440  friend class Callback;
441 
442  public:
444  {
445  }
446 
453  : CallbackBase(impl)
454  {
455  }
456 
464  template <typename... BArgs>
465  Callback(const Callback<R, BArgs..., UArgs...>& cb, BArgs... bargs)
466  {
467  auto f = cb.DoPeekImpl()->GetFunction();
468 
469  CallbackComponentVector components(cb.DoPeekImpl()->GetComponents());
470  components.insert(components.end(),
471  {std::make_shared<CallbackComponent<std::decay_t<BArgs>>>(bargs)...});
472 
473  m_impl = Create<CallbackImpl<R, UArgs...>>(
474  [f, bargs...](auto&&... uargs) -> R {
475  return f(bargs..., std::forward<decltype(uargs)>(uargs)...);
476  },
477  components);
478  }
479 
492  template <typename T,
493  std::enable_if_t<!std::is_base_of_v<CallbackBase, T>, int> = 0,
494  typename... BArgs>
495  Callback(T func, BArgs... bargs)
496  {
497  // store the function in a std::function object
498  std::function<R(BArgs..., UArgs...)> f(func);
499 
500  // The original function is comparable if it is a function pointer or
501  // a pointer to a member function or a pointer to a member data.
502  constexpr bool isComp =
503  std::is_function_v<std::remove_pointer_t<T>> || std::is_member_pointer_v<T>;
504 
505  CallbackComponentVector components(
506  {std::make_shared<CallbackComponent<T, isComp>>(func),
507  std::make_shared<CallbackComponent<std::decay_t<BArgs>>>(bargs)...});
508 
509  m_impl = Create<CallbackImpl<R, UArgs...>>(
510  [f, bargs...](auto&&... uargs) -> R {
511  return f(bargs..., std::forward<decltype(uargs)>(uargs)...);
512  },
513  components);
514  }
515 
516  private:
528  template <std::size_t... INDEX, typename... BoundArgs>
529  auto BindImpl(std::index_sequence<INDEX...> seq, BoundArgs&&... bargs)
530  {
531  Callback<R, std::tuple_element_t<sizeof...(bargs) + INDEX, std::tuple<UArgs...>>...> cb;
532 
533  const auto f = DoPeekImpl()->GetFunction();
534 
535  CallbackComponentVector components(DoPeekImpl()->GetComponents());
536  components.insert(components.end(),
537  {std::make_shared<CallbackComponent<std::decay_t<BoundArgs>>>(bargs)...});
538 
539  cb.m_impl = Create<std::remove_pointer_t<decltype(cb.DoPeekImpl())>>(
540  [f, bargs...](auto&&... uargs) mutable {
541  return f(bargs..., std::forward<decltype(uargs)>(uargs)...);
542  },
543  components);
544 
545  return cb;
546  }
547 
548  public:
556  template <typename... BoundArgs>
557  auto Bind(BoundArgs&&... bargs)
558  {
559  static_assert(sizeof...(UArgs) > 0);
560  return BindImpl(std::make_index_sequence<sizeof...(UArgs) - sizeof...(BoundArgs)>{},
561  std::forward<BoundArgs>(bargs)...);
562  }
563 
569  bool IsNull() const
570  {
571  return (DoPeekImpl() == nullptr);
572  }
573 
575  void Nullify()
576  {
577  m_impl = nullptr;
578  }
579 
586  R operator()(UArgs... uargs) const
587  {
588  return (*(DoPeekImpl()))(uargs...);
589  }
590 
597  bool IsEqual(const CallbackBase& other) const
598  {
599  return m_impl->IsEqual(other.GetImpl());
600  }
601 
608  bool CheckType(const CallbackBase& other) const
609  {
610  return DoCheckType(other.GetImpl());
611  }
612 
619  bool Assign(const CallbackBase& other)
620  {
621  auto otherImpl = other.GetImpl();
622  if (!DoCheckType(otherImpl))
623  {
624  std::string othTid = otherImpl->GetTypeid();
625  std::string myTid = CallbackImpl<R, UArgs...>::DoGetTypeid();
626  NS_FATAL_ERROR_CONT("Incompatible types. (feed to \"c++filt -t\" if needed)"
627  << std::endl
628  << "got=" << othTid << std::endl
629  << "expected=" << myTid);
630  return false;
631  }
632  m_impl = const_cast<CallbackImplBase*>(PeekPointer(otherImpl));
633  return true;
634  }
635 
636  private:
638  CallbackImpl<R, UArgs...>* DoPeekImpl() const
639  {
640  return static_cast<CallbackImpl<R, UArgs...>*>(PeekPointer(m_impl));
641  }
642 
650  {
651  if (other && dynamic_cast<const CallbackImpl<R, UArgs...>*>(PeekPointer(other)) != nullptr)
652  {
653  return true;
654  }
655  else if (!other)
656  {
657  return true;
658  }
659  else
660  {
661  return false;
662  }
663  }
664 };
665 
676 template <typename R, typename... Args>
677 bool
679 {
680  return !a.IsEqual(b);
681 }
682 
702 template <typename T, typename OBJ, typename R, typename... Args>
703 Callback<R, Args...>
704 MakeCallback(R (T::*memPtr)(Args...), OBJ objPtr)
705 {
706  return Callback<R, Args...>(memPtr, objPtr);
707 }
708 
709 template <typename T, typename OBJ, typename R, typename... Args>
710 Callback<R, Args...>
711 MakeCallback(R (T::*memPtr)(Args...) const, OBJ objPtr)
712 {
713  return Callback<R, Args...>(memPtr, objPtr);
714 }
715 
728 template <typename R, typename... Args>
729 Callback<R, Args...>
730 MakeCallback(R (*fnPtr)(Args...))
731 {
732  return Callback<R, Args...>(fnPtr);
733 }
734 
745 template <typename R, typename... Args>
746 Callback<R, Args...>
748 {
749  return Callback<R, Args...>();
750 }
751 
763 template <typename R, typename... Args, typename... BArgs>
764 auto
765 MakeBoundCallback(R (*fnPtr)(Args...), BArgs&&... bargs)
766 {
767  return Callback<R, Args...>(fnPtr).Bind(std::forward<BArgs>(bargs)...);
768 }
769 
784 template <typename T, typename OBJ, typename R, typename... Args, typename... BArgs>
785 auto
786 MakeCallback(R (T::*memPtr)(Args...), OBJ objPtr, BArgs... bargs)
787 {
788  return Callback<R, Args...>(memPtr, objPtr).Bind(bargs...);
789 }
790 
791 template <typename T, typename OBJ, typename R, typename... Args, typename... BArgs>
792 auto
793 MakeCallback(R (T::*memPtr)(Args...) const, OBJ objPtr, BArgs... bargs)
794 {
795  return Callback<R, Args...>(memPtr, objPtr).Bind(bargs...);
796 }
797 
800 } // namespace ns3
801 
802 namespace ns3
803 {
804 
806 {
807  public:
809  CallbackValue();
814  CallbackValue(const CallbackBase& base);
816  ~CallbackValue() override;
818  void Set(CallbackBase base);
819  /* Documented by print-introspected-doxygen.cc */
820  template <typename T>
821  bool GetAccessor(T& value) const;
823  Ptr<AttributeValue> Copy() const override;
829  std::string SerializeToString(Ptr<const AttributeChecker> checker) const override;
837  bool DeserializeFromString(std::string value, Ptr<const AttributeChecker> checker) override;
838 
839  private:
840  /* Documented by print-introspected-doxygen.cc */
842 };
843 
846 
847 } // namespace ns3
848 
849 namespace ns3
850 {
851 
852 template <typename T>
853 bool
855 {
856  if (value.CheckType(m_value))
857  {
858  if (!value.Assign(m_value))
859  {
861  }
862  return true;
863  }
864  return false;
865 }
866 
867 } // namespace ns3
868 
869 #endif /* CALLBACK_H */
double f(double x, void *params)
Definition: 80211b.c:70
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:360
CallbackBase(Ptr< CallbackImplBase > impl)
Construct from a pimpl.
Definition: callback.h:378
Ptr< CallbackImplBase > GetImpl() const
Definition: callback.h:368
Ptr< CallbackImplBase > m_impl
the pimpl
Definition: callback.h:383
bool IsEqual(std::shared_ptr< const CallbackComponentBase > other) const override
Equality test between functions.
Definition: callback.h:224
CallbackComponent(const T &t)
Constructor.
Definition: callback.h:214
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:191
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:438
Callback(const Ptr< CallbackImpl< R, UArgs... >> &impl)
Construct from a CallbackImpl pointer.
Definition: callback.h:452
bool IsEqual(const CallbackBase &other) const
Equality test.
Definition: callback.h:597
bool DoCheckType(Ptr< const CallbackImplBase > other) const
Check for compatible types.
Definition: callback.h:649
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:575
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
R operator()(UArgs... uargs) const
Functor with varying numbers of arguments.
Definition: callback.h:586
auto Bind(BoundArgs &&... bargs)
Bind a variable number of arguments.
Definition: callback.h:557
auto BindImpl(std::index_sequence< INDEX... > seq, BoundArgs &&... bargs)
Implementation of the Bind method.
Definition: callback.h:529
Callback(T func, BArgs... bargs)
Construct from a function and bind some arguments (if any)
Definition: callback.h:495
Callback(const Callback< R, BArgs..., UArgs... > &cb, BArgs... bargs)
Construct from another callback and bind some arguments (if any)
Definition: callback.h:465
CallbackImpl< R, UArgs... > * DoPeekImpl() const
Definition: callback.h:638
bool CheckType(const CallbackBase &other) const
Check for compatible types.
Definition: callback.h:608
bool Assign(const CallbackBase &other)
Adopt the other's implementation, if type compatible.
Definition: callback.h:619
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:242
std::vector< std::shared_ptr< CallbackComponentBase > > m_components
Stores the original callable object and the bound arguments, if any.
Definition: callback.h:351
std::function< R(UArgs...)> m_func
Stores the callable object associated with this callback (as a lambda)
Definition: callback.h:348
R operator()(UArgs... uargs) const
Function call operator.
Definition: callback.h:280
static std::string DoGetTypeid()
Get the name of this object type.
Definition: callback.h:328
const CallbackComponentVector & GetComponents() const
Get the vector of callback components.
Definition: callback.h:269
const std::function< R(UArgs...)> & GetFunction() const
Get the stored function.
Definition: callback.h:260
CallbackImpl(std::function< R(UArgs...)> func, const CallbackComponentVector &components)
Constructor.
Definition: callback.h:250
std::string GetTypeid() const override
Get the name of this object type.
Definition: callback.h:322
bool IsEqual(Ptr< const CallbackImplBase > other) const override
Equality test.
Definition: callback.h:285
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
Definition: callback.h:854
CallbackBase m_value
Definition: callback.h:841
Ptr< AttributeValue > Copy() const override
Definition: callback.cc:60
~CallbackValue() override
Destructor.
Definition: callback.cc:46
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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:747
#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:765
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition: ptr.h:442
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:678
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:704
std::vector< std::shared_ptr< CallbackComponentBase > > CallbackComponentVector
Vector of callback components.
Definition: callback.h:231
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:449
ns3::Ptr smart pointer declaration and implementation.
ns3::SimpleRefCount declaration and template implementation.