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. 将vim作为QT开发的IDE

    转载请注明链接与作者huihui1988 用了一段时间的vim,喜欢上了这种简洁高效的编辑器.恰逢正在学习QT中,于是将vim变成了开发QT的工具.以下是具体配置. 一.语法高亮支持: 1.打开VIM ...

  2. 关于在Reshaper中添加代码模板代码段

    http://www.cnblogs.com/tristinjet/archive/2009/08/19/1550203.html 去 tools->模板中进行模板编辑设置

  3. Bring Your Charts to Life with HTML5 Canvas and JavaScript

    Bring Your Charts to Life with HTML5 Canvas and JavaScript Bring Your Charts to Life with HTML5 Canv ...

  4. JNI与JNA性能比较

    JNI与JNA性能比较 在介绍JNA时,提到了JNA是基于JNI的,是在JNI上封装了一层,JNI性能不如JNA.最近在网上看到篇简单的比较这两者性能的文档,感觉不错,现转载一下: 分别用JNI和JN ...

  5. windows查看端口占用情况及查杀进程

    我们平时在做web开发运行web服务器或运行某个应用时会报错,提示该应用的端口号已被占用,我们可以用以下的方法解决. 解决方法一:重新为应用配置端口. 解决方法二:找到占用端口的应用并关闭该应用释放占 ...

  6. Java程序员面试题集(116-135)

    摘要:这一部分讲解基于Java的Web开发相关面试题,即便在Java走向没落的当下,基于Java的Web开发因为拥有非常成熟的解决方案,仍然被广泛应用.不管你的Web开发中是否使用框架,JSP和Ser ...

  7. 关于map与set的一点理解;

    set代码: #include<stdio.h> #include<set> using namespace std; int main(){ set<int>m; ...

  8. poj 2429 Pollard_rho大数分解

    先对lcm/gcd进行分解,问题转变为从因子中选出一些数相乘,剩下的数也相乘,要求和最小. 这里能够直接搜索,注意一个问题,因为同样因子不能分配给两边(会改变gcd)所以能够将同样因子合并,这种话,搜 ...

  9. Spring--------web应用中保存spring容器

    ---恢复内容开始--- 问题:在一个web应用中我使用了spring框架,但有一部分模块或组件并没有托管给Spring,比如有的可能是一个webservice服务类,如果我想在这些非托管的类里使用托 ...

  10. 查看被锁的数据[Z]

    SELECT LOCK_INFO.OWNER || '.' || LOCK_INFO.OBJ_NAME AS OBJ_NAME --对象名称(已经被锁住) ,LOCK_INFO.SUBOBJ_NAME ...