【发布时间】:2020-02-21 19:40:17
【问题描述】:
我是第一次使用 GLib。因此,为了了解如何使用 GLib API,我编写了以下虚拟程序。
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
g_main_loop_quit(main_loop);
cout << "Stopped main loop from running" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
if (worker_thread.joinable())
{
worker_thread.join();
}
}
void queue_callback(int (*callback)(void))
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)callback, NULL, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
};
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
int main()
{
executor e;
e.queue_callback(func1);
e.queue_callback(func2);
return 0;
}
当我运行程序时,它没有完成执行,它卡住了。这是它打印的输出。
Stopped main loop from running
Starting main loop
func1 started
func1 finished waiting
func2 started
func2 finished waiting
有时它会因以下错误而失败
Stopped main loop from running
Starting main loop
(process:16343): GLib-CRITICAL **: 10:58:54.405: g_main_loop_run: assertion 'g_atomic_int_get (&loop->ref_count) > 0' failed
Finished main loop
我的猜测是这两个问题都在发生,因为 g_main_loop_quit 和 g_main_loop_unref 在 g_main_loop_run 之前运行。如何解决这些问题?
在 user7860670 发表评论后编辑: 感谢 user7860670 的建议。这是现在的工作代码。
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void queue_callback(int (*callback)(void))
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)callback, NULL, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
};
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
int main()
{
executor e;
e.queue_callback(func1);
e.queue_callback(func2);
return 0;
}
【问题讨论】: