diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 6c7594d32..7ebdc6873 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -28,6 +28,7 @@ Bugs fixed - Bug 1662 - m_type not set for Ipv6OptionRouterAlertHeader - Bug 1678 - C++11 compliance problem with std::pair" - Bug 1683 - IPv6 autoconfigured don't use *infinite* lifetimes +- Bug 1669 - ns-3 should support binding two and three (possibly more) arguments Known issues ------------ diff --git a/src/core/model/callback.h b/src/core/model/callback.h index 6f718f253..08e2f2458 100644 --- a/src/core/model/callback.h +++ b/src/core/model/callback.h @@ -319,6 +319,105 @@ private: typename TypeTraits::ReferencedType m_a; }; +template +class TwoBoundFunctorCallbackImpl : public CallbackImpl { +public: + template + TwoBoundFunctorCallbackImpl (FUNCTOR functor, ARG1 arg1, ARG2 arg2) + : m_functor (functor), m_a1 (arg1), m_a2 (arg2) {} + virtual ~TwoBoundFunctorCallbackImpl () {} + R operator() (void) { + return m_functor (m_a1,m_a2); + } + R operator() (T1 a1) { + return m_functor (m_a1,m_a2,a1); + } + R operator() (T1 a1,T2 a2) { + return m_functor (m_a1,m_a2,a1,a2); + } + R operator() (T1 a1,T2 a2,T3 a3) { + return m_functor (m_a1,m_a2,a1,a2,a3); + } + R operator() (T1 a1,T2 a2,T3 a3,T4 a4) { + return m_functor (m_a1,m_a2,a1,a2,a3,a4); + } + R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) { + return m_functor (m_a1,m_a2,a1,a2,a3,a4,a5); + } + R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) { + return m_functor (m_a1,m_a2,a1,a2,a3,a4,a5,a6); + } + R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7) { + return m_functor (m_a1,m_a2,a1,a2,a3,a4,a5,a6,a7); + } + virtual bool IsEqual (Ptr other) const { + TwoBoundFunctorCallbackImpl const *otherDerived = + dynamic_cast const *> (PeekPointer (other)); + if (otherDerived == 0) + { + return false; + } + else if (otherDerived->m_functor != m_functor || + otherDerived->m_a1 != m_a1 || otherDerived->m_a2 != m_a2) + { + return false; + } + return true; + } +private: + T m_functor; + typename TypeTraits::ReferencedType m_a1; + typename TypeTraits::ReferencedType m_a2; +}; + +template +class ThreeBoundFunctorCallbackImpl : public CallbackImpl { +public: + template + ThreeBoundFunctorCallbackImpl (FUNCTOR functor, ARG1 arg1, ARG2 arg2, ARG3 arg3) + : m_functor (functor), m_a1 (arg1), m_a2 (arg2), m_a3 (arg3) {} + virtual ~ThreeBoundFunctorCallbackImpl () {} + R operator() (void) { + return m_functor (m_a1,m_a2,m_a3); + } + R operator() (T1 a1) { + return m_functor (m_a1,m_a2,m_a3,a1); + } + R operator() (T1 a1,T2 a2) { + return m_functor (m_a1,m_a2,m_a3,a1,a2); + } + R operator() (T1 a1,T2 a2,T3 a3) { + return m_functor (m_a1,m_a2,m_a3,a1,a2,a3); + } + R operator() (T1 a1,T2 a2,T3 a3,T4 a4) { + return m_functor (m_a1,m_a2,m_a3,a1,a2,a3,a4); + } + R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) { + return m_functor (m_a1,m_a2,m_a3,a1,a2,a3,a4,a5); + } + R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) { + return m_functor (m_a1,m_a2,m_a3,a1,a2,a3,a4,a5,a6); + } + virtual bool IsEqual (Ptr other) const { + ThreeBoundFunctorCallbackImpl const *otherDerived = + dynamic_cast const *> (PeekPointer (other)); + if (otherDerived == 0) + { + return false; + } + else if (otherDerived->m_functor != m_functor || + otherDerived->m_a1 != m_a1 || otherDerived->m_a2 != m_a2 || otherDerived->m_a3 != m_a3) + { + return false; + } + return true; + } +private: + T m_functor; + typename TypeTraits::ReferencedType m_a1; + typename TypeTraits::ReferencedType m_a2; + typename TypeTraits::ReferencedType m_a3; +}; class CallbackBase { public: @@ -396,6 +495,26 @@ public: return Callback (impl); } + template + Callback TwoBind (TX1 a1, TX2 a2) { + Ptr > impl = + Ptr > ( + new TwoBoundFunctorCallbackImpl< + Callback, + R,T1,T2,T3,T4,T5,T6,T7,T8,T9> (*this, a1, a2), false); + return Callback (impl); + } + + template + Callback ThreeBind (TX1 a1, TX2 a2, TX3 a3) { + Ptr > impl = + Ptr > ( + new ThreeBoundFunctorCallbackImpl< + Callback, + R,T1,T2,T3,T4,T5,T6,T7,T8,T9> (*this, a1, a2, a3), false); + return Callback (impl); + } + bool IsNull (void) const { return (DoPeekImpl () == 0) ? true : false; } @@ -954,6 +1073,114 @@ Callback MakeBoundCallback (R (*fnPtr)(TX,T1,T2,T3,T4 Create > (fnPtr, a); return Callback (impl); } + +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2), ARG1 a1, ARG2 a2) { + Ptr > impl = + Create >(fnPtr, a1, a2); + return Callback (impl); +} + +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1), ARG1 a1, ARG2 a2) { + Ptr > impl = + Create > (fnPtr, a1, a2); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2), ARG1 a1, ARG2 a2) { + Ptr > impl = + Create > (fnPtr, a1, a2); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2,T3), ARG1 a1, ARG2 a2) { + Ptr > impl = + Create > (fnPtr, a1, a2); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2,T3,T4), ARG1 a1, ARG2 a2) { + Ptr > impl = + Create > (fnPtr, a1, a2); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2,T3,T4,T5), ARG1 a1, ARG2 a2) { + Ptr > impl = + Create > (fnPtr, a1, a2); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2,T3,T4,T5,T6), ARG1 a1, ARG2 a2) { + Ptr > impl = + Create > (fnPtr, a1, a2); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2,T3,T4,T5,T6,T7), ARG1 a1, ARG2 a2) { + Ptr > impl = + Create > (fnPtr, a1, a2); + return Callback (impl); +} + +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3), ARG1 a1, ARG2 a2, ARG3 a3) { + Ptr > impl = + Create >(fnPtr, a1, a2, a3); + return Callback (impl); +} + +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1), ARG1 a1, ARG2 a2, ARG3 a3) { + Ptr > impl = + Create > (fnPtr, a1, a2, a3); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1,T2), ARG1 a1, ARG2 a2, ARG3 a3) { + Ptr > impl = + Create > (fnPtr, a1, a2, a3); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1,T2,T3), ARG1 a1, ARG2 a2, ARG3 a3) { + Ptr > impl = + Create > (fnPtr, a1, a2, a3); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1,T2,T3,T4), ARG1 a1, ARG2 a2, ARG3 a3) { + Ptr > impl = + Create > (fnPtr, a1, a2, a3); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1,T2,T3,T4,T5), ARG1 a1, ARG2 a2, ARG3 a3) { + Ptr > impl = + Create > (fnPtr, a1, a2, a3); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1,T2,T3,T4,T5,T6), ARG1 a1, ARG2 a2, ARG3 a3) { + Ptr > impl = + Create > (fnPtr, a1, a2, a3); + return Callback (impl); +} + } // namespace ns3 namespace ns3 { diff --git a/src/core/test/callback-test-suite.cc b/src/core/test/callback-test-suite.cc index 1e935ee65..af6deb378 100644 --- a/src/core/test/callback-test-suite.cc +++ b/src/core/test/callback-test-suite.cc @@ -300,6 +300,24 @@ static int gMakeBoundCallbackTest1; static bool *gMakeBoundCallbackTest2; static bool *gMakeBoundCallbackTest3a; static int gMakeBoundCallbackTest3b; +static int gMakeBoundCallbackTest4a; +static int gMakeBoundCallbackTest4b; +static int gMakeBoundCallbackTest5a; +static int gMakeBoundCallbackTest5b; +static int gMakeBoundCallbackTest5c; +static int gMakeBoundCallbackTest6a; +static int gMakeBoundCallbackTest6b; +static int gMakeBoundCallbackTest6c; +static int gMakeBoundCallbackTest7a; +static int gMakeBoundCallbackTest7b; +static int gMakeBoundCallbackTest7c; +static int gMakeBoundCallbackTest8a; +static int gMakeBoundCallbackTest8b; +static int gMakeBoundCallbackTest8c; +static int gMakeBoundCallbackTest9a; +static int gMakeBoundCallbackTest9b; +static int gMakeBoundCallbackTest9c; +static int gMakeBoundCallbackTest9d; void MakeBoundCallbackTarget1 (int a) @@ -321,6 +339,57 @@ MakeBoundCallbackTarget3 (bool *a, int b) return 1234; } +void +MakeBoundCallbackTarget4 (int a, int b) +{ + gMakeBoundCallbackTest4a = a; + gMakeBoundCallbackTest4b = b; +} + +int +MakeBoundCallbackTarget5 (int a, int b) +{ + gMakeBoundCallbackTest5a = a; + gMakeBoundCallbackTest5b = b; + return 1234; +} + +int +MakeBoundCallbackTarget6 (int a, int b, int c) +{ + gMakeBoundCallbackTest6a = a; + gMakeBoundCallbackTest6b = b; + gMakeBoundCallbackTest6c = c; + return 1234; +} + +void +MakeBoundCallbackTarget7 (int a, int b, int c) +{ + gMakeBoundCallbackTest7a = a; + gMakeBoundCallbackTest7b = b; + gMakeBoundCallbackTest7c = c; +} + +int +MakeBoundCallbackTarget8 (int a, int b, int c) +{ + gMakeBoundCallbackTest8a = a; + gMakeBoundCallbackTest8b = b; + gMakeBoundCallbackTest8c = c; + return 1234; +} + +int +MakeBoundCallbackTarget9 (int a, int b, int c, int d) +{ + gMakeBoundCallbackTest9a = a; + gMakeBoundCallbackTest9b = b; + gMakeBoundCallbackTest9c = c; + gMakeBoundCallbackTest9d = d; + return 1234; +} + MakeBoundCallbackTestCase::MakeBoundCallbackTestCase () : TestCase ("Check MakeBoundCallback() mechanism") { @@ -333,6 +402,24 @@ MakeBoundCallbackTestCase::DoSetup (void) gMakeBoundCallbackTest2 = 0; gMakeBoundCallbackTest3a = 0; gMakeBoundCallbackTest3b = 0; + gMakeBoundCallbackTest4a = 0; + gMakeBoundCallbackTest4b = 0; + gMakeBoundCallbackTest5a = 0; + gMakeBoundCallbackTest5b = 0; + gMakeBoundCallbackTest5c = 0; + gMakeBoundCallbackTest6a = 0; + gMakeBoundCallbackTest6b = 0; + gMakeBoundCallbackTest6c = 0; + gMakeBoundCallbackTest7a = 0; + gMakeBoundCallbackTest7b = 0; + gMakeBoundCallbackTest7c = 0; + gMakeBoundCallbackTest8a = 0; + gMakeBoundCallbackTest8b = 0; + gMakeBoundCallbackTest8c = 0; + gMakeBoundCallbackTest9a = 0; + gMakeBoundCallbackTest9b = 0; + gMakeBoundCallbackTest9c = 0; + gMakeBoundCallbackTest9d = 0; } void @@ -376,6 +463,51 @@ MakeBoundCallbackTestCase::DoRun (void) NS_TEST_ASSERT_MSG_EQ (result, 1234, "Return value of callback not correct"); NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest3a, &a, "Callback did not fire or binding not correct"); NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest3b, 2468, "Callback did not fire or argument not correct"); + + // + // Test the TwoBound variant + // + Callback target4 = MakeBoundCallback (&MakeBoundCallbackTarget4, 3456, 5678); + target4 (); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest4a, 3456, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest4b, 5678, "Callback did not fire or binding not correct"); + + Callback target5 = MakeBoundCallback (&MakeBoundCallbackTarget5, 3456, 5678); + int resultTwoA = target5 (); + NS_TEST_ASSERT_MSG_EQ (resultTwoA, 1234, "Return value of callback not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest5a, 3456, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest5b, 5678, "Callback did not fire or binding not correct"); + + Callback target6 = MakeBoundCallback (&MakeBoundCallbackTarget6, 3456, 5678); + int resultTwoB = target6 (6789); + NS_TEST_ASSERT_MSG_EQ (resultTwoB, 1234, "Return value of callback not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest6a, 3456, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest6b, 5678, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest6c, 6789, "Callback did not fire or argument not correct"); + + // + // Test the ThreeBound variant + // + Callback target7 = MakeBoundCallback (&MakeBoundCallbackTarget7, 2345, 3456, 4567); + target7 (); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest7a, 2345, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest7b, 3456, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest7c, 4567, "Callback did not fire or binding not correct"); + + Callback target8 = MakeBoundCallback (&MakeBoundCallbackTarget8, 2345, 3456, 4567); + int resultThreeA = target8 (); + NS_TEST_ASSERT_MSG_EQ (resultThreeA, 1234, "Return value of callback not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest8a, 2345, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest8b, 3456, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest8c, 4567, "Callback did not fire or binding not correct"); + + Callback target9 = MakeBoundCallback (&MakeBoundCallbackTarget9, 2345, 3456, 4567); + int resultThreeB = target9 (5678); + NS_TEST_ASSERT_MSG_EQ (resultThreeB, 1234, "Return value of callback not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest9a, 2345, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest9b, 3456, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest9c, 4567, "Callback did not fire or binding not correct"); + NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest9d, 5678, "Callback did not fire or binding not correct"); } // ===========================================================================