• libevent学习八(evbuffer)


    1.evbuffer以队列的形式管理字节,从尾部添加,从头部取出(FIFO)
    2.evbuffer内部存储形式是多个独立的连续内存
     
     
     
    接口
    //创建和删除
    struct evbuffer *evbuffer_new(void);
    void evbuffer_free(struct evbuffer *buf);
     
    //加锁解锁
    //默认情况下是没有加锁的,多线程并发访问不安全
    //第二个参数lock为空,则自动分配一个锁( 使用evthread_set_lock_creation_callback()设置的锁创建函数)
    int evbuffer_enable_locking(struct evbuffer *buf, void *lock);
    //没有必要为单独的操作加锁,因为单独的操作已经是原子级别的了
    void evbuffer_lock(struct evbuffer *buf);
    void evbuffer_unlock(struct evbuffer *buf);
     
     
    //获取evbuffer包含的字节数
    size_t evbuffer_get_length(const struct evbuffer *buf);
     
    //获取队列首部的连续空间长度
    size_t evbuffer_get_contiguous_space(const struct evbuffer *buf);
     
    //基础的读写数据接口
    //将数据添加到尾部
    int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen);
    //格式化的添加数据到尾部
    int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
    int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap);
     
    //修改最后一块连续内存,或者添加一块连续内存
    int evbuffer_expand(struct evbuffer *buf, size_t datlen);
     
    //从evbuffer移动数据到另一个evbuffer
    int evbuffer_add_buffer(struct evbuffer *dst, struct evbuffer *src);
    int evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
        size_t datlen);
     
    //在首部添加数据
    //这些函数不应该用于和bufferevent关联的evbuffer
    int evbuffer_prepend(struct evbuffer *buf, const void *data, size_t size);
    int evbuffer_prepend_buffer(struct evbuffer *dst, struct evbuffer* src);
     
    //查看首部N字节的连续空间(首先必须确定这N字节空间是连续的,使用evbuffer_get_contiguous_space ()
    //size参数为负数,则拷贝首部连续空间的所有数据
    //如果size很大,该接口效率低
    unsigned char *evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size);
     
    //从evbuffer删除数据
    //evbuffer_drain不拷贝数据,evbuffer_remove要拷贝数据
    int evbuffer_drain(struct evbuffer *buf, size_t len);
    int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);
     
    //从首部拷贝而不删除数据
    //如果效率不好可以使用 evbuffer_peek()
    ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data, size_t datlen);
    ev_ssize_t evbuffer_copyout_from(struct evbuffer *buf,
         const struct evbuffer_ptr *pos,
         void *data_out, size_t datlen);
     
    //按行进行读写
    enum evbuffer_eol_style {
            EVBUFFER_EOL_ANY,     //已任何序列为换行符
            EVBUFFER_EOL_CRLF,   //回车换行的组合为换行标示 ( 或者 )
            EVBUFFER_EOL_CRLF_STRICT,  //严格的
            EVBUFFER_EOL_LF,  //以 为换行标示
            EVBUFFER_EOL_NUL //以NULL为换行标示
    };
     
    //返回的指针在堆上分配,n_read_out参数也是返回参数
    char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out,
        enum evbuffer_eol_style eol_style);
     
    //在evbuffer中搜索
    //表示位置的结构(pos是相对于开始位置的偏移值)
    struct evbuffer_ptr {
            ev_ssize_t pos;
            struct {
                    /* internal fields */
            } _internal;
    };
    struct evbuffer_ptr evbuffer_search(struct evbuffer *buffer,
        const char *what, size_t len, const struct evbuffer_ptr *start);
    struct evbuffer_ptr evbuffer_search_range(struct evbuffer *buffer,
        const char *what, size_t len, const struct evbuffer_ptr *start,
        const struct evbuffer_ptr *end);
    struct evbuffer_ptr evbuffer_search_eol(struct evbuffer *buffer,
        struct evbuffer_ptr *start, size_t *eol_len_out,
        enum evbuffer_eol_style eol_style);
     
     
    //偏移位置计算标示
    //EVBUFFER_PTR_SET,将位置作为绝对位置来设置
    //EVBUFFER_PTR_ADD,在当前位置加上参数指定的位置
    enum evbuffer_ptr_how {
            EVBUFFER_PTR_SET,
            EVBUFFER_PTR_ADD
    };
    int evbuffer_ptr_set(struct evbuffer *buffer, struct evbuffer_ptr *pos,
        size_t position, enum evbuffer_ptr_how how);
     
     
    //搜索所有的字符串
    #include <event2/buffer.h>
    #include <string.h>

    /* Count the total occurrences of 'str' in 'buf'. */int count_instances(struct evbuffer *buf, const char *str)
    {
        size_t len = strlen(str);
        int total = 0;
        struct evbuffer_ptr p;

        if (!len)
            /* Don't try to count the occurrences of a 0-length string. */
            return -1;

        evbuffer_ptr_set(buf, &p, 0, EVBUFFER_PTR_SET);

        while (1) {
             p = evbuffer_search(buf, str, len, &p);
             if (p.pos < 0)
                 break;
             total++;
             evbuffer_ptr_set(buf, &p, 1, EVBUFFER_PTR_ADD);
        }

        return total;
    }
     
     
    //在不使用拷贝的情况下,直接查看evbuffer的数据
    struct evbuffer_iovec {
            void *iov_base;
            size_t iov_len;
    };
     
    //修改被evbuffer_iovec指向的数据,将导致未定义行为
    //任何修改evbuffer的函数被调用,将导致evbuffer_peek设置的指针失效
    int evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len,
        struct evbuffer_ptr *start_at,
        struct evbuffer_iovec *vec_out, int n_vec);
     
     
    //直接向evbuffer写入数据,不存在数据拷贝
    //获取evbuffer的内部指针,如果目前的空间不够,将会进行自动扩展
    //目前的实现将不会使用多于两个的evbuffer_iovec
    //如果提供一个evbuffer_iovec则会进行空间连续校验,以及导致evbuffer调整内部存储,所以最好提供大于1个的evbuffer_iovec
    int evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size,
        struct evbuffer_iovec *vec, int n_vecs);
     
    //如果获取到指针后,有修改evbuffer数据的行为,将导致指针失效
    //或者的指针的值不能被修改
    //如果evbuffer以及有数据则,这些数据将加到已有数据的后面
     
    //将数据提交的evbuffer
    int evbuffer_commit_space(struct evbuffer *buf,
        struct evbuffer_iovec *vec, int n_vecs);
     
    网络IO
     
    //howmuch参数为负 对于读表示读多少由libevent自行判断,对于写表示写整个buffer的内容
    //读到结尾返回值为0,返回负数表示失败,失败的原因应进一步确认,是非阻塞IO不能立即完成
    //还是其他真实错误
     
    //如果使用bufferevent则这些调用都由bufferevent完成,不需要用户调用
     
     
    int evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd);
    int evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd,
            ev_ssize_t howmuch);
    int evbuffer_read(struct evbuffer *buffer, evutil_socket_t fd, int howmuch);
     
     
    Evbuffer and callback
    //当数据增加或删除时的回调函数
    struct evbuffer_cb_info {
            size_t orig_size;//变化前的长度
            size_t n_added;   //添加的长度
            size_t n_deleted;  //删除的长度
    };

    typedef void (*evbuffer_cb_func)(struct evbuffer *buffer,
        const struct evbuffer_cb_info *info, void *arg);
     
    //设置回调函数
    struct evbuffer_cb_entry;
    struct evbuffer_cb_entry *evbuffer_add_cb(struct evbuffer *buffer,
        evbuffer_cb_func cb, void *cbarg);
     
    //失效或删除回调函数
    int evbuffer_remove_cb_entry(struct evbuffer *buffer,
        struct evbuffer_cb_entry *ent);
    int evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb,
        void *cbarg);
    //使用 EVBUFFER_CB_ENABLED失效
    #define EVBUFFER_CB_ENABLED 1
    int evbuffer_cb_set_flags(struct evbuffer *buffer,
                              struct evbuffer_cb_entry *cb,
                              ev_uint32_t flags);
    int evbuffer_cb_clear_flags(struct evbuffer *buffer,
                              struct evbuffer_cb_entry *cb,
                              ev_uint32_t flags);
     
     
    //延迟回调函数的调用
    int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base);
     
     
    //避免数据拷贝的 基本的ebuffer-IO
     
    typedef void (*evbuffer_ref_cleanup_cb)(const void *data,
        size_t datalen, void *extra);

    int evbuffer_add_reference(struct evbuffer *outbuf,
        const void *data, size_t datlen,
        evbuffer_ref_cleanup_cb cleanupfn, void *extra);
     
     
    //直接发送文件相关接口,由于支持的版本很新,目前未测试
     
    int evbuffer_add_file(struct evbuffer *output, int fd, ev_off_t offset,
        size_t length);
     
    struct evbuffer_file_segment;

    struct evbuffer_file_segment *evbuffer_file_segment_new(
            int fd, ev_off_t offset, ev_off_t length, unsigned flags);
    void evbuffer_file_segment_free(struct evbuffer_file_segment *seg);
    int evbuffer_add_file_segment(struct evbuffer *buf,
        struct evbuffer_file_segment *seg, ev_off_t offset, ev_off_t length);
     
     
    typedef void (*evbuffer_file_segment_cleanup_cb)(
        struct evbuffer_file_segment const *seg, int flags, void *arg);

    void evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment *seg,
            evbuffer_file_segment_cleanup_cb cb, void *arg);
     
     
    int evbuffer_add_buffer_reference(struct evbuffer *outbuf,
        struct evbuffer *inbuf);
     
     
    int evbuffer_freeze(struct evbuffer *buf, int at_front);
    int evbuffer_unfreeze(struct evbuffer *buf, int at_front);
     
     
    //过时的接口
    char *evbuffer_readline(struct evbuffer *buffer);
    unsigned char *evbuffer_find(struct evbuffer *buffer,
        const unsigned char *what, size_t len);
     
    typedef void (*evbuffer_cb)(struct evbuffer *buffer,
        size_t old_len, size_t new_len, void *arg);
    void evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg);
     
     
     
     
  • 相关阅读:
    bzoj3306: 树(dfs序+倍增+线段树)
    bzoj1969: [Ahoi2005]LANE 航线规划(树链剖分)
    Codeforces 578B. "Or" Game(思维题)
    bzoj3251: 树上三角形(思维题)
    bzoj2006: [NOI2010]超级钢琴(堆+RMQ)
    bzoj4165: 矩阵(堆+hash)
    bzoj3007: 拯救小云公主(二分+并查集)
    Codeforces 582C. Superior Periodic Subarrays(数学+计数)
    Codeforces 585E. Present for Vitalik the Philatelist(容斥)
    Codeforces 585D. Lizard Era: Beginning(meet in the middle)
  • 原文地址:https://www.cnblogs.com/manziluo/p/5789645.html
Copyright © 2020-2023  润新知