Skip to content

Commit 1df6dc3

Browse files
committed
fix: new python signal connect
1 parent ec139f7 commit 1df6dc3

2 files changed

Lines changed: 53 additions & 95 deletions

File tree

python-wrapper/python_api.cpp

Lines changed: 48 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -145,49 +145,12 @@ ValType convert_variant(const attribute_type & e)
145145
return cast[idx](e);
146146
}
147147

148-
class signal_forwarder {
149-
150-
std::mutex mtx;
151-
std::queue<std::function<void()>> fns;
152-
153-
public:
154-
bool exit = false;
155-
std::condition_variable cv;
156-
157-
void put(std::function<void()> && fn) {
158-
std::unique_lock l(mtx);
159-
fns.emplace(std::forward<decltype(fn)>(fn));
160-
cv.notify_all();
161-
}
162-
163-
void run() {
164-
std::function<void()> f;
165-
if (!fns.empty())
166-
{
167-
{
168-
std::unique_lock l(mtx);
169-
f = std::move(fns.front());
170-
fns.pop();
171-
}
172-
// run after lock release because f() will take the gil and weird things can happen with the main thread.
173-
f();
174-
}
175-
}
176-
177-
bool empty() {
178-
return fns.empty();
179-
}
180-
181-
void wait() {
182-
std::unique_lock l(mtx);
183-
cv.wait(l, [this]{ return !fns.empty() || exit; });
184-
}
185-
186-
};
187-
188148
PYBIND11_MAKE_OPAQUE(std::map<std::pair<uint64_t, std::string>, Edge>)
189149
PYBIND11_MAKE_OPAQUE(std::map<std::string, Attribute>)
190150

151+
152+
static QCoreApplication *app = nullptr;
153+
191154
PYBIND11_MODULE(pydsr, m) {
192155
py::bind_map<std::map<std::pair<uint64_t, std::string>, Edge>>(m, "MapStringEdge");
193156
py::bind_dsr_map<std::map<std::string, Attribute>>(m, "MapStringAttribute");
@@ -196,24 +159,31 @@ PYBIND11_MODULE(pydsr, m) {
196159

197160
uint64_t local_agent_id = -1;
198161

199-
200-
static signal_forwarder recv;
201-
static std::thread signal_thread ([&] {
202-
while(true) {
203-
recv.wait();
204-
if (recv.exit) break;
205-
recv.run();
206-
}
162+
std::thread signal_thread ([] {
163+
int argc = 0;
164+
char *argv[] = {nullptr};
165+
auto *QApp = new QCoreApplication(argc, argv);
166+
app = QApp;
167+
QApp->exec();
207168
});
208169

209-
auto cleanup_callback = []() {
210-
recv.exit = true;
211-
recv.cv.notify_all();
212-
signal_thread.join();
213-
};
170+
signal_thread.detach();
214171

215-
m.add_object("_cleanup", py::capsule(cleanup_callback));
172+
// ugly busy wait until the QApp thread is running.
173+
while (app != nullptr){}
216174

175+
py::module::import("atexit").attr("register")(
176+
py::cpp_function{
177+
[&]() -> void {
178+
if (app) {
179+
QCoreApplication::quit();
180+
//app->quit();
181+
//signal_thread.join();
182+
std::exit(0);
183+
}
184+
}
185+
}
186+
);
217187

218188
//Disable messages from Qt.
219189
qInstallMessageHandler([](QtMsgType type, const QMessageLogContext &context, const QString &msg) {
@@ -367,11 +337,9 @@ PYBIND11_MODULE(pydsr, m) {
367337
switch (type) {
368338
case UPDATE_NODE:
369339
try {
370-
QObject::connect(G, &DSR::DSRGraph::update_node_signal,
371-
[fn_callback = std::get<std::function<void(std::uint64_t, const std::string &)>>(fn_callback)]
372-
(auto a, auto b) {
373-
recv.put([a, b, fn_callback] { fn_callback(a, b); });
374-
});
340+
QObject::connect(G, &DSR::DSRGraph::update_node_signal, app,
341+
std::get<std::function<void(std::uint64_t, const std::string &)>>(fn_callback),
342+
Qt::QueuedConnection);
375343

376344
} catch (std::exception &e) {
377345
std::cout << "Update Node Callback must be (int, str)\n " << std::endl;
@@ -380,11 +348,9 @@ PYBIND11_MODULE(pydsr, m) {
380348
break;
381349
case UPDATE_NODE_ATTR:
382350
try {
383-
QObject::connect(G, &DSR::DSRGraph::update_node_attr_signal,
384-
[fn_callback = std::get<std::function<void(std::uint64_t, const std::vector<std::string> &)>>(fn_callback)]
385-
(auto a, auto b) {
386-
recv.put([a, b, fn_callback] { fn_callback(a, b); });
387-
});
351+
QObject::connect(G, &DSR::DSRGraph::update_node_attr_signal, app,
352+
std::get<std::function<void(std::uint64_t, const std::vector<std::string> &)>>(fn_callback),
353+
Qt::QueuedConnection);
388354

389355
} catch (std::exception &e) {
390356
std::cout << "Update Node Attribute Callback must be (int, [str])\n " << std::endl;
@@ -393,71 +359,59 @@ PYBIND11_MODULE(pydsr, m) {
393359
break;
394360
case UPDATE_EDGE:
395361
try {
396-
QObject::connect(G, &DSR::DSRGraph::update_edge_signal,
397-
[fn_callback = std::get<std::function<void(std::uint64_t, std::uint64_t, const std::string &)>>(fn_callback)]
398-
(auto a, auto b, auto c) {
399-
recv.put([a, b, c, fn_callback] { fn_callback(a, b, c); });
400-
});
362+
QObject::connect(G, &DSR::DSRGraph::update_edge_signal, app,
363+
std::get<std::function<void(std::uint64_t, std::uint64_t, const std::string &)>>(fn_callback),
364+
Qt::QueuedConnection);
401365
} catch (std::exception &e) {
402366
std::cout << "Update Edge Callback must be (int, int, str)\n " << std::endl;
403367
throw e;
404368
}
405369
break;
406370
case UPDATE_EDGE_ATTR:
407371
try {
408-
QObject::connect(G, &DSR::DSRGraph::update_edge_attr_signal,
409-
[fn_callback = std::get<std::function<void(std::uint64_t, std::uint64_t, const std::string &, const std::vector<std::string> &)>>(fn_callback)]
410-
(auto a, auto b, auto c, auto d) {
411-
recv.put([a, b, c, d, fn_callback] { fn_callback(a, b, c, d); });
412-
});
372+
QObject::connect(G, &DSR::DSRGraph::update_edge_attr_signal, app,
373+
std::get<std::function<void(std::uint64_t, std::uint64_t, const std::string &, const std::vector<std::string> &)>>(fn_callback),
374+
Qt::QueuedConnection);
413375
} catch (std::exception &e) {
414376
std::cout << "Update Edge Attribute Callback must be (int, int, str, [str])\n " << std::endl;
415377
throw e;
416378
}
417379
break;
418380
case DELETE_EDGE:
419381
try {
420-
QObject::connect(G, &DSR::DSRGraph::del_edge_signal,
421-
[fn_callback = std::get<std::function<void(std::uint64_t, std::uint64_t, const std::string &)>>(fn_callback)]
422-
(std::uint64_t a, std::uint64_t b, const std::string & c) {
423-
recv.put([a, b, c, fn_callback] { fn_callback(a, b, c); });
424-
});
382+
QObject::connect(G, &DSR::DSRGraph::del_edge_signal, app,
383+
std::get<std::function<void(std::uint64_t, std::uint64_t, const std::string &)>>(fn_callback),
384+
Qt::QueuedConnection);
425385
} catch (std::exception &e) {
426386
std::cout << "Delete Edge Callback must be (int, int, str)\n " << std::endl;
427387
throw e;
428388
}
429389
break;
430390
case DELETE_NODE:
431391
try {
432-
QObject::connect(G, &DSR::DSRGraph::del_node_signal,
433-
[fn_callback = std::get<std::function<void(std::uint64_t)>>(fn_callback)]
434-
(auto a) {
435-
recv.put([a,fn_callback] { fn_callback(a); });
436-
});
392+
QObject::connect(G, &DSR::DSRGraph::del_node_signal, app,
393+
std::get<std::function<void(std::uint64_t)>>(fn_callback),
394+
Qt::QueuedConnection);
437395
} catch (std::exception &e) {
438396
std::cout << "Delete Node Callback must be (int)\n " << std::endl;
439397
throw e;
440398
}
441399
break;
442400
case DELETE_NODE_OBJ:
443401
try {
444-
QObject::connect(G, &DSR::DSRGraph::deleted_node_signal,
445-
[fn_callback = std::get<std::function<void(const DSR::Node&)>>(fn_callback)]
446-
(auto a) {
447-
recv.put([a,fn_callback] { fn_callback(a); });
448-
});
402+
QObject::connect(G, &DSR::DSRGraph::deleted_node_signal, app,
403+
std::get<std::function<void(const DSR::Node&)>>(fn_callback),
404+
Qt::QueuedConnection);
449405
} catch (std::exception &e) {
450406
std::cout << "Delete Node Callback must be (pydsr.Node)\n " << std::endl;
451407
throw e;
452408
}
453409
break;
454410
case DELETE_EDGE_OBJ:
455411
try {
456-
QObject::connect(G, &DSR::DSRGraph::deleted_edge_signal,
457-
[fn_callback = std::get<std::function<void(const DSR::Edge&)>>(fn_callback)]
458-
(auto a) {
459-
recv.put([a,fn_callback] { fn_callback(a); });
460-
});
412+
QObject::connect(G, &DSR::DSRGraph::deleted_edge_signal, app,
413+
std::get<std::function<void(const DSR::Edge&)>>(fn_callback),
414+
Qt::QueuedConnection);
461415
} catch (std::exception &e) {
462416
std::cout << "Delete Node Callback must be (pydsr.Edge)\n " << std::endl;
463417
throw e;

python-wrapper/test/TestSignalsQueued.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,8 @@ def deleted_edge_obj(edge: Edge):
120120
console.print("DELETE NODE", style="green")
121121

122122
result = g.delete_node(2)
123-
console.print(result)
123+
console.print(result)
124+
125+
126+
import time
127+
time.sleep(1)

0 commit comments

Comments
 (0)