重写 libev 的 EV_WIN32_HANDLE_TO_FD
libev 的 EV_WIN32_HANDLE_TO_FD 默认实现是调用C库的 _open_osfhandle ,但这里有个问题是转换后,关闭 fd 就默认关闭了 handle。当它遇到 libcurl 时就出现了问题。 libcurl handle 的创建和关闭都是 libcurl 来管理的,适配 libev 时只需要简单的映射和反映射、关闭 fd 只取消映射关系不关闭底层 handle。
这里重新实现了 EV_WIN32_HANDLE_TO_FD ,解决了 _open_osfhandle 的限制
ev_win32_handle.h
#pragma once
#if defined(_WIN32) && defined(EV_STANDALONE) /*
ANFD ev_loop::anfds[anfdmax], that is an array use fd as its index. so we must map win32 socket to [0, FD_SETSIZE). if you can limit mapped fd to be used only in one specified thread, we can use per thread map also--reduce lock and reduce little memory. */ #ifdef __cplusplus
extern "C" {
#endif int OpenFd(SOCKET h);
SOCKET GetHandle(int fd);
int CloseFd(int fd, int close_handle); #define EV_FD_TO_WIN32_HANDLE(fd) GetHandle(fd)
#define EV_WIN32_HANDLE_TO_FD(handle) OpenFd(handle)
#define EV_WIN32_CLOSE_FD(fd) CloseFd(fd, 1) #ifdef __cplusplus
}
#endif #endif
ev_win32_handle.cpp
#if defined(_WIN32) && defined(EV_STANDALONE) #define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <assert.h> #include <mutex> // std::call_once, std::once_flag #include "ev_win32_handle.h" typedef struct vfd_entry_t
{
SOCKET handle; /* OS handle, i.e. SOCKET */
//int fd; /* fd */
vfd_entry_t *next; /* Next free fd, -1 if last */
} vfd_entry; vfd_entry vfds[FD_SETSIZE] = {};
vfd_entry *vfd_free = NULL;
std::once_flag vfds_init_flag;
std::mutex vfds_mutex; void InitFd()
{
vfd_entry *pre = NULL;
for (int idx = FD_SETSIZE - ; idx >= ; --idx)
{
vfds[idx].handle = /*INVALID_HANDLE_VALUE;*/INVALID_SOCKET;
//vfds[idx].fd = idx;
vfds[idx].next = pre; pre = &vfds[idx];
} vfd_free = pre;
} int OpenFd(SOCKET h)
{
std::call_once(vfds_init_flag, InitFd);
std::lock_guard<std::mutex> lck (vfds_mutex); int fd = -;
if (vfd_free)
{
vfd_entry *next = vfd_free->next;
vfd_free->handle = h;
vfd_free->next = NULL; //fd = vfd_free->fd;
fd = vfd_free - vfds;
vfd_free = next;
}
assert(fd >= && fd < FD_SETSIZE);
return fd;
} SOCKET GetHandle(int fd)
{
assert(fd >= && fd < FD_SETSIZE);
return vfds[fd].handle;
} extern int CloseFd(int fd, int close_handle /*= 0*/)
{
assert(fd >= && fd < FD_SETSIZE); if (close_handle)
{
assert(vfds[fd].next == NULL);
closesocket(vfds[fd].handle);
} std::lock_guard<std::mutex> lck (vfds_mutex);
vfds[fd].handle = /*INVALID_HANDLE_VALUE;*/INVALID_SOCKET;
vfds[fd].next = vfd_free;
vfd_free = &vfds[fd]; return ;
} #endif
libev 整合 libcurl 使用可以参考 libcurl 的官方样例 http://curl.haxx.se/libcurl/c/evhiperfifo.html
自定义 libev 的映射,也可以参考 python 的 gevent 库
重写 libev 的 EV_WIN32_HANDLE_TO_FD的更多相关文章
- boost::asio 使用 libcurl
curl 使用 asio 的官方样例 http://curl.haxx.se/libcurl/c/asiohiper.html, 但这个例子用起来有很明细的 bug,asio 异步IO 只注册一次,也 ...
- libev代码
就是贴上来: ev.c: /* * libev event processing core, watcher management */ /* this big block deduces confi ...
- .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]
方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...
- category中重写方法?
问:可以在category中重写方法吗? 答:代码上可以实现 在category中重写方法,但在实际开发中,不建议这样做.如果确实需要重写原有方法也建议使用子类进行重写. category是为了更方便 ...
- ASP.NET Aries 4.0 开源发布:已完成基础功能优化重写
主要更新: 1:增加AR.Global.GetUser() 方法返回当前登陆者的用户信息. 2:重写AR.Combobox 支持下拉树. 3:调整及扩展Input下拉的配置参数. 4:优化及新增AR. ...
- 小丁带你走进git的世界四-重写历史记录
一.git对象文件创建 开篇先补充一个知识点,就是比如我建立一个文件之后,使用git add就会生成一个git对象,但是git对象生成后可以在.git/objects里面对应,首先我们来初始化一个仓库 ...
- 已经重写,源码和文章请跳转http://www.cnblogs.com/ymnets/p/5621706.html
文章由于写得比较仓促 已经重写,源码和文章请跳转 http://www.cnblogs.com/ymnets/p/5621706.html 系列目录 前言: 导入导出实在多例子,很多成熟的组建都分装了 ...
- C#基础回顾(二)—页面值传递、重载与重写、类与结构体、装箱与拆箱
一.前言 -孤独的路上有梦想作伴,乘风破浪- 二.页面值传递 (1)C#各页面之间可以进行数据的交换和传递,页面之间可根据获取的数据,进行各自的操作(跳转.计算等操作).为了实现多种方式的数据传递,C ...
- SQL Server索引视图以(物化视图)及索引视图与查询重写
本位出处:http://www.cnblogs.com/wy123/p/6041122.html 经常听Oracle的同学说起来物化视图,物化视图的作用之一就是可以实现查询重写,听起来有一种高大上的感 ...
随机推荐
- 配置文件入门 - WebConfig.config常用配置节点介绍
一.配置文件入门 .Net提供了一种保存项目配置信息的办法,就是利用配置文件,配置文件的后缀一般是.config.在WinForm程序中配置文件一般是App.config.在Asp.net中一般默认是 ...
- Linux APP源码级编译安装
首先需要了解下tar包. 以下文章作出解释了: http://www.cnblogs.com/laipDIDI/articles/2214270.html http://baike.baidu.com ...
- HDMI相关知识
HDMI热插拔检测原理 HDMI(19Pin)/DVI(16 pin)的功能是热插拔检测(HPD),这个信号将作为主机系统是否对HDMI/DVI是否发送TMDS信号的依据.HPD是从显示器输出送往计算 ...
- IOS拷贝文件到沙盒
- (void)copyFileFromResourceTOSandbox { //文件类型 NSString * docPath = [[NSBundle mainBundle] pathForRe ...
- HDU 1559 最大子矩阵 (DP)
题目地址:pid=1559">HDU 1559 构造二维前缀和矩阵.即矩阵上的点a[i][j]表示左上方的点为(0,0),右下方的点为(i,j)的矩阵的和.然后枚举每一个矩阵的左上方的 ...
- VLC各个Module模块之间共享变量的实现方法
在做VLC开发的时候,想使用一个模块访问另外一个模块的数据, 比如在网络模块得到了一些数据,想在其他模块得到这些数据进行处理,这时候就需要两个模块共享一些变量. 查看VLC的源码,发现VLC专门有va ...
- 关于JS 对象与JSON对象
Js对象 格式 : //var dataStr = '{ code: 1, msg: "修改成功", read: 1 }'; 序列化字符串为js对象: var p = eval(& ...
- js 的try catch
语法: try { //在此运行代码 } catch(err) { //在此处理错误 } 注意:try...catch 使用小写字母.大写字母会出错. <script language=&quo ...
- SQL-LINQ-Lambda 语法对照
SQL LINQ Lambda SELECT *FROM Employees from e in Employees select e Employees .Select (e => e) ...
- 解决linux top命令提示的unknown terminal type的问题
[root@localhost bin]# top 'xterm-256color': unknown terminal type. 在网上搜索了解决方法如下: 解决办法: 1.临时办法,下次启动失效 ...