服务器架构设计1

说到服务器,通常可以想象都是一个while(1)无限循环,当某种条件触发之后,则跳出循环。

然而,有些时候,则需要服务器针对某些ses,周期性的执行特定操作,如何实现呢。

一个简单的方法就是,建立session的node list,节点信息包括(time,ses私有变量,回调函数,执行周期interval),主线程周期性的访问这个node list,如果时间条件满足,执行回调函数。


构造了一个简单node list,便于说明。

 

inline uint64_t get_current_clock(void)

{

    struct timespec tp;

    clock_gettime(CLOCK_MONOTONIC, &tp);

    return (uint64_t)tp.tv_sec * 1e3 + (uint64_t)(tp.tv_nsec / 1e6);

}



static void heap_insert_helper(timer_event_t* heap[], uint32_t idx)

{

    if(idx <= 0) {

        return;

    }

    uint32_t p = (idx - 1) >> 1;

    if(heap[p]->time <= heap[idx]->time) {

        return;

    } else {

        timer_event_t* tmp = heap[p];

        heap[p] = heap[idx];

        heap[idx] = tmp;

        heap_insert_helper(heap, p);

    }

}



static void event_heap_insert(timer_ctx_t* ctx, timer_event_t* evt)

{

    timer_event_t** heap = ctx->heap;

    uint32_t idx = ctx->nevts++;

    heap[idx] = evt;

    heap_insert_helper(heap, idx);

}



static void heap_del_helper(timer_event_t* heap[], uint32_t nevts, uint32_t idx)

{

    if(idx >= nevts) {

        return;

    }



    uint32_t lchild = idx * 2 + 1;

    uint32_t rchild = idx * 2 + 2;

    uint32_t i = idx;



    if(lchild < nevts && (heap[i]->time > heap[lchild]->time)) {

        i = lchild;

    }



    if(rchild < nevts && (heap[i]->time > heap[rchild]->time)) {

        i = rchild;

    }

    

    if(i != idx) {

        timer_event_t* tmp = heap[i];

        heap[i] = heap[idx];

        heap[idx] = tmp;

        heap_del_helper(heap, nevts, i);

    }

}



static timer_event_t* event_heap_pop(timer_ctx_t* ctx)

{

    timer_event_t* evt = ctx->heap[0];

    ctx->heap[0] = ctx->heap[--ctx->nevts];

    heap_del_helper(ctx->heap, ctx->nevts, 0);

    return evt;

}



static void

event_re_enqueue(timer_ctx_t* ctx, timer_event_t* evt)

{

    if(evt->enable && evt->interval > 0) {

        evt->time += evt->interval;

        if(evt->count > 0) {

            evt->count--;

            if(evt->count == 0) {

                evt->interval = 0;

            }

        }

        event_heap_insert(ctx, evt);

    } else {

        mpool_put(evt);

    }

}



void timer_run(timer_ctx_t *ctx)

{

    while(ctx->nevts > 0 

          && ctx->heap[0]->time <= get_current_clock()) {

        timer_event_t *evt = event_heap_pop(ctx);

        if(evt->enable && evt->cb) {

            evt->cb(evt->data);

        }

        event_re_enqueue(ctx, evt);

    }

}



timer_ctx_t* timer_init(timer_ctx_t* ctx)

{

    if(!ctx) {

        return NULL;

    }



    memset(ctx, 0, sizeof(timer_ctx_t));



    //make sure mpool is large enough

    ctx->mpool = mpool_calloc(MAX_EVENT_COUNT, sizeof(timer_event_t));

//    ctx->mpool = mpool_init(sizeof(timer_event_t), 

//            (sizeof(timer_event_t) + sizeof(void*)) * MAX_EVENT_COUNT + 512, 

//            NULL);



    if(!ctx->mpool) {

        goto error;

    }



    return ctx;



error:

    mpool_cleanup(ctx->mpool);

    return NULL;

}



void timer_cleanup(timer_ctx_t *ctx) 

{



    if(!ctx) {

        return;

    }

    mpool_cleanup(ctx->mpool);

    ctx->mpool = NULL;

}



int 

timer_register(

    timer_ctx_t *ctx, 

    timer_cb_t cb, 

    void* data, 

    uint32_t delay, 

    uint32_t interval, 

    uint32_t count)

{

    timer_event_t *evt = NULL;

    if(ctx->nevts >= MAX_EVENT_COUNT) {

        goto err;

    }



    evt = (timer_event_t*)mpool_get(ctx->mpool);

    if(!evt) {

        goto err;

    }

    memset(evt, 0, sizeof(timer_event_t));



    int idx = mpool_get_idx(ctx->mpool, evt);

    if(idx < 0) {

        goto err;

    }



    evt->id = idx;

    evt->time = get_current_clock() + delay;

    evt->cb = cb;

    evt->data = data;

    evt->interval = interval;

    evt->count = count;

    evt->enable = 1;



    event_heap_insert(ctx, evt);

    

    return idx;



err:

    if(evt) {

        mpool_put(evt);

    }    

    return -1;

}



void timer_cancel(timer_ctx_t *ctx, int id)

{

    timer_event_t *evt = mpool_get_by_idx(ctx->mpool, id);

    if(evt) {

        evt->enable = 0;

    }

}


 

 

你可能感兴趣的:(架构设计)