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. JavaEE Tutorials (28) - Duke书店案例研究示例

    28.1Duke书店的设计和架构43828.2Duke书店接口439 28.2.1Book Java持久化API实体439 28.2.2Duke书店中使用的企业bean440 28.2.3Duke书店 ...

  2. Linux系统编程(7)—— 进程之进程概述

    我们知道,每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体.现在我们全面了解一下其中都有哪些信息. 进程id.系统中每个进程有 ...

  3. OpenStack Keystone v3 API新特性

    原连接 http://blog.chinaunix.net/uid-21335514-id-3497996.html keystone的v3 API与v2.0相比有很大的不同,从API的请求格式到re ...

  4. Python列表及元组

    列表(list)是Python以及其他语言中最常用到的数据结构之一.Python使用使用中括号[ ] 来解析列表.列表是可变的(mutable)——可以改变列表的内容. 如 list1 = ['phy ...

  5. Hibernate中save、saveorupdate、persist方法的区别

    在Hibernate中,save().saveOrUpdate()和persist()都是用于将对象保存到数据库中的方法,但其中有些细微的差别.例如,save()只能INSERT记录,但是saveOr ...

  6. AJAX最简单的原理以及应用

    Ajax是创建快速动态网页的技术,通过后台与服务器少量的数据交互,是网页实现异步更新.也就是在不整个刷新页面的情况下,可以更新网页中的局部区域. 在原始web应用的模式中: 浏览器       以 h ...

  7. 技术之美[程序人生]我在IBM实习的日子

    写这篇文章的时候,我已经在IBM正式工作了,看看上一篇博文的发布日期,才发现,我已经将近三个月没有更新博客了,多么惊人!为什么这么久?期间发生了很多事情.最重要的一件就是我大学毕业了!毕业的那么平淡, ...

  8. vs debug 快捷键

    命令名 快捷键 说明 调试.应用代码更改 Alt + F10 启动生成操作,利用它可以通过“编辑并继续”功能应用对正在调试的代码所作的更改. 调试.自动窗口 Ctrl + D,Ctrl + A 显示“ ...

  9. poj 3308 (最大流)

    题意:n*m的地图,给出L个火星人登陆的坐标,要在火星人登陆地球的瞬间全部消灭他们,有一种激光枪,一次可以消灭一行(或一列),消灭一行(或一列)有不同的代价,总代价是所有激光枪的代价之积. 思路:之前 ...

  10. Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8010977 前面我们从Android应用程序与 ...