把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(3)(★firecat推荐★)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(3)(★firecat推荐★)

Libevent中的timeout事件是使用最小堆来管理维护的.代码位于<minheap-internal.h>.


源码来源:https://github.com/libevent/libevent/blob/release-2.1.8-stable/minheap-internal.h



本篇在第2篇的基础之上进行优化升级,加上类似muduo活塞式的buffer。


本篇实现Linux网络库epoll+时间堆+buffer实现高性能服务器。


完整的工程下载:https://download.csdn.net/download/libaineu2004/10468714




1、CMakeLists.txt


cmake_minimum_required(VERSION 2.8)

PROJECT(min_heap_libevent_epoll_buf)

AUX_SOURCE_DIRECTORY(. SRC_LIST)

ADD_EXECUTABLE(${PROJECT_NAME} ${SRC_LIST})


2、buffer.h

#ifndef MYREDISNET_AEBUFFER_H
#define MYREDISNET_AEBUFFER_H
/// 《Linux多线程服务端编程:使用muduo C++网络库》陈硕著 7.4章节,P204
/// https://github.com/chenshuo/muduo
/// muduo buf:A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer
///
/// @code
/// +-------------------+------------------+------------------+
/// | prependable bytes |  readable bytes  |  writable bytes  |
/// |                   |     (CONTENT)    |                  |
/// +-------------------+------------------+------------------+
/// |                   |                  |                  |
/// 0      <=      readerIndex   <=   writerIndex    <=     size
///
/// @endcode
//#include "zmalloc.h"//不能直接包含reids这个头文件,编译会报错 basic_string.h:2423:7: error: ‘__str’ was not declared in this scope
//#include "myjemalloc.h"//要用这个
#include <sys/types.h>
//no use jemalloc,only libc
#define zmalloc malloc
#define zfree(p) if (p) { free(p); }
#define zrealloc realloc
#define DEFAULT_BUFF_SIZE        1024
typedef struct {
    unsigned char *buff;
    size_t size;
    size_t read_idx;
    size_t write_idx;
} buffer_t;
buffer_t *alloc_buffer();
void free_buffer(buffer_t *buffer);
void check_buffer_size(buffer_t *buffer, size_t avlid_size);
size_t get_readable_size(buffer_t *buffer);
size_t get_writeable_size(buffer_t *buffer);
#endif //MYREDISNET_AEBUFFER_H


3、buffer.c4、client.h


#ifndef CLIENT_H

#define CLIENT_H

#include <stdio.h>

#include <stdint.h> //eg. uint64_t

#include "buffer.h"

typedef struct {

   int fd;

   int epollfd;

   int timerId;

   uint64_t last_recv_tick;

   buffer_t *read_buffer;

   buffer_t *write_buffer;

} client_t;

typedef struct fileEvent {

   client_t *clientData;

} fileEvent;

extern fileEvent *fileev;

extern client_t *alloc_client();

extern uint64_t get_tick_count();

extern void free_client(client_t *client);

extern void create_fileEvent(int setsize);

extern void destroy_fileEvent(int setsize);

#endif // CLIENT_H


5、client.c

#include "client.h"
fileEvent *fileev = NULL;
uint64_t get_tick_count() //come from /teamtalk/util.cpp
{
#ifdef _WIN32
    LARGE_INTEGER liCounter;
    LARGE_INTEGER liCurrent;
    if (!QueryPerformanceFrequency(&liCounter))
        return GetTickCount();
    QueryPerformanceCounter(&liCurrent);
    return (uint64_t)(liCurrent.QuadPart * 1000 / liCounter.QuadPart);
#else
    struct timeval tval;
    uint64_t ret_tick;
    gettimeofday(&tval, NULL);
    ret_tick = tval.tv_sec * 1000L + tval.tv_usec / 1000L;
    return ret_tick;
#endif
}
client_t *alloc_client()
{
    client_t * client = zmalloc(sizeof(client_t));
    if (client == NULL) {
        goto err;
    }
    client->fd = -1;
    client->timerId = -1;
    client->last_recv_tick = get_tick_count();
    client->read_buffer = alloc_buffer();
    client->write_buffer = alloc_buffer();
    if (client->read_buffer == NULL || client->write_buffer == NULL) {
        goto err;
    }
    return client;
err:
    if (client) {
        free_client(client);
    }
    return NULL;
}
void free_client(client_t *client)
{
    if (client) {
        if (client->fd > 0) {
            close(client->fd);
        }
        free_buffer(client->read_buffer);
        free_buffer(client->write_buffer);
        zfree(client);
    }
}
void create_fileEvent(int setsize)
{
     fileev = zmalloc(sizeof(fileEvent) * setsize);
}
void destroy_fileEvent(int setsize)
{
    int i = 0;
    for (i = 0; i < setsize; i++)
    {
        if (fileev->clientData != NULL)
        {
            free_client(fileev->clientData);
        }
    }
    zfree(fileev);
}

6、minheap-event-firecat.h

#ifndef MINHEAPEVENTFIRECAT_H
#define MINHEAPEVENTFIRECAT_H
#include <sys/time.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
//come from https://github.com/libevent/libevent/blob/release-2.1.8-stable/mm-internal.h
#define mm_malloc(sz) malloc(sz)
#define mm_calloc(n, sz) calloc((n), (sz))
#define mm_strdup(s) strdup(s)
#define mm_realloc(p, sz) realloc((p), (sz))
#define mm_free(p) free(p)
//come from https://github.com/libevent/libevent/blob/release-2.1.8-stable/include/event2/util.h
#define evutil_timercmp(tvp, uvp, cmp)                          \
    (((tvp)->tv_sec == (uvp)->tv_sec) ?                           \
    ((tvp)->tv_usec cmp (uvp)->tv_usec) :                     \
    ((tvp)->tv_sec cmp (uvp)->tv_sec))
#define evutil_timersub(tvp, uvp, vvp)                      \
    do {                                                    \
    (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;     \
    (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;  \
    if ((vvp)->tv_usec < 0) {                         \
    (vvp)->tv_sec--;                             \
    (vvp)->tv_usec += 1000000;                       \
    }                                                   \
    } while (0)
#define evutil_timeradd(tvp, uvp, vvp)                          \
    do {                                                        \
    (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec;         \
    (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec;       \
    if ((vvp)->tv_usec >= 1000000) {                      \
    (vvp)->tv_sec++;                                 \
    (vvp)->tv_usec -= 1000000;                           \
    }                                                       \
    } while (0)
//come from https://github.com/libevent/libevent/blob/release-2.1.8-stable/include/event2/event_struct.h
struct event
{
    /* for managing timeouts */
    union {
        //TAILQ_ENTRY(event) ev_next_with_common_timeout;
        int min_heap_idx;
    } ev_timeout_pos;
    unsigned int timer_id;
    struct timeval ev_interval;
    struct timeval ev_timeout;
    int ev_exe_num;
    int (*ev_callback)(void *arg);
    int ev_arg;
    int ev_res; /* result passed to event callback */
    int ev_flags;
};
//static inline void gettime(struct timeval *tm);
static void gettime(struct timeval *tm)
{
    gettimeofday(tm, NULL);
}
//come from redis src "ae.c"
static void aeGetTime(long *seconds, long *milliseconds)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    *seconds = tv.tv_sec;
    *milliseconds = tv.tv_usec/1000;
}
#endif // MINHEAPEVENTFIRECAT_H
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
3月前
|
C语言 C++ Windows
QT多插件通信框架CTK编译记录
本文记录了编译QT多插件通信框架CTK的过程,包括编译结果截图、部署配置、Log4Qt编译配置、参考链接和拓展资料。文中提供了详细的编译步骤和配置文件示例,以及相关的资源链接。
QT多插件通信框架CTK编译记录
把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(2)(★firecat推荐★)
把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(2)(★firecat推荐★)
192 0
|
网络协议 NoSQL 关系型数据库
《Linux多线程服务端编程:使用muduo C++网络库》学习笔记,★firecat推荐★
《Linux多线程服务端编程:使用muduo C++网络库》学习笔记,★firecat推荐★
431 0
《Linux多线程服务端编程:使用muduo C++网络库》学习笔记,★firecat推荐★
|
区块链 C++ Windows
写了个VC++ MFC小工具,一键整理Resource.h文件,重新排序并去重复ID(★firecat推荐★)
写了个VC++ MFC小工具,一键整理Resource.h文件,重新排序并去重复ID(★firecat推荐★)
1023 0
写了个VC++ MFC小工具,一键整理Resource.h文件,重新排序并去重复ID(★firecat推荐★)
|
前端开发
Qt界面设计 -- 点滴记录(★firecat推荐★)
Qt界面设计 -- 点滴记录(★firecat推荐★)
189 0
Qt界面设计 -- 点滴记录(★firecat推荐★)
|
Linux C语言
把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(3)(★firecat推荐★)
把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(★firecat推荐★)
271 0
把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(4)(★firecat推荐★)
把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(4)(★firecat推荐★)
105 0
|
Linux C++
把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(1)(★firecat推荐★)
把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(1)(★firecat推荐★)
132 0
把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(5)(★firecat推荐★)
把libevent 2.1.8源码的最小堆提取出来,自己封装成定时器使用(5)(★firecat推荐★)
114 0
|
算法 应用服务中间件 Linux
epoll定时器实现系列文章:高性能定时器实现的三种方式---升序链表,时间轮,最小堆(★firecat推荐★)
epoll定时器实现系列文章:高性能定时器实现的三种方式---升序链表,时间轮,最小堆(★firecat推荐★)
952 0