A Discrete-Event Network Simulator
API
callback.h
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2005,2006 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 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 * Stefano Avallone <stavallo@unina.it>
20 */
21
22#ifndef CALLBACK_H
23#define CALLBACK_H
24
25#include "ptr.h"
26#include "fatal-error.h"
27#include "attribute.h"
28#include "attribute-helper.h"
29#include "simple-ref-count.h"
30#include <typeinfo>
31#include <vector>
32#include <functional>
33#include <memory>
34#include <utility>
35
42namespace ns3 {
43
44// Define the doxygen subgroups all at once,
45// since the implementations are interleaved.
46
80class CallbackImplBase : public SimpleRefCount<CallbackImplBase>
81{
82public:
85 {}
92 virtual bool IsEqual (Ptr<const CallbackImplBase> other) const = 0;
97 virtual std::string GetTypeid (void) const = 0;
98
99protected:
104 static std::string Demangle (const std::string& mangled);
111 template <typename T>
112 static std::string GetCppTypeid (void)
113 {
114 std::string typeName;
115 try
116 {
117 typeName = typeid (T).name ();
118 typeName = Demangle (typeName);
119 }
120 catch (const std::bad_typeid &e)
121 {
122 typeName = e.what ();
123 }
124 return typeName;
125 }
126};
127
128
135{
136public:
145 virtual bool IsEqual (std::shared_ptr<const CallbackComponentBase> other) const = 0;
146};
147
157template <typename T, bool isComparable = true>
159{
160public:
166 CallbackComponent (const T& t)
167 : m_comp (t) {}
168
175 bool IsEqual (std::shared_ptr<const CallbackComponentBase> other) const
176 {
177 auto p = std::dynamic_pointer_cast<const CallbackComponent<T>> (other);
178
179 // other must have the same type and value as ours
180 if (p == nullptr || p->m_comp != m_comp)
181 {
182 return false;
183 }
184
185 return true;
186 }
187
188private:
190};
191
192
204template <typename T>
206{
207public:
213 CallbackComponent (const T& t) {}
214
221 bool IsEqual (std::shared_ptr<const CallbackComponentBase> other) const
222 {
223 return false;
224 }
225};
226
228typedef std::vector<std::shared_ptr<CallbackComponentBase>> CallbackComponentVector;
229
237template <typename R, typename... UArgs>
239public:
240
247 CallbackImpl (std::function<R(UArgs...)> func,
248 const CallbackComponentVector& components)
249 : m_func (func), m_components (components)
250 {}
251
256 const std::function<R(UArgs...)>& GetFunction (void) const
257 { return m_func; }
258
264 { return m_components; }
265
272 R operator() (UArgs... uargs) const {
273 return m_func (uargs...);
274 }
275
276 virtual bool IsEqual (Ptr<const CallbackImplBase> other) const
277 {
278 CallbackImpl<R,UArgs...> const *otherDerived =
279 dynamic_cast<CallbackImpl<R,UArgs...> const *> (PeekPointer (other));
280
281 if (otherDerived == 0)
282 {
283 return false;
284 }
285
286 // if the two callback implementations are made of a distinct number of
287 // components, they are different
288 if (m_components.size () != otherDerived->GetComponents ().size ())
289 {
290 return false;
291 }
292
293 // the two functions are equal if they compare equal or the shared pointers
294 // point to the same locations
295 if (!m_components.at (0)->IsEqual (otherDerived->GetComponents ().at (0))
296 && m_components.at (0) != otherDerived->GetComponents ().at (0))
297 {
298 return false;
299 }
300
301 // check if the remaining components are equal one by one
302 for (std::size_t i = 1; i < m_components.size (); i++)
303 {
304 if (!m_components.at (i)->IsEqual (otherDerived->GetComponents ().at (i)))
305 {
306 return false;
307 }
308 }
309
310 return true;
311 }
312
313 virtual std::string GetTypeid (void) const
314 {
315 return DoGetTypeid ();
316 }
318 static std::string DoGetTypeid (void)
319 {
320 static std::vector<std::string> vec = { GetCppTypeid<R> (), GetCppTypeid<UArgs> ()... };
321
322 static std::string id ("CallbackImpl<");
323 for (auto& s : vec)
324 {
325 id.append (s + ",");
326 }
327 if (id.back () == ',')
328 {
329 id.pop_back ();
330 }
331 id.push_back ('>');
332
333 return id;
334 }
335
336private:
338 std::function<R(UArgs...)> m_func;
339
341 std::vector<std::shared_ptr<CallbackComponentBase>> m_components;
342};
343
344
351{
352public:
354 {}
357 {
358 return m_impl;
359 }
360
361protected:
367 {}
369};
370
421template<typename R, typename... UArgs>
422class Callback : public CallbackBase {
423public:
425 {}
426
433 : CallbackBase (impl)
434 {}
435
443 template <typename... BArgs>
444 Callback (const CallbackBase& cb, BArgs... bargs)
445 {
446 auto cbDerived = static_cast<CallbackImpl<R,BArgs...,UArgs...> const *> (PeekPointer (cb.GetImpl ()));
447
448 std::function<R(BArgs...,UArgs...)> f (cbDerived->GetFunction ());
449
450 CallbackComponentVector components (cbDerived->GetComponents ());
451 components.insert (components.end (), { std::make_shared<CallbackComponent<BArgs>> (bargs)... });
452
453 m_impl = Create<CallbackImpl<R,UArgs...>> ([f,bargs...](UArgs... uargs) -> R
454 { return f (bargs..., uargs...); },
455 components);
456 }
457
470 template <typename T,
471 std::enable_if_t<!std::is_base_of_v<CallbackBase,T>,int> = 0,
472 typename... BArgs>
473 Callback (T func, BArgs... bargs)
474 {
475 // store the function in a std::function object
476 std::function<R(BArgs...,UArgs...)> f (func);
477
478 // The original function is comparable if it is a function pointer or
479 // a pointer to a member function or a pointer to a member data.
480 constexpr bool isComp = std::is_function_v<std::remove_pointer_t<T>>
481 || std::is_member_pointer_v<T>;
482
483 CallbackComponentVector components ({ std::make_shared<CallbackComponent<T,isComp>> (func),
484 std::make_shared<CallbackComponent<BArgs>> (bargs)... });
485
486 m_impl = Create<CallbackImpl<R,UArgs...>> ([f,bargs...](UArgs... uargs) -> R
487 { return f (bargs..., uargs...); },
488 components);
489 }
490
491private:
503 template <std::size_t... INDEX, typename... BoundArgs>
504 auto BindImpl (std::index_sequence<INDEX...> seq, BoundArgs... bargs)
505 {
506 return Callback<R, std::tuple_element_t<sizeof...(bargs)+INDEX,std::tuple<UArgs...>>...>
507 (*this, bargs...);
508 }
509
510public:
511
519 template <typename... BoundArgs>
520 auto Bind (BoundArgs... bargs)
521 {
522 static_assert (sizeof...(UArgs) > 0);
523 return BindImpl (std::make_index_sequence<sizeof...(UArgs) - sizeof...(BoundArgs)>{},
524 std::forward<BoundArgs> (bargs)...);
525 }
526
532 bool IsNull (void) const
533 {
534 return (DoPeekImpl () == 0);
535 }
537 void Nullify (void)
538 {
539 m_impl = 0;
540 }
541
548 R operator() (UArgs... uargs) const {
549 return (*(DoPeekImpl ()))(uargs...);
550 }
551
558 bool IsEqual (const CallbackBase &other) const
559 {
560 return m_impl->IsEqual (other.GetImpl ());
561 }
562
569 bool CheckType (const CallbackBase & other) const
570 {
571 return DoCheckType (other.GetImpl ());
572 }
579 bool Assign (const CallbackBase &other)
580 {
581 auto otherImpl = other.GetImpl ();
582 if (!DoCheckType (otherImpl))
583 {
584 std::string othTid = otherImpl->GetTypeid ();
585 std::string myTid = CallbackImpl<R,UArgs...>::DoGetTypeid ();
586 NS_FATAL_ERROR_CONT ("Incompatible types. (feed to \"c++filt -t\" if needed)" << std::endl <<
587 "got=" << othTid << std::endl <<
588 "expected=" << myTid);
589 return false;
590 }
591 m_impl = const_cast<CallbackImplBase *> (PeekPointer (otherImpl));
592 return true;
593 }
594
595private:
597 CallbackImpl<R,UArgs...> *DoPeekImpl (void) const {
598 return static_cast<CallbackImpl<R,UArgs...> *> (PeekPointer (m_impl));
599 }
607 {
608 if (other &&
609 dynamic_cast<const CallbackImpl<R,UArgs...> *> (PeekPointer (other)) != 0)
610 {
611 return true;
612 }
613 else if (!other)
614 {
615 return true;
616 }
617 else
618 {
619 return false;
620 }
621 }
622};
623
624
635template <typename R, typename... Args>
637{
638 return !a.IsEqual (b);
639}
640
660template <typename T, typename OBJ, typename R, typename... Args>
661Callback<R,Args...> MakeCallback (R (T::*memPtr)(Args...), OBJ objPtr) {
662 return Callback<R,Args...> (memPtr, objPtr);
663}
664
665template <typename T, typename OBJ, typename R, typename... Args>
666Callback<R,Args...> MakeCallback (R (T::*memPtr)(Args...) const, OBJ objPtr) {
667 return Callback<R,Args...> (memPtr, objPtr);
668}
681template <typename R, typename... Args>
682Callback<R,Args...> MakeCallback (R (*fnPtr)(Args...)) {
683 return Callback<R,Args...> (fnPtr);
684}
685
696template <typename R, typename... Args>
697Callback<R,Args...> MakeNullCallback (void) {
698 return Callback<R,Args...> ();
699}
700
701
713template <typename R, typename... Args, typename... BArgs>
714auto MakeBoundCallback (R (*fnPtr)(Args...), BArgs... bargs)
715{
716 return Callback<R,Args...> (fnPtr).Bind (bargs...);
717}
718
733template <typename T, typename OBJ, typename R, typename... Args, typename... BArgs>
734auto MakeCallback (R (T::*memPtr)(Args...), OBJ objPtr, BArgs... bargs)
735{
736 return Callback<R,Args...> (memPtr, objPtr).Bind (bargs...);
737}
738
739template <typename T, typename OBJ, typename R, typename... Args, typename... BArgs>
740auto MakeCallback (R (T::*memPtr)(Args...) const, OBJ objPtr, BArgs... bargs)
741{
742 return Callback<R,Args...> (memPtr, objPtr).Bind (bargs...);
743}
746} // namespace ns3
747
748namespace ns3 {
749
751{
752public:
754 CallbackValue ();
759 CallbackValue (const CallbackBase &base);
761 virtual ~CallbackValue ();
763 void Set (CallbackBase base);
764 /* Documented by print-introspected-doxygen.cc */
765 template <typename T>
766 bool GetAccessor (T &value) const;
768 virtual Ptr<AttributeValue> Copy (void) const;
774 virtual std::string SerializeToString (Ptr<const AttributeChecker> checker) const;
782 virtual bool DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker);
783
784private:
785 /* Documented by print-introspected-doxygen.cc */
787};
788
791
792} // namespace ns3
793
794namespace ns3 {
795
796template <typename T>
797bool CallbackValue::GetAccessor (T &value) const
798{
799 if (value.CheckType (m_value))
800 {
801 if (!value.Assign (m_value))
802 {
804 }
805 return true;
806 }
807 return false;
808}
809
810} // namespace ns3
811
812
813#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:69
Base class for Callback class.
Definition: callback.h:351
CallbackBase(Ptr< CallbackImplBase > impl)
Construct from a pimpl.
Definition: callback.h:366
Ptr< CallbackImplBase > GetImpl(void) const
Definition: callback.h:356
Ptr< CallbackImplBase > m_impl
the pimpl
Definition: callback.h:368
CallbackComponent(const T &t)
Constructor.
Definition: callback.h:213
bool IsEqual(std::shared_ptr< const CallbackComponentBase > other) const
Equality test between functions.
Definition: callback.h:221
Abstract base class for CallbackComponent.
Definition: callback.h:135
virtual bool IsEqual(std::shared_ptr< const CallbackComponentBase > other) const =0
Equality test.
virtual ~CallbackComponentBase()
Virtual destructor.
Definition: callback.h:138
Stores a component of a callback, i.e., the callable object or a bound argument.
Definition: callback.h:159
CallbackComponent(const T &t)
Constructor.
Definition: callback.h:166
bool IsEqual(std::shared_ptr< const CallbackComponentBase > other) const
Equality test between the values of two components.
Definition: callback.h:175
T m_comp
the value of the callback component
Definition: callback.h:189
Callback template class.
Definition: callback.h:422
Callback(const CallbackBase &cb, BArgs... bargs)
Construct from another callback and bind some arguments (if any)
Definition: callback.h:444
bool IsEqual(const CallbackBase &other) const
Equality test.
Definition: callback.h:558
auto Bind(BoundArgs... bargs)
Bind a variable number of arguments.
Definition: callback.h:520
bool DoCheckType(Ptr< const CallbackImplBase > other) const
Check for compatible types.
Definition: callback.h:606
CallbackImpl< R, UArgs... > * DoPeekImpl(void) const
Definition: callback.h:597
R operator()(UArgs... uargs) const
Functor with varying numbers of arguments.
Definition: callback.h:548
void Nullify(void)
Discard the implementation, set it to null.
Definition: callback.h:537
Callback(T func, BArgs... bargs)
Construct from a function and bind some arguments (if any)
Definition: callback.h:473
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:532
auto BindImpl(std::index_sequence< INDEX... > seq, BoundArgs... bargs)
Implementation of the Bind method.
Definition: callback.h:504
Callback(Ptr< CallbackImpl< R, UArgs... > > const &impl)
Construct from a CallbackImpl pointer.
Definition: callback.h:432
bool CheckType(const CallbackBase &other) const
Check for compatible types.
Definition: callback.h:569
bool Assign(const CallbackBase &other)
Adopt the other's implementation, if type compatible.
Definition: callback.h:579
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(void)
Helper to get the C++ typeid as a string.
Definition: callback.h:112
virtual ~CallbackImplBase()
Virtual destructor.
Definition: callback.h:84
virtual std::string GetTypeid(void) const =0
Get the name of this object type.
static std::string Demangle(const std::string &mangled)
Definition: callback.cc:134
CallbackImpl class with varying numbers of argument types.
Definition: callback.h:238
std::vector< std::shared_ptr< CallbackComponentBase > > m_components
Stores the original callable object and the bound arguments, if any.
Definition: callback.h:341
const std::function< R(UArgs...)> & GetFunction(void) const
Get the stored function.
Definition: callback.h:256
static std::string DoGetTypeid(void)
Get the name of this object type.
Definition: callback.h:318
std::function< R(UArgs...)> m_func
Stores the callable object associated with this callback (as a lambda)
Definition: callback.h:338
R operator()(UArgs... uargs) const
Function call operator.
Definition: callback.h:272
CallbackImpl(std::function< R(UArgs...)> func, const CallbackComponentVector &components)
Constructor.
Definition: callback.h:247
virtual bool IsEqual(Ptr< const CallbackImplBase > other) const
Equality test.
Definition: callback.h:276
virtual std::string GetTypeid(void) const
Get the name of this object type.
Definition: callback.h:313
const CallbackComponentVector & GetComponents(void) const
Get the vector of callback components.
Definition: callback.h:263
AttributeValue implementation for Callback.
Definition: callback.h:751
virtual std::string SerializeToString(Ptr< const AttributeChecker > checker) const
Serialize to string.
Definition: callback.cc:60
void Set(CallbackBase base)
Definition: callback.cc:47
CallbackValue()
Constructor.
Definition: callback.cc:34
bool GetAccessor(T &value) const
Access the Callback value as type T.
Definition: callback.h:797
virtual Ptr< AttributeValue > Copy(void) const
Definition: callback.cc:54
virtual ~CallbackValue()
Destructor.
Definition: callback.cc:42
virtual bool DeserializeFromString(std::string value, Ptr< const AttributeChecker > checker)
Deserialize from string (not implemented)
Definition: callback.cc:68
CallbackBase m_value
The stored Callback instance.
Definition: callback.h:786
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(void)
Definition: callback.h:697
#define NS_FATAL_ERROR_CONT(msg)
Report a fatal error with a message, deferring termination.
Definition: fatal-error.h:181
#define NS_FATAL_ERROR_NO_MSG()
Report a fatal error and terminate.
Definition: fatal-error.h:128
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:714
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition: ptr.h:483
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:489
bool operator!=(Callback< R, Args... > a, Callback< R, Args... > b)
Inequality test.
Definition: callback.h:636
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:661
std::vector< std::shared_ptr< CallbackComponentBase > > CallbackComponentVector
Vector of callback components.
Definition: callback.h:228
ns3::Ptr smart pointer declaration and implementation.
ns3::SimpleRefCount declaration and template implementation.