A Discrete-Event Network Simulator
API
threaded-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 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 * Author: Claudio Freire <claudio-daniel.freire@inria.fr>
18 */
19#include "ns3/calendar-scheduler.h"
20#include "ns3/config.h"
21#include "ns3/heap-scheduler.h"
22#include "ns3/list-scheduler.h"
23#include "ns3/map-scheduler.h"
24#include "ns3/simulator.h"
25#include "ns3/string.h"
26#include "ns3/test.h"
27
28#include <chrono> // seconds, milliseconds
29#include <ctime>
30#include <list>
31#include <thread> // sleep_for
32#include <utility>
33
34using namespace ns3;
35
37constexpr int MAXTHREADS = 64;
38
57{
58 public:
67 const std::string& simulatorType,
68 unsigned int threads);
73 void EventA(int a);
78 void EventB(int b);
83 void EventC(int c);
88 void EventD(int d);
93 void DoNothing(unsigned int threadno);
98 static void SchedulingThread(std::pair<ThreadedSimulatorEventsTestCase*, unsigned int> context);
102 void End();
103 uint64_t m_a;
104 uint64_t m_b;
105 uint64_t m_c;
106 uint64_t m_d;
107 unsigned int m_threads;
109 bool m_stop;
111 std::string m_simulatorType;
112 std::string m_error;
113 std::list<std::thread> m_threadlist;
114
115 private:
116 void DoSetup() override;
117 void DoRun() override;
118 void DoTeardown() override;
119};
120
122 const std::string& simulatorType,
123 unsigned int threads)
124 : TestCase("Check threaded event handling with " + std::to_string(threads) + " threads, " +
125 schedulerFactory.GetTypeId().GetName() + " scheduler, in " + simulatorType),
126 m_threads(threads),
127 m_schedulerFactory(schedulerFactory),
128 m_simulatorType(simulatorType)
129{
130}
131
132void
134{
135 m_stop = true;
136 for (auto& thread : m_threadlist)
137 {
138 if (thread.joinable())
139 {
140 thread.join();
141 }
142 }
143}
144
145void
147 std::pair<ThreadedSimulatorEventsTestCase*, unsigned int> context)
148{
149 ThreadedSimulatorEventsTestCase* me = context.first;
150 unsigned int threadno = context.second;
151
152 while (!me->m_stop)
153 {
154 me->m_threadWaiting[threadno] = true;
155 Simulator::ScheduleWithContext(threadno,
156 MicroSeconds(1),
158 me,
159 threadno);
160 while (!me->m_stop && me->m_threadWaiting[threadno])
161 {
162 std::this_thread::sleep_for(std::chrono::nanoseconds(500));
163 }
164 }
165}
166
167void
169{
170 if (!m_error.empty())
171 {
172 m_error = "Bad threaded scheduling";
173 }
174 m_threadWaiting[threadno] = false;
175}
176
177void
179{
180 if (m_a != m_b || m_a != m_c || m_a != m_d)
181 {
182 m_error = "Bad scheduling";
183 Simulator::Stop();
184 }
185 ++m_a;
186 Simulator::Schedule(MicroSeconds(10), &ThreadedSimulatorEventsTestCase::EventB, this, a + 1);
187}
188
189void
191{
192 if (m_a != (m_b + 1) || m_a != (m_c + 1) || m_a != (m_d + 1))
193 {
194 m_error = "Bad scheduling";
195 Simulator::Stop();
196 }
197 ++m_b;
198 Simulator::Schedule(MicroSeconds(10), &ThreadedSimulatorEventsTestCase::EventC, this, b + 1);
199}
200
201void
203{
204 if (m_a != m_b || m_a != (m_c + 1) || m_a != (m_d + 1))
205 {
206 m_error = "Bad scheduling";
207 Simulator::Stop();
208 }
209 ++m_c;
210 Simulator::Schedule(MicroSeconds(10), &ThreadedSimulatorEventsTestCase::EventD, this, c + 1);
211}
212
213void
215{
216 if (m_a != m_b || m_a != m_c || m_a != (m_d + 1))
217 {
218 m_error = "Bad scheduling";
219 Simulator::Stop();
220 }
221 ++m_d;
222 if (m_stop)
223 {
224 Simulator::Stop();
225 }
226 else
227 {
228 Simulator::Schedule(MicroSeconds(10),
230 this,
231 d + 1);
232 }
233}
234
235void
237{
238 if (!m_simulatorType.empty())
239 {
240 Config::SetGlobal("SimulatorImplementationType", StringValue(m_simulatorType));
241 }
242
243 m_error = "";
244
245 m_a = m_b = m_c = m_d = 0;
246}
247
248void
250{
251 m_threadlist.clear();
252
253 Config::SetGlobal("SimulatorImplementationType", StringValue("ns3::DefaultSimulatorImpl"));
254}
255
256void
258{
259 m_stop = false;
260 Simulator::SetScheduler(m_schedulerFactory);
261
262 Simulator::Schedule(MicroSeconds(10), &ThreadedSimulatorEventsTestCase::EventA, this, 1);
263 Simulator::Schedule(Seconds(1), &ThreadedSimulatorEventsTestCase::End, this);
264
265 for (unsigned int i = 0; i < m_threads; ++i)
266 {
267 m_threadlist.emplace_back(
269 std::pair<ThreadedSimulatorEventsTestCase*, unsigned int>(this, i));
270 }
271
272 Simulator::Run();
273 Simulator::Destroy();
274
275 NS_TEST_EXPECT_MSG_EQ(m_error.empty(), true, m_error);
276 NS_TEST_EXPECT_MSG_EQ(m_a, m_b, "Bad scheduling");
277 NS_TEST_EXPECT_MSG_EQ(m_a, m_c, "Bad scheduling");
278 NS_TEST_EXPECT_MSG_EQ(m_a, m_d, "Bad scheduling");
279}
280
287{
288 public:
290 : TestSuite("threaded-simulator")
291 {
292 std::string simulatorTypes[] = {"ns3::RealtimeSimulatorImpl", "ns3::DefaultSimulatorImpl"};
293 std::string schedulerTypes[] = {"ns3::ListScheduler",
294 "ns3::HeapScheduler",
295 "ns3::MapScheduler",
296 "ns3::CalendarScheduler"};
297 unsigned int threadCounts[] = {0, 2, 10, 20};
298 ObjectFactory factory;
299
300 for (auto& simulatorType : simulatorTypes)
301 {
302 for (auto& schedulerType : schedulerTypes)
303 {
304 for (auto& threadCount : threadCounts)
305 {
306 factory.SetTypeId(schedulerType);
308 new ThreadedSimulatorEventsTestCase(factory, simulatorType, threadCount),
309 TestCase::QUICK);
310 }
311 }
312 }
313 }
314};
315
Check threaded event handling with various thread number, schedulers, and simulator types.
std::list< std::thread > m_threadlist
Thread list.
static void SchedulingThread(std::pair< ThreadedSimulatorEventsTestCase *, unsigned int > context)
Schedule a thread.
ThreadedSimulatorEventsTestCase(ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads)
Constructor.
ObjectFactory m_schedulerFactory
Scheduler factory.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
bool m_threadWaiting[MAXTHREADS]
Threads waiting to be scheduled.
std::string m_error
Error condition.
uint64_t m_c
The value incremented when EventC is called.
uint64_t m_b
The value incremented when EventB is called.
std::string m_simulatorType
Simulator type.
uint64_t m_d
The value incremented when EventD is called.
void End()
End the thread execution.
void DoRun() override
Implementation to actually run this TestCase.
unsigned int m_threads
The number of threads.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint64_t m_a
The value incremented when EventA is called.
void DoNothing(unsigned int threadno)
No-op function, records the thread that called it.
The threaded simulator Test Suite.
Instantiate subclasses of ns3::Object.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
Hold variables of type string.
Definition: string.h:42
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
void SetGlobal(std::string name, const AttributeValue &value)
Definition: config.cc:937
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:251
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Every class exported by the ns3 library is enclosed in the ns3 namespace.
STL namespace.
constexpr int MAXTHREADS
Maximum number of threads.
static ThreadedSimulatorTestSuite g_threadedSimulatorTestSuite
Static variable for test initialization.