core: Use std::function to implement callbacks

This commit is contained in:
Stefano Avallone
2018-11-14 10:51:57 +01:00
committed by Stefano Avallone
parent b2cd3d7264
commit 3e20515664
8 changed files with 526 additions and 1525 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -45,7 +45,7 @@ namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("FdReader");
FdReader::FdReader ()
: m_fd (-1), m_readCallback (0), m_stop (false),
: m_fd (-1), m_stop (false),
m_destroyEvent ()
{
NS_LOG_FUNCTION (this);

View File

@@ -98,6 +98,7 @@ private:
static bool gBasicCallbackTest5;
static bool gBasicCallbackTest6;
static bool gBasicCallbackTest7;
static bool gBasicCallbackTest8;
/** @} */
/**
@@ -144,6 +145,7 @@ BasicCallbackTestCase::DoSetup (void)
gBasicCallbackTest5 = false;
gBasicCallbackTest6 = false;
gBasicCallbackTest7 = false;
gBasicCallbackTest8 = false;
}
void
@@ -153,7 +155,7 @@ BasicCallbackTestCase::DoRun (void)
// Make sure we can declare and compile a Callback pointing to a member
// function returning void and execute it.
//
Callback<void> target1 (this, &BasicCallbackTestCase::Target1);
Callback<void> target1 (&BasicCallbackTestCase::Target1, this);
target1 ();
NS_TEST_ASSERT_MSG_EQ (m_test1, true, "Callback did not fire");
@@ -162,7 +164,7 @@ BasicCallbackTestCase::DoRun (void)
// function that returns an int and execute it.
//
Callback<int> target2;
target2 = Callback<int> (this, &BasicCallbackTestCase::Target2);
target2 = Callback<int> (&BasicCallbackTestCase::Target2, this);
target2 ();
NS_TEST_ASSERT_MSG_EQ (m_test2, true, "Callback did not fire");
@@ -170,7 +172,7 @@ BasicCallbackTestCase::DoRun (void)
// Make sure we can declare and compile a Callback pointing to a member
// function that returns void, takes a double parameter, and execute it.
//
Callback<void, double> target3 = Callback<void, double> (this, &BasicCallbackTestCase::Target3);
Callback<void, double> target3 = Callback<void, double> (&BasicCallbackTestCase::Target3, this);
target3 (0.0);
NS_TEST_ASSERT_MSG_EQ (m_test3, true, "Callback did not fire");
@@ -178,7 +180,7 @@ BasicCallbackTestCase::DoRun (void)
// Make sure we can declare and compile a Callback pointing to a member
// function that returns void, takes two parameters, and execute it.
//
Callback<int, double, int> target4 = Callback<int, double, int> (this, &BasicCallbackTestCase::Target4);
Callback<int, double, int> target4 = Callback<int, double, int> (&BasicCallbackTestCase::Target4, this);
target4 (0.0, 1);
NS_TEST_ASSERT_MSG_EQ (m_test4, true, "Callback did not fire");
@@ -189,27 +191,32 @@ BasicCallbackTestCase::DoRun (void)
// sure that the constructor is properly disambiguated. If the arguments are
// not needed, we just pass in dummy values.
//
Callback<void> target5 = Callback<void> (&BasicCallbackTarget5, true, true);
Callback<void> target5 = Callback<void> (&BasicCallbackTarget5);
target5 ();
NS_TEST_ASSERT_MSG_EQ (gBasicCallbackTest5, true, "Callback did not fire");
//
// Make sure we can declare and compile a Callback pointing to a non-member
// function that returns void, takes one integer argument and execute it.
// We also need to provide two dummy arguments to the constructor here.
//
Callback<void, int> target6 = Callback<void, int> (&BasicCallbackTarget6, true, true);
Callback<void, int> target6 = Callback<void, int> (&BasicCallbackTarget6);
target6 (1);
NS_TEST_ASSERT_MSG_EQ (gBasicCallbackTest6, true, "Callback did not fire");
//
// Make sure we can declare and compile a Callback pointing to a non-member
// function that returns int, takes one integer argument and execute it.
// We also need to provide two dummy arguments to the constructor here.
//
Callback<int, int> target7 = Callback<int, int> (&BasicCallbackTarget7, true, true);
Callback<int, int> target7 = Callback<int, int> (&BasicCallbackTarget7);
target7 (1);
NS_TEST_ASSERT_MSG_EQ (gBasicCallbackTest7, true, "Callback did not fire");
//
// Make sure we can create a callback pointing to a lambda.
//
Callback<double, int> target8 ([](int p){ gBasicCallbackTest8 = true; return p/2.; });
target8 (5);
NS_TEST_ASSERT_MSG_EQ (gBasicCallbackTest8, true, "Callback did not fire");
}
/**
@@ -403,6 +410,19 @@ public:
virtual ~MakeBoundCallbackTestCase ()
{}
/**
* Member function to test the creation of a bound callback pointing to a member function
*
* \param a first argument
* \param b second argument
* \param c third argument
* \return the sum of the arguments
*/
int BoundTarget (int a, int b, int c)
{
return a+b+c;
}
private:
virtual void DoRun (void);
virtual void DoSetup (void);
@@ -679,6 +699,170 @@ MakeBoundCallbackTestCase::DoRun (void)
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");
//
// Test creating a bound callback pointing to a member function. Also, make sure that
// an argument can be bound to a reference.
//
int b = 1;
Callback<int> target10 = Callback<int> (&MakeBoundCallbackTestCase::BoundTarget, this, std::ref (b), 5, 2);
NS_TEST_ASSERT_MSG_EQ (target10 (), 8, "Bound callback returned an unexpected value");
b = 3;
NS_TEST_ASSERT_MSG_EQ (target10 (), 10, "Bound callback returned an unexpected value");
}
/**
* \ingroup callback-tests
*
* Test the callback equality implementation.
*/
class CallbackEqualityTestCase : public TestCase
{
public:
CallbackEqualityTestCase ();
virtual ~CallbackEqualityTestCase () {}
/**
* Member function used to test equality of callbacks.
*
* \param a first argument
* \param b second argument
* \return the sum of the arguments
*/
int TargetMember (double a, int b)
{
return static_cast<int> (a) + b;
}
private:
virtual void DoRun (void);
virtual void DoSetup (void);
};
/**
* Non-member function used to test equality of callbacks.
*
* \param a first argument
* \param b second argument
* \return the sum of the arguments
*/
int
CallbackEqualityTarget (double a, int b)
{
return static_cast<int> (a) + b;
}
CallbackEqualityTestCase::CallbackEqualityTestCase ()
: TestCase ("Check Callback equality test")
{
}
void
CallbackEqualityTestCase::DoSetup (void)
{
}
void
CallbackEqualityTestCase::DoRun (void)
{
//
// Make sure that two callbacks pointing to the same member function
// compare equal.
//
Callback<int, double, int> target1a (&CallbackEqualityTestCase::TargetMember, this);
Callback<int, double, int> target1b = MakeCallback (&CallbackEqualityTestCase::TargetMember, this);
NS_TEST_ASSERT_MSG_EQ (target1a.IsEqual (target1b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same member function
// compare equal, after binding the first argument.
//
Callback<int, int> target2a (&CallbackEqualityTestCase::TargetMember, this, 1.5);
Callback<int, int> target2b = target1b.Bind (1.5);
NS_TEST_ASSERT_MSG_EQ (target2a.IsEqual (target2b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same member function
// compare equal, after binding the first two arguments.
//
Callback<int> target3a (target2a, 2);
Callback<int> target3b = target1b.Bind (1.5, 2);
NS_TEST_ASSERT_MSG_EQ (target3a.IsEqual (target3b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same member function do
// not compare equal if they are bound to different arguments.
//
Callback<int> target3c = target1b.Bind (1.5, 3);
NS_TEST_ASSERT_MSG_EQ (target3c.IsEqual (target3b), false, "Equality test failed");
//
// Make sure that two callbacks pointing to the same non-member function
// compare equal.
//
Callback<int, double, int> target4a (&CallbackEqualityTarget);
Callback<int, double, int> target4b = MakeCallback (&CallbackEqualityTarget);
NS_TEST_ASSERT_MSG_EQ (target4a.IsEqual (target4b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same non-member function
// compare equal, after binding the first argument.
//
Callback<int, int> target5a (&CallbackEqualityTarget, 1.5);
Callback<int, int> target5b = target4b.Bind (1.5);
NS_TEST_ASSERT_MSG_EQ (target5a.IsEqual (target5b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same non-member function
// compare equal, after binding the first two arguments.
//
Callback<int> target6a (target5a, 2);
Callback<int> target6b = target4b.Bind (1.5, 2);
NS_TEST_ASSERT_MSG_EQ (target6a.IsEqual (target6b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same non-member function do
// not compare equal if they are bound to different arguments.
//
Callback<int> target6c = target4b.Bind (1.5, 3);
NS_TEST_ASSERT_MSG_EQ (target6c.IsEqual (target6b), false, "Equality test failed");
//
// Check that we cannot compare lambdas.
//
Callback<double, int, double> target7a ([](int p, double d){ return d + p/2.; });
Callback<double, int, double> target7b ([](int p, double d){ return d + p/2.; });
NS_TEST_ASSERT_MSG_EQ (target7a.IsEqual (target7b), false, "Compared lambdas?");
//
// Make sure that a callback pointing to a lambda and a copy of it compare equal.
//
Callback<double, int, double> target7c (target7b);
NS_TEST_ASSERT_MSG_EQ (target7c.IsEqual (target7b), true, "Equality test failed");
//
// Make sure that a callback pointing to a lambda and a copy of it compare equal,
// after binding the first argument.
//
Callback<double, int> target8b = target7b.Bind (1);
Callback<double, int> target8c (target7c, 1);
NS_TEST_ASSERT_MSG_EQ (target8b.IsEqual (target8c), true, "Equality test failed");
//
// Make sure that a callback pointing to a lambda and a copy of it compare equal,
// after binding the first two arguments.
//
Callback<double> target9b = target8b.Bind (2);
Callback<double> target9c (target8c, 2);
NS_TEST_ASSERT_MSG_EQ (target9b.IsEqual (target9c), true, "Equality test failed");
//
// Make sure that a callback pointing to a lambda and a copy of it do not compare
// equal if they are bound to different arguments.
//
Callback<double> target9d = target8b.Bind (4);
NS_TEST_ASSERT_MSG_EQ (target9d.IsEqual (target9c), false, "Equality test failed");
}
/**
@@ -935,6 +1119,7 @@ CallbackTestSuite::CallbackTestSuite ()
AddTestCase (new BasicCallbackTestCase, TestCase::QUICK);
AddTestCase (new MakeCallbackTestCase, TestCase::QUICK);
AddTestCase (new MakeBoundCallbackTestCase, TestCase::QUICK);
AddTestCase (new CallbackEqualityTestCase, TestCase::QUICK);
AddTestCase (new NullifyCallbackTestCase, TestCase::QUICK);
AddTestCase (new MakeCallbackTemplatesTestCase, TestCase::QUICK);
}

View File

@@ -53,13 +53,8 @@ private:
* \param b Second parameter.
*/
void CbOne (uint8_t a, double b);
/**
* Second callback.
* \param a First parameter.
* \param b Second parameter.
*/
void CbTwo (uint8_t a, double b);
CallbackBase m_cbTwo; //!< second callback
bool m_one; //!< Variable set by the first callback.
bool m_two; //!< Variable set by the second callback.
};
@@ -74,15 +69,18 @@ BasicTracedCallbackTestCase::CbOne ([[maybe_unused]] uint8_t a, [[maybe_unused]]
m_one = true;
}
void
BasicTracedCallbackTestCase::CbTwo ([[maybe_unused]] uint8_t a, [[maybe_unused]] double b)
{
m_two = true;
}
void
BasicTracedCallbackTestCase::DoRun (void)
{
//
// Disconnecting callbacks from a traced callback is based on the ability to
// compare callbacks. Given that lambdas cannot be compared, a callback
// pointing to a lambda needs to be stored to allow it to be disconnected
// later. Here we check that it is enough to store the callback as a CallbackBase.
//
m_cbTwo = Callback<void, uint8_t, double> ([this](uint8_t, double){ m_two = true; });
//
// Create a traced callback and connect it up to our target methods. All that
// these methods do is to set corresponding member variables m_one and m_two.
@@ -95,7 +93,7 @@ BasicTracedCallbackTestCase::DoRun (void)
// to true.
//
trace.ConnectWithoutContext (MakeCallback (&BasicTracedCallbackTestCase::CbOne, this));
trace.ConnectWithoutContext (MakeCallback (&BasicTracedCallbackTestCase::CbTwo, this));
trace.ConnectWithoutContext (m_cbTwo);
m_one = false;
m_two = false;
trace (1, 2);
@@ -115,7 +113,7 @@ BasicTracedCallbackTestCase::DoRun (void)
//
// If we now disconnect callback two then neither callback should be called.
//
trace.DisconnectWithoutContext (MakeCallback (&BasicTracedCallbackTestCase::CbTwo, this));
trace.DisconnectWithoutContext (m_cbTwo);
m_one = false;
m_two = false;
trace (1, 2);
@@ -126,7 +124,7 @@ BasicTracedCallbackTestCase::DoRun (void)
// If we connect them back up, then both callbacks should be called.
//
trace.ConnectWithoutContext (MakeCallback (&BasicTracedCallbackTestCase::CbOne, this));
trace.ConnectWithoutContext (MakeCallback (&BasicTracedCallbackTestCase::CbTwo, this));
trace.ConnectWithoutContext (m_cbTwo);
m_one = false;
m_two = false;
trace (1, 2);

View File

@@ -324,7 +324,7 @@ IpL4Protocol::DownTargetCallback6
Icmpv4L4Protocol::GetDownTarget6 (void) const
{
NS_LOG_FUNCTION (this);
return (IpL4Protocol::DownTargetCallback6)NULL;
return IpL4Protocol::DownTargetCallback6 ();
}
} // namespace ns3

View File

@@ -1606,7 +1606,7 @@ IpL4Protocol::DownTargetCallback
Icmpv6L4Protocol::GetDownTarget (void) const
{
NS_LOG_FUNCTION (this);
return (IpL4Protocol::DownTargetCallback)NULL;
return IpL4Protocol::DownTargetCallback ();
}
IpL4Protocol::DownTargetCallback6

View File

@@ -22,7 +22,7 @@
#ifndef MATRIX_BASED_CHANNEL_H
#define MATRIX_BASED_CHANNEL_H
#include <complex.h>
// #include <complex>
#include <ns3/object.h>
#include <ns3/nstime.h>
#include <ns3/vector.h>

View File

@@ -474,7 +474,7 @@ WifiPrimaryChannelsTest::DoRun (void)
auto dev = DynamicCast<WifiNetDevice> (m_staDevices[bss].Get (i));
Simulator::Schedule (m_time, &WifiPhy::SetReceiveOkCallback, dev->GetPhy (),
MakeCallback (&WifiPrimaryChannelsTest::ReceiveDl, this)
.TwoBind (bss, i));
.Bind (bss, i));
}
auto dev = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss));
Simulator::Schedule (m_time, &WifiPhy::SetReceiveOkCallback, dev->GetPhy (),