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. UESTC_Palindromic String 2015 UESTC Training for Search Algorithm & String<Problem M>

    M - Palindromic String Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 128000/128000KB (Java ...

  2. Difference Between Mod_Python & Mod_Wsgi | eHow

    Difference Between Mod_Python & Mod_Wsgi | eHow     x    YES    NO    Why not?     Thanks for he ...

  3. hdu 5625 Clarke and chemistry

    Problem Description Clarke is a patient with multiple personality disorder. One day, Clarke turned i ...

  4. ASP.NET中连接数据库的各种方法

    ASP.NET中连接数据库的各种方法 连接SQL数据库的方法:(一).在Web.Config中创建连接字符串:1.<add name="ConnectionString" c ...

  5. mvc 日历控件

    第二个是日历控件,在网上查了一个普通的日历控件,也生成了下拉的日历样子,但是一些脚本比如选择年月,需要一些时间,最后只好套用了My97 DatePicker,这样以来其实简单多了. 第一步:下载 My ...

  6. Unity uGUI 登录及注册功能

    上次我们已经完成了登录界面的模拟功能,今天咱们把上次没做完的继续完善下!那么废话少说直接开始吧! PS:本次完善的功能有: 1,增加对数据库的操作. 2,使用了MD5Key值加密 3,完善登录和组测功 ...

  7. SCII码表 键盘常用ASCII码

    ASCII码对照表   在Web开发时,如下的ASCII码只要加上&#和;就可以变成Web可以辨认的字符了在处理特殊字符的时候特别有用,如:' 单引号在数据库查询的时候是杀手,但是如果转换成' ...

  8. PHP学习笔记十二【数组排序】

    <?php $arr=array(0,5,-1); $temp=0; for($i=0;$i<count($arr)-1;$i++) { for($j=0;$j<count($arr ...

  9. oracle数据库10g下载地址

    Oracle Database 10g Release 2 (10.2.0.1.0) Enterprise/Standard Edition for Microsoft Windows (32-bit ...

  10. Entity Framework 6 Code First创建

    基本上我是DB先设计好的,所以就按现存在的table去写程式. 1.Web.config里配置Db连接字串,Connection String Name为DefaultConnection <c ...