IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 新版本glib使用epoll代替poll -> 正文阅读

[C++知识库]新版本glib使用epoll代替poll

新版本的glib支持使用外部的事件循环代替内部的poll,这篇文章使用的glib版本是V2.72.0, 理解还很粗浅,但是demo能跑起来,还需要再详细研究一下参考的两个链接,多线程下使用及效率是怎样的都还不清楚。

1、新API

通过新的API g_main_context_new_with_flags 及新变量G_MAIN_CONTEXT_FLAGS_OWNERLESS_POLLING可以创建一个无主的poll,然后通过glib的一套API可以实现自己的事件循环。ubuntu18下的demo:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <glib.h>
#include <sys/epoll.h>

static GMainContext *watchdog_context = NULL;

int num = 0;
static gboolean cb_check(gpointer user_data) 
{
   printf("In cb_check %d \n", num);
}

char* name = "ori";
static gpointer cb_watchdog(gpointer user_data) 
{
   num = 1;
   GMainLoop *loop = (GMainLoop *) user_data;
   GMainContext *watchdog_context = g_main_loop_get_context(loop);
   GSource *timeout_source;

   timeout_source = g_timeout_source_new_seconds(2);
   
   g_source_set_callback(timeout_source, cb_check, watchdog_context, (gpointer)name);
   g_source_attach(timeout_source, watchdog_context);
   g_source_unref(timeout_source);

   printf("Sessions watchdog started\n");

   g_main_loop_run(loop);

   printf("Sessions watchdog stopped\n");

   return NULL;
}

void test_ori_glib_event_loop()
{
   /* Start the sessions timeout watchdog */
   watchdog_context = g_main_context_new();
   GError *error = NULL;
   GMainLoop *watchdog_loop = g_main_loop_new(watchdog_context, FALSE);
   
   GThread *watchdog = g_thread_try_new("timeout watchdog", &cb_watchdog, watchdog_loop, &error);
   if(error != NULL) 
   {
   	printf("Got error %d (%s) trying to start sessions timeout watchdog...\n",
   		error->code, error->message ? error->message : "??");
   	g_error_free(error);
   	exit(1);
   }
}

unsigned short glib_event_2_epoll(unsigned short  glib_event)
{
   unsigned short ret = 0;
   
   if (glib_event & G_IO_IN)
   	ret |= EPOLLIN;
   
   if (glib_event & G_IO_OUT)
   	ret |= EPOLLOUT;
   
   if (glib_event & G_IO_PRI)
   	ret |= EPOLLPRI;
   
   if (glib_event & G_IO_HUP)
   	ret |= EPOLLHUP;
   
   if (glib_event & G_IO_NVAL)
   	ret |= EPOLLERR;
   
   return ret;
}

unsigned short epoll_event_2_glib(unsigned short  epoll_event)
{
   unsigned short ret = 0;
   
   if (epoll_event & EPOLLIN) 
   	ret |= G_IO_IN;
   
   if (epoll_event & EPOLLOUT)
   	ret |= G_IO_OUT ;
   
   if (epoll_event & EPOLLPRI)
   	ret |= G_IO_PRI;
   
   if (epoll_event & EPOLLHUP)
   	ret |= G_IO_HUP;
   
   if (epoll_event & EPOLLERR)
   	ret |= G_IO_NVAL;
   
   return ret;
}

#define MAX_EVENTS (4096)
int ev_poll(GPollFD *fds,
   guint    nfds,
   gint     timeout)
{
   GPollFD *f = NULL;
   int epollfd = -1;
   struct epoll_event  ev;
   int ret = 0;
   
   int max_events = nfds;
   struct epoll_event epoll_events[MAX_EVENTS];
   for (f = fds; f < &fds[nfds]; ++f)
   {
   	if (f->fd >= 0)
   	{
           if(epollfd == -1)
   		{
               epollfd = epoll_create1(EPOLL_CLOEXEC);
               if ( epollfd == -1 )
               {
                   perror( "epoll_create1" );
                   continue;
               }
           }
   		
   		ev.events  = f->events;//glib_event_2_epoll(f->events);
   		ev.data.fd = f->fd;
   		
   		if( epoll_ctl(epollfd, EPOLL_CTL_ADD, f->fd, &ev) == -1 )
   		{
   			perror( "epoll_ctl: listen_sock" );
   			continue;
   		}

   	}
   }
   
   nfds = epoll_wait( epollfd, epoll_events, MAX_EVENTS, 10 );
   
   if(nfds > 0)
   {
       //unsigned short events = event[i].events;
       struct epoll_event  *ev = NULL;
       for (ev = epoll_events; ev < &epoll_events[nfds]; ++ev)
       {
           f->revents = 0;
           if (f->fd >= 0)
           {
               f->revents = ev->events;//epoll_event_2_glib(ev->events);
           }
       }
   }
   else
   {
       perror( "epoll_wait" );
       return 0;
   }
   
   if(epollfd != -1)
   {
       close(epollfd);
   }
   
   return nfds;
}

char* evname = "ev_ori";
/* epoll实现的事件侦听及处理 */
void test_ev_glib_event_loop()
{
   num = 2;
   /* Start the sessions timeout watchdog */
   GMainContext *ctx = g_main_context_new_with_flags (G_MAIN_CONTEXT_FLAGS_OWNERLESS_POLLING);
   g_main_context_push_thread_default (ctx);
   
   GPollFD fds[20];
   gint fds_size;
   gint max_priority;
   GSource *source = NULL;
   
   GSource *timeout_source;

   timeout_source = g_timeout_source_new_seconds(2);
   g_source_set_callback(timeout_source, cb_check, ctx, (gpointer)evname);
   g_source_attach(timeout_source, ctx);
   g_source_unref(timeout_source);
   
   for(;;)
   {
   	gboolean ready_to_dispatch = g_main_context_prepare (ctx, &max_priority);
   	gint timeout, nready;
   	fds_size = g_main_context_query (ctx, max_priority, &timeout, fds, G_N_ELEMENTS (fds));
   	//nready = g_poll (fds, fds_size, /*timeout=*/0);
   	nready = ev_poll (fds, fds_size, /*timeout=*/0);
   	if (!ready_to_dispatch && nready == 0)
   	{
   	  if (timeout == -1)
   		break;
   	  else
   		g_usleep (timeout * 1000);
   	}
   	if(fds_size == 1)
   	printf("events %d \n", fds[0].events);
   	printf("events G_IO_IN[%d] G_IO_OUT[%d] G_IO_PRI[%d]\n", G_IO_IN, G_IO_OUT, G_IO_PRI);
   	
   	ready_to_dispatch = g_main_context_check (ctx, max_priority, fds, fds_size);
   	
   	if (ready_to_dispatch)
   		g_main_context_dispatch (ctx);
   }
   
   g_assert_cmpint (g_poll (fds, fds_size, 0), >, 0);

   g_main_context_unref (ctx);
}

int main()
{

   //test_ori_glib_event_loop();
   test_ev_glib_event_loop();
   
   while(1)
   {
   	sleep(1);
   }
   
   return 0;
}

编译

gcc -o demo_glib main.c -lpthread `pkg-config --cflags glib-2.0` `pkg-config --libs glib-2.0`

2、参考

《1》、Pluggable event loop backends (epoll support)
《2》、Add g_main_context_new_with_flags() and ownerless polling option

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:32:36  更:2021-12-11 15:34:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:46:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码