From a374c0f03e575c82c58702985ab01dcedc817206 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Tue, 13 Jan 2009 19:27:44 +0000 Subject: [PATCH 1/2] Make Simulator::IsFinished () take into account the stop time. Needed to run custom simulation loops (see bug 375) --- src/simulator/default-simulator-impl.cc | 2 +- src/simulator/realtime-simulator-impl.cc | 2 +- src/simulator/simulator.h | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/simulator/default-simulator-impl.cc b/src/simulator/default-simulator-impl.cc index ec3db6aac..bf3cd2105 100644 --- a/src/simulator/default-simulator-impl.cc +++ b/src/simulator/default-simulator-impl.cc @@ -124,7 +124,7 @@ DefaultSimulatorImpl::ProcessOneEvent (void) bool DefaultSimulatorImpl::IsFinished (void) const { - return m_events->IsEmpty (); + return m_events->IsEmpty () || m_stop; } uint64_t diff --git a/src/simulator/realtime-simulator-impl.cc b/src/simulator/realtime-simulator-impl.cc index 5cc3c10b1..fd26901a2 100644 --- a/src/simulator/realtime-simulator-impl.cc +++ b/src/simulator/realtime-simulator-impl.cc @@ -384,7 +384,7 @@ RealtimeSimulatorImpl::IsFinished (void) const bool rc; { CriticalSection cs (m_mutex); - rc = m_events->IsEmpty (); + rc = m_events->IsEmpty () || m_stop; } return rc; diff --git a/src/simulator/simulator.h b/src/simulator/simulator.h index 11a4a1a9d..d0d66a9c4 100644 --- a/src/simulator/simulator.h +++ b/src/simulator/simulator.h @@ -97,8 +97,9 @@ public: static void Destroy (void); /** - * If there any any events lefts to be scheduled, return - * true. Return false otherwise. + * If there any any events lefts to be scheduled and simulation time + * has not yet reached the "stop time" (see Simulator::Stop()), + * return true. Return false otherwise. */ static bool IsFinished (void); /** From c0ea878ba27e130236de7898d60ce149591909f6 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Tue, 13 Jan 2009 19:28:26 +0000 Subject: [PATCH 2/2] Bug 375: Ctrl-C does not always work when running Python simulations --- bindings/python/ns3_module_simulator.py | 5 -- bindings/python/ns3module_helpers.cc | 47 +++++++++++++++++++ .../ns3modulegen_core_customizations.py | 3 ++ bindings/python/ns3modulescan.py | 4 +- 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/bindings/python/ns3_module_simulator.py b/bindings/python/ns3_module_simulator.py index cc3a38859..da1d6eb39 100644 --- a/bindings/python/ns3_module_simulator.py +++ b/bindings/python/ns3_module_simulator.py @@ -294,11 +294,6 @@ def register_Ns3Simulator_methods(root_module, cls): 'ns3::Time', [], is_static=True) - ## simulator.h: static void ns3::Simulator::Run() [member function] - cls.add_method('Run', - 'void', - [], - is_static=True, unblock_threads=True) ## simulator.h: static void ns3::Simulator::RunOneEvent() [member function] cls.add_method('RunOneEvent', 'void', diff --git a/bindings/python/ns3module_helpers.cc b/bindings/python/ns3module_helpers.cc index fb0a6983f..85d0884c9 100644 --- a/bindings/python/ns3module_helpers.cc +++ b/bindings/python/ns3module_helpers.cc @@ -279,3 +279,50 @@ _wrap_CommandLine_AddValue(PyNs3CommandLine *self, PyObject *args, PyObject *kwa return Py_None; } + +PyObject * +_wrap_Simulator_Run(PyNs3Simulator *PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs, + PyObject **return_exception) +{ + const char *keywords[] = {"signal_check_frequency", NULL}; + int signal_check_frequency = 100; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "|i", (char **) keywords, &signal_check_frequency)) { + PyObject *exc_type, *traceback; + PyErr_Fetch(&exc_type, return_exception, &traceback); + Py_XDECREF(exc_type); + Py_XDECREF(traceback); + return NULL; + } + + PyThreadState *py_thread_state = NULL; + + if (signal_check_frequency == -1) + { + if (PyEval_ThreadsInitialized ()) + py_thread_state = PyEval_SaveThread(); + ns3::Simulator::Run(); + if (py_thread_state) + PyEval_RestoreThread(py_thread_state); + } else { + while (!ns3::Simulator::IsFinished()) + { + if (PyEval_ThreadsInitialized()) + py_thread_state = PyEval_SaveThread(); + + for (int n = signal_check_frequency; n > 0 && !ns3::Simulator::IsFinished(); --n) + { + ns3::Simulator::RunOneEvent(); + } + + if (py_thread_state) + PyEval_RestoreThread(py_thread_state); + PyErr_CheckSignals(); + if (PyErr_Occurred()) + return NULL; + } + } + Py_INCREF(Py_None); + return Py_None; +} + diff --git a/bindings/python/ns3modulegen_core_customizations.py b/bindings/python/ns3modulegen_core_customizations.py index f984617c5..d89c525b0 100644 --- a/bindings/python/ns3modulegen_core_customizations.py +++ b/bindings/python/ns3modulegen_core_customizations.py @@ -287,6 +287,9 @@ def Simulator_customizations(module): Simulator.add_custom_method_wrapper("ScheduleDestroy", "_wrap_Simulator_ScheduleDestroy", flags=["METH_VARARGS", "METH_KEYWORDS", "METH_STATIC"]) + Simulator.add_custom_method_wrapper("Run", "_wrap_Simulator_Run", + flags=["METH_VARARGS", "METH_KEYWORDS", "METH_STATIC"]) + def CommandLine_customizations(module): CommandLine = module['ns3::CommandLine'] diff --git a/bindings/python/ns3modulescan.py b/bindings/python/ns3modulescan.py index 9e1eba6cc..8a3a3850a 100644 --- a/bindings/python/ns3modulescan.py +++ b/bindings/python/ns3modulescan.py @@ -150,11 +150,11 @@ def pre_scan_hook(dummy_module_parser, and pygccxml_definition.name.startswith('Schedule'): global_annotations['ignore'] = None - # unblock python threads for Simulator::Run + # manually wrapped if isinstance(pygccxml_definition, member_function_t) \ and pygccxml_definition.parent.name == 'Simulator' \ and pygccxml_definition.name == 'Run': - global_annotations['unblock_threads'] = True + global_annotations['ignore'] = True ## classes