• 重写 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 - 1; idx >= 0; --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 = -1;
        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 >= 0 && fd < FD_SETSIZE);
        return fd;
    }
    
    SOCKET GetHandle(int fd)
    {
        assert(fd >= 0 && fd < FD_SETSIZE);
        return vfds[fd].handle;
    }
    
    extern int CloseFd(int fd, int close_handle /*= 0*/)
    {
        assert(fd >= 0 && 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 0;
    }
    
    
    
    #endif

    libev 整合 libcurl 使用可以参考 libcurl 的官方样例 http://curl.haxx.se/libcurl/c/evhiperfifo.html

    自定义 libev 的映射,也可以参考 python 的 gevent 库

  • 相关阅读:
    (华中科大)江南雨烟 C++ STL 专栏
    MoreWindows 微软认证专家博客目录(白话算法,C++ STL,windows编程)
    「转」基于Jmeter和Jenkins搭建性能测试框架
    【转】docker之Dockerfile实践
    Python 统一动态创建多个model对应的modelForm类(type()函数)
    owasp zap 安全审计工具 安装/拦截请求
    【转】持续集成 Sonar 平台搭建及 Sonar 自定义规则打包部署篇
    【转】SonarQube配置自定义的CheckStyle代码规则
    【转+整理】jenkins与SonarQube集成
    【转】jenkins插件pipeline使用介绍
  • 原文地址:https://www.cnblogs.com/JesseFang/p/4682305.html
Copyright © 2020-2023  润新知