@@ -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-
188148PYBIND11_MAKE_OPAQUE (std::map<std::pair<uint64_t , std::string>, Edge>)
189149PYBIND11_MAKE_OPAQUE(std::map<std::string, Attribute>)
190150
151+
152+ static QCoreApplication *app = nullptr;
153+
191154PYBIND11_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;
0 commit comments