48a49
> #include "base/misc.hh"
55a57
>
64,68c66
< * Memory management is mostly done using reference counting in
< * Python. However, PyBind can't keep track of the reference the event
< * queue holds to a scheduled event. We therefore need to inhibit
< * deletion and hand over ownership to the event queue in case a
< * scheduled event loses all of its Python references.
---
> * Memory management is done using reference counting in Python.
73,87d70
< struct Deleter {
< void operator()(PyEvent *ev) {
< assert(!ev->isAutoDelete());
< if (ev->scheduled()) {
< // The event is scheduled, give ownership to the event
< // queue.
< ev->setFlags(Event::AutoDelete);
< } else {
< // The event isn't scheduled, hence Python owns it and
< // we need to free it here.
< delete ev;
< }
< }
< };
<
89,90c72,74
< : Event(priority)
< { }
---
> : Event(priority, Event::Managed)
> {
> }
93,100d76
< if (isAutoDelete()) {
< // Ownership of the event was handed over to the event queue
< // because the last revference in Python land was GCed. We
< // need to claim the object again since we're creating a new
< // Python reference.
< clearFlags(AutoDelete);
< }
<
104a81,101
>
> protected:
> void acquireImpl() override {
> py::object obj = py::cast(this);
>
> if (obj) {
> obj.inc_ref();
> } else {
> panic("Failed to get PyBind object to increase ref count\n");
> }
> }
>
> void releaseImpl() override {
> py::object obj = py::cast(this);
>
> if (obj) {
> obj.dec_ref();
> } else {
> panic("Failed to get PyBind object to decrease ref count\n");
> }
> }
127,132c124,127
< .def("deschedule", [](EventQueue *eq, PyEvent *e) {
< eq->deschedule(e);
< }, py::arg("event"))
< .def("reschedule", [](EventQueue *eq, PyEvent *e, Tick t, bool alw) {
< eq->reschedule(e, t, alw);
< }, py::arg("event"), py::arg("tick"), py::arg("always") = false)
---
> .def("deschedule", &EventQueue::deschedule,
> py::arg("event"))
> .def("reschedule", &EventQueue::reschedule,
> py::arg("event"), py::arg("tick"), py::arg("always") = false)
137c132
< // word. This is what the old SWIG code did, but that will result
---
> // world. This is what the old SWIG code did, but that will result
146,150c141,145
< // TODO: We currently export a wrapper class and not the Event
< // base class. This wil be problematic if we ever return an event
< // from C++.
< py::class_<PyEvent, std::unique_ptr<PyEvent, PyEvent::Deleter>>
< c_event(m, "Event");
---
> // Event base class. These should never be returned directly to
> // Python since they don't have a well-defined life cycle. Python
> // events should be derived from PyEvent instead.
> py::class_<Event> c_event(
> m, "Event");
152,153d146
< .def(py::init<Event::Priority>(),
< py::arg("priority") = (int)Event::Default_Pri)
160d152
< .def("isAutoDelete", &Event::isAutoDelete)
164a157,161
> py::class_<PyEvent, Event>(m, "PyEvent")
> .def(py::init<Event::Priority>(),
> py::arg("priority") = (int)Event::Default_Pri)
> ;
>