传统实现程序命令行的输入一般使用scanf或者getchar系统调用,这样,要求程序实现时要使用一个独立的线程检测用户的输入,这样就涉及到多线程编程的一系列问题。glib的mainloop机制可以提供单线程多事件源的注入,只要我们将用户的输入转换成GSource,就可以实现一种单线程的既可以响应用户输入,同时又能在输入的间隙处理其它事件的类并发模型。
1、基本概念
1.1 GMainContext
1.2 GMainLoop
1.3 GSource
1.4 Poll机制
1.5 File Descriptor
2、实现
2.1 创建一个GMainLoop
loop = g_main_loop_new (NULL, FALSE);
参数说明:
NULL指的是GMainLoop基于的GMainContext,NULL参数表示该mainloop基于glib的default context。
2.2 创建一个GSource
2.2.1 为GSource提供一个回调函数结构体
static gboolean prepare( GSource * source, gint * timeout_ )
{
* timeout_ = -1;
return FALSE;
}
static gboolean check( GSource * source )
{
gboolean _result = FALSE;
if( fd.revents == POLLIN )
{
_result = TRUE;
}
return _result;
}
static gboolean dispatch( GSource * source, GSourceFunc callback, gpointer user_data )
{
gchar _cmd[100] = {0};
read( 0, _cmd, sizeof( _cmd ));
switch( _cmd[0] )
{
case 'h':
printUsage();
break;
case 'p':
break;
case 'x':
g_main_loop_quit (loop);
break;
case '>':
break;
case '<':
break;
default:
break;
}
printf( ">" );
fflush( stdout );
return G_SOURCE_CONTINUE;
}
static GSourceFuncs funcs =
{
.prepare = prepare,
.check = check,
.dispatch = dispatch
};
2.2.2 为GSource提供stdin fd
static GPollFD fd =
{
.fd = 0,
.events = POLLIN,
.revents = 0
};
2.2.3 创建GSource
_source = g_source_new( &funcs, sizeof( GSource ));
g_source_attach( _source, NULL );
2.2.4 为GSource添加stdin fd
g_source_add_poll( _source, &fd );
2.2.5 释放GSource引用
g_source_unref( _source );//一定要做,否则会内存泄漏
2.3 运行GMainLoop
g_main_loop_run (loop);
至此,命令行接口已创建完毕,程序运行后,用户可以通过控制台输入命令。开发者后续可以在mainloop上附加其它的GSource,使这个mainloop可以处理额外的并发事件。