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的更多相关文章

  1. boost::asio 使用 libcurl

    curl 使用 asio 的官方样例 http://curl.haxx.se/libcurl/c/asiohiper.html, 但这个例子用起来有很明细的 bug,asio 异步IO 只注册一次,也 ...

  2. libev代码

    就是贴上来: ev.c: /* * libev event processing core, watcher management */ /* this big block deduces confi ...

  3. .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]

    方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...

  4. category中重写方法?

    问:可以在category中重写方法吗? 答:代码上可以实现 在category中重写方法,但在实际开发中,不建议这样做.如果确实需要重写原有方法也建议使用子类进行重写. category是为了更方便 ...

  5. ASP.NET Aries 4.0 开源发布:已完成基础功能优化重写

    主要更新: 1:增加AR.Global.GetUser() 方法返回当前登陆者的用户信息. 2:重写AR.Combobox 支持下拉树. 3:调整及扩展Input下拉的配置参数. 4:优化及新增AR. ...

  6. 小丁带你走进git的世界四-重写历史记录

    一.git对象文件创建 开篇先补充一个知识点,就是比如我建立一个文件之后,使用git add就会生成一个git对象,但是git对象生成后可以在.git/objects里面对应,首先我们来初始化一个仓库 ...

  7. 已经重写,源码和文章请跳转http://www.cnblogs.com/ymnets/p/5621706.html

    文章由于写得比较仓促 已经重写,源码和文章请跳转 http://www.cnblogs.com/ymnets/p/5621706.html 系列目录 前言: 导入导出实在多例子,很多成熟的组建都分装了 ...

  8. C#基础回顾(二)—页面值传递、重载与重写、类与结构体、装箱与拆箱

    一.前言 -孤独的路上有梦想作伴,乘风破浪- 二.页面值传递 (1)C#各页面之间可以进行数据的交换和传递,页面之间可根据获取的数据,进行各自的操作(跳转.计算等操作).为了实现多种方式的数据传递,C ...

  9. SQL Server索引视图以(物化视图)及索引视图与查询重写

    本位出处:http://www.cnblogs.com/wy123/p/6041122.html 经常听Oracle的同学说起来物化视图,物化视图的作用之一就是可以实现查询重写,听起来有一种高大上的感 ...

随机推荐

  1. 配置文件入门 - WebConfig.config常用配置节点介绍

    一.配置文件入门 .Net提供了一种保存项目配置信息的办法,就是利用配置文件,配置文件的后缀一般是.config.在WinForm程序中配置文件一般是App.config.在Asp.net中一般默认是 ...

  2. Linux APP源码级编译安装

    首先需要了解下tar包. 以下文章作出解释了: http://www.cnblogs.com/laipDIDI/articles/2214270.html http://baike.baidu.com ...

  3. HDMI相关知识

    HDMI热插拔检测原理 HDMI(19Pin)/DVI(16 pin)的功能是热插拔检测(HPD),这个信号将作为主机系统是否对HDMI/DVI是否发送TMDS信号的依据.HPD是从显示器输出送往计算 ...

  4. IOS拷贝文件到沙盒

    - (void)copyFileFromResourceTOSandbox { //文件类型 NSString * docPath = [[NSBundle mainBundle] pathForRe ...

  5. HDU 1559 最大子矩阵 (DP)

    题目地址:pid=1559">HDU 1559 构造二维前缀和矩阵.即矩阵上的点a[i][j]表示左上方的点为(0,0),右下方的点为(i,j)的矩阵的和.然后枚举每一个矩阵的左上方的 ...

  6. VLC各个Module模块之间共享变量的实现方法

    在做VLC开发的时候,想使用一个模块访问另外一个模块的数据, 比如在网络模块得到了一些数据,想在其他模块得到这些数据进行处理,这时候就需要两个模块共享一些变量. 查看VLC的源码,发现VLC专门有va ...

  7. 关于JS 对象与JSON对象

    Js对象 格式 : //var dataStr = '{ code: 1, msg: "修改成功", read: 1 }'; 序列化字符串为js对象: var p = eval(& ...

  8. js 的try catch

    语法: try { //在此运行代码 } catch(err) { //在此处理错误 } 注意:try...catch 使用小写字母.大写字母会出错. <script language=&quo ...

  9. SQL-LINQ-Lambda 语法对照

    SQL LINQ Lambda  SELECT *FROM Employees from e in Employees  select e Employees .Select (e => e)  ...

  10. 解决linux top命令提示的unknown terminal type的问题

    [root@localhost bin]# top 'xterm-256color': unknown terminal type. 在网上搜索了解决方法如下: 解决办法: 1.临时办法,下次启动失效 ...