天天看點

把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

      

繼續閱讀