概述
简介
在数据类型里面介绍过双端队列,双端队列没有线程和锁的概念,需要调用者自行保证数据同步性,本章要介绍的是异步队列,本身具有多线程同步特性,非常方便使用。
数据结构
异步队列的数据结构不透明,只可以整体使用它,无法单独引用其内部的成员。
typedef struct _GAsyncQueue GAsyncQueue;
函数列表
GAsyncQueue *
g_async_queue_new ()
GAsyncQueue *
g_async_queue_new_full ()
GAsyncQueue *
g_async_queue_ref ()
void
g_async_queue_unref ()
void
g_async_queue_push ()
void
g_async_queue_push_sorted ()
void
g_async_queue_push_front ()
gboolean
g_async_queue_remove ()
gpointer
g_async_queue_pop ()
gpointer
g_async_queue_try_pop ()
gpointer
g_async_queue_timeout_pop ()
gint
g_async_queue_length ()
void
g_async_queue_sort ()
void
g_async_queue_lock ()
void
g_async_queue_unlock ()
void
g_async_queue_ref_unlocked ()
void
g_async_queue_unref_and_unlock ()
void
g_async_queue_push_unlocked ()
void
g_async_queue_push_sorted_unlocked ()
void
g_async_queue_push_front_unlocked ()
gboolean
g_async_queue_remove_unlocked ()
gpointer
g_async_queue_pop_unlocked ()
gpointer
g_async_queue_try_pop_unlocked ()
gpointer
g_async_queue_timeout_pop_unlocked ()
gint
g_async_queue_length_unlocked ()
void
g_async_queue_sort_unlocked ()
gpointer
g_async_queue_timed_pop ()
gpointer
g_async_queue_timed_pop_unlocked ()
函数功能分类
创建
// 最简单的异步队列创建函数
GAsyncQueue *
g_async_queue_new ()
// 带节点释放函数的异步队列创建函数
GAsyncQueue *
g_async_queue_new_full ()
加解锁
// 异步队列的函数大多有两个版本,一个是带锁版本,一个是不带锁版本
// 如果使用的是不带锁版本,需要先对异步队列lock,使其获得锁,才可以调用无锁函数,执行完之后,再解锁
void
g_async_queue_lock ()
void
g_async_queue_unlock ()
入队列
// 最常用的入队列操作函数
void
g_async_queue_push ()
// 将数据入队列到指定位置,此函数要求队列原来就是有序的,执行完入队列操作后,队列仍保持有序
void
g_async_queue_push_sorted ()
// 将数据入队列到队列最开始位置
void
g_async_queue_push_front ()
// 下面三个是入队列的无锁操作函数,和上面三个的作用相同,但需要配合g_async_queue_lock和g_async_queue_unlock使用。
void
g_async_queue_push_unlocked ()
void
g_async_queue_push_sorted_unlocked ()
void
g_async_queue_push_front_unlocked ()
出队列
// 最常用的出队列操作函数
gpointer
g_async_queue_pop ()
// 尝试出队列,此函数不会阻塞,队列中没有数据会立即返回
gpointer
g_async_queue_try_pop ()
// 尝试出队列,阻塞指定时间,超时后返回
gpointer
g_async_queue_timeout_pop ()
// 下面三个是出队列的无锁操作函数,和上面三个的作用相同,但需要配合g_async_queue_lock和g_async_queue_unlock使用。
gpointer
g_async_queue_pop_unlocked ()
gpointer
g_async_queue_try_pop_unlocked ()
gpointer
g_async_queue_timeout_pop_unlocked ()
排序
// 队列内数据排序,有锁和无锁两个版本
void
g_async_queue_sort ()
void
g_async_queue_sort_unlocked ()
测长
// 返回队列长度,有锁和无锁两个版本
gint
g_async_queue_length ()
gint
g_async_queue_length_unlocked ()
移除
// 将一个元素从队列移除,有锁和无锁两个版本
gboolean
g_async_queue_remove ()
gboolean
g_async_queue_remove_unlocked ()
引用解引用
// GLib特有的引用和解引用函数,有锁和无锁两个版本
GAsyncQueue *
g_async_queue_ref ()
void
g_async_queue_unref ()
void
g_async_queue_ref_unlocked ()
void
g_async_queue_unref_and_unlock ()
函数功能说明及综合演示
出队列
g_async_queue_pop函数,如果队列中没有数据,则此接口一直阻塞。
举例验证:push线程延迟2秒向队列发送数据,则pop线程会阻塞2秒,直到队列中有数据。
演示程序见下:
源码见glib_examplesglib_async_queueglib_async_queue_pop
#include <glib.h>
static gpointer test_aqueue_push_func(gpointer data)
{
GAsyncQueue *aqueue = NULL;
g_print("%s n", __FUNCTION__);
g_print("delay 2 seconds to push data n");
g_usleep(2*1000*1000);
aqueue = (GAsyncQueue *)data;
g_async_queue_push(aqueue, GINT_TO_POINTER(99));
return NULL;
}
static gpointer test_aqueue_pop_func(gpointer data)
{
gpointer val = NULL;
GAsyncQueue *aqueue = NULL;
g_print("%s n", __FUNCTION__);
aqueue = (GAsyncQueue *)data;
val = g_async_queue_pop(aqueue);
g_print("val: %d n", GPOINTER_TO_INT(val));
return NULL;
}
gint main(gint argc, gchar **argv)
{
GThread *thd_push, *thd_pop;
GAsyncQueue *aqueue = NULL;
aqueue = g_async_queue_new();
thd_push = g_thread_new("thd_push", test_aqueue_push_func, aqueue);
thd_pop
= g_thread_new("thd_pop", test_aqueue_pop_func, aqueue);
g_thread_join(thd_push);
g_thread_join(thd_pop);
g_async_queue_unref(aqueue);
return 0;
}
运行结果:
[root@centos7_6 build]# ./glib_async_queue_pop
test_aqueue_pop_func
test_aqueue_push_func
delay 2 seconds to push data
val: 99
[root@centos7_6 build]# ./glib_async_queue_pop
test_aqueue_push_func
delay 2 seconds to push data
test_aqueue_pop_func
val: 99
无论是pop线程还是push线程先执行,都是等2秒之后才能取到数据,在这2秒内pop线程阻塞。
异步队列锁
下列函数允许调用者自己处理异步队列的锁。
g_async_queue_lock
g_async_queue_unlock
g_async_queue_push_unlocked
g_async_queue_pop_unlocked
下面举例演示一下上述函数的用法。
源码见glib_examplesglib_async_queueglib_async_queue_locks
#include <glib.h>
static gpointer test_aqueue_push_func(gpointer data)
{
GAsyncQueue *aqueue = NULL;
g_print("%s n", __FUNCTION__);
aqueue = (GAsyncQueue *)data;
g_async_queue_lock(aqueue);
g_async_queue_push_unlocked(aqueue, GINT_TO_POINTER(99));
g_async_queue_unlock(aqueue);
return NULL;
}
static gpointer test_aqueue_pop_func(gpointer data)
{
gpointer val = NULL;
GAsyncQueue *aqueue = NULL;
g_print("%s n", __FUNCTION__);
aqueue = (GAsyncQueue *)data;
g_async_queue_lock(aqueue);
val = g_async_queue_pop_unlocked(aqueue);
g_async_queue_unlock(aqueue);
g_print("val: %d n", GPOINTER_TO_INT(val));
return NULL;
}
gint main(gint argc, gchar **argv)
{
GThread *thd_push, *thd_pop;
GAsyncQueue *aqueue = NULL;
aqueue = g_async_queue_new();
thd_push = g_thread_new("thd_push", test_aqueue_push_func, aqueue);
thd_pop
= g_thread_new("thd_pop", test_aqueue_pop_func, aqueue);
g_thread_join(thd_push);
g_thread_join(thd_pop);
g_async_queue_unref(aqueue);
return 0;
}
运行结果:
[root@centos7_6 build]# ./glib_async_queue_locks
test_aqueue_push_func
test_aqueue_pop_func
val: 99
[root@centos7_6 build]# ./glib_async_queue_locks
test_aqueue_pop_func
test_aqueue_push_func
val: 99
尝试出队列
g_async_queue_try_pop尝试从队列中取出一个元素,如果队列中有数据,则取出,如果队列中无数据,则返回空,此接口不阻塞。
源码见glib_examplesglib_async_queueglib_async_queue_try_pop
#include <glib.h>
static gpointer test_aqueue_push_func(gpointer data)
{
GAsyncQueue *aqueue = NULL;
g_print("%s n", __FUNCTION__);
g_print("delay 1 seconds to push data n");
g_usleep(1*1000*1000);
aqueue = (GAsyncQueue *)data;
g_async_queue_push(aqueue, GINT_TO_POINTER(99));
return NULL;
}
static gpointer test_aqueue_pop_func(gpointer data)
{
gpointer val = NULL;
GAsyncQueue *aqueue = NULL;
g_print("%s n", __FUNCTION__);
aqueue = (GAsyncQueue *)data;
val = g_async_queue_try_pop(aqueue);
g_print("val: %d n", GPOINTER_TO_INT(val));
g_print("delay 2 seconds to pop data n");
g_usleep(2*1000*1000);
val = g_async_queue_try_pop(aqueue);
g_print("val: %d n", GPOINTER_TO_INT(val));
val = g_async_queue_try_pop(aqueue);
g_print("val: %d n", GPOINTER_TO_INT(val));
return NULL;
}
gint main(gint argc, gchar **argv)
{
GThread *thd_push, *thd_pop;
GAsyncQueue *aqueue = NULL;
aqueue = g_async_queue_new();
thd_push = g_thread_new("thd_push", test_aqueue_push_func, aqueue);
thd_pop
= g_thread_new("thd_pop", test_aqueue_pop_func, aqueue);
g_thread_join(thd_push);
g_thread_join(thd_pop);
g_async_queue_unref(aqueue);
return 0;
}
运行结果:
[root@centos7_6 build]# ./glib_async_queue_try_pop
test_aqueue_pop_func
val: 0
delay 2 seconds to pop data
test_aqueue_push_func
delay 1 seconds to push data
val: 99
val: 0
尝试出队列无锁版本
g_async_queue_try_pop_unlocked与g_async_queue_try_pop类似,需要自己处理锁。
下面是示例函数:
源码见glib_examplesglib_async_queueglib_async_queue_try_pop_unlocked
#include <glib.h>
static gpointer test_aqueue_push_func(gpointer data)
{
GAsyncQueue *aqueue = NULL;
g_print("%s n", __FUNCTION__);
g_print("delay 1 seconds to push data n");
g_usleep(1*1000*1000);
aqueue = (GAsyncQueue *)data;
g_async_queue_lock(aqueue);
g_async_queue_push_unlocked(aqueue, GINT_TO_POINTER(99));
g_async_queue_unlock(aqueue);
return NULL;
}
static gpointer test_aqueue_pop_func(gpointer data)
{
gpointer val = NULL;
GAsyncQueue *aqueue = NULL;
g_print("%s n", __FUNCTION__);
aqueue = (GAsyncQueue *)data;
g_async_queue_lock(aqueue);
val = g_async_queue_try_pop_unlocked(aqueue);
g_print("val: %d n", GPOINTER_TO_INT(val));
g_async_queue_unlock(aqueue);
g_print("delay 2 seconds to pop data n");
g_usleep(2*1000*1000);
g_async_queue_lock(aqueue);
val = g_async_queue_try_pop_unlocked(aqueue);
g_print("val: %d n", GPOINTER_TO_INT(val));
g_async_queue_unlock(aqueue);
g_async_queue_lock(aqueue);
val = g_async_queue_try_pop_unlocked(aqueue);
g_print("val: %d n", GPOINTER_TO_INT(val));
g_async_queue_unlock(aqueue);
return NULL;
}
gint main(gint argc, gchar **argv)
{
GThread *thd_push, *thd_pop;
GAsyncQueue *aqueue = NULL;
aqueue = g_async_queue_new();
thd_push = g_thread_new("thd_push", test_aqueue_push_func, aqueue);
thd_pop
= g_thread_new("thd_pop", test_aqueue_pop_func, aqueue);
g_thread_join(thd_push);
g_thread_join(thd_pop);
g_async_queue_unref(aqueue);
return 0;
}
运行结果:
[root@centos7_6 build]# ./glib_async_queue_try_pop_unlocked
test_aqueue_push_func
delay 1 seconds to push data
test_aqueue_pop_func
val: 0
delay 2 seconds to pop data
val: 99
val: 0
可以看到三次try_pop均立即返回,当队列中没有数据时,返回值为空。
超时
g_async_queue_timeout_pop,从异步队列中取数据,阻塞指定时间,超时则退出,返回值为空。
如果队列中有数据,则本函数立即返回。
超时时间为微秒Microsecond(1Second=1*1000Millisecond=1*1000*1000Microsecond
)。
下面是演示程序:
源码见glib_examplesglib_async_queueglib_async_queue_timed_pop
#include <glib.h>
static gpointer test_aqueue_push_func(gpointer data)
{
GAsyncQueue *aqueue = NULL;
g_print("%s n", __FUNCTION__);
g_print("delay 2 seconds to push data n");
g_usleep(2*1000*1000);
aqueue = (GAsyncQueue *)data;
g_async_queue_push(aqueue, GINT_TO_POINTER(99));
return NULL;
}
static gpointer test_aqueue_pop_func(gpointer data)
{
gpointer val = NULL;
guint64 timeout = 0;
GAsyncQueue *aqueue = NULL;
g_print("%s n", __FUNCTION__);
aqueue = (GAsyncQueue *)data;
timeout = 1*1000*1000;
val = g_async_queue_timeout_pop(aqueue, timeout);
g_print("val: %d n", GPOINTER_TO_INT(val));
g_print("delay 2 seconds to pop data again n");
g_usleep(2*1000*1000);
val = g_async_queue_try_pop(aqueue);
g_print("val: %d n", GPOINTER_TO_INT(val));
return NULL;
}
gint main(gint argc, gchar **argv)
{
GThread *thd_push, *thd_pop;
GAsyncQueue *aqueue = NULL;
aqueue = g_async_queue_new();
thd_push = g_thread_new("thd_push", test_aqueue_push_func, aqueue);
thd_pop
= g_thread_new("thd_pop", test_aqueue_pop_func, aqueue);
g_thread_join(thd_push);
g_thread_join(thd_pop);
g_async_queue_unref(aqueue);
return 0;
}
运行结果:
[root@centos7_6 build]# ./glib_async_queue_timed_pop
test_aqueue_push_func
delay 2 seconds to push data
test_aqueue_pop_func
val: 0
delay 2 seconds to pop data again
val: 99
最后
以上就是昏睡荔枝为你收集整理的5_05_GLib库入门与实践_异步队列的全部内容,希望文章能够帮你解决5_05_GLib库入门与实践_异步队列所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复