skynet---4--看看

#ifndef SKYNET_MONITOR_H
#define SKYNET_MONITOR_H
#include <stdint.h>
struct skynet_monitor;
struct skynet_monitor * skynet_monitor_new();
void skynet_monitor_delete(struct skynet_monitor *);
void skynet_monitor_trigger(struct skynet_monitor *, uint32_t source, uint32_t destination);
void skynet_monitor_check(struct skynet_monitor *);
#endif


#include "skynet_monitor.h"
#include "skynet_server.h"
#include "skynet.h"
#include <stdlib.h>
#include <string.h>
struct skynet_monitor {
    int version;
    int check_version;
    uint32_t source;
    uint32_t destination;
};
struct skynet_monitor *
skynet_monitor_new() {
    struct skynet_monitor * ret = malloc(sizeof(*ret));
    memset(ret, 0, sizeof(*ret));
    return ret;
}
void
skynet_monitor_delete(struct skynet_monitor *sm) {
    free(sm);
}
void
skynet_monitor_trigger(struct skynet_monitor *sm, uint32_t source, uint32_t destination) {
    sm->source = source;
    sm->destination = destination;
    __sync_fetch_and_add(&sm->version , 1);
}
void
skynet_monitor_check(struct skynet_monitor *sm) {
    if (sm->version == sm->check_version) {
        if (sm->destination) {
            skynet_context_endless(sm->destination);
            skynet_error(NULL, "A message from [ :%08x ] to [ :%08x ] maybe in an endless loop", sm->source , sm->destination);
        }
    } else {
        sm->check_version = sm->version;
    }
}



沒看明白。。。


#ifndef SKYNET_MESSAGE_QUEUE_H
#define SKYNET_MESSAGE_QUEUE_H
#include <stdlib.h>
#include <stdint.h>
struct skynet_message {
    uint32_t source;
    int session;
    void * data;
    size_t sz;
};
struct message_queue;
struct message_queue * skynet_globalmq_pop(void);
struct message_queue * skynet_mq_create(uint32_t handle);
void skynet_mq_mark_release(struct message_queue *q);
int skynet_mq_release(struct message_queue *q);
uint32_t skynet_mq_handle(struct message_queue *);
// 0 for success
int skynet_mq_pop(struct message_queue *q, struct skynet_message *message);
void skynet_mq_push(struct message_queue *q, struct skynet_message *message);
void skynet_mq_lock(struct message_queue *q, int session);
void skynet_mq_unlock(struct message_queue *q);
void skynet_mq_force_push(struct message_queue *q);
void skynet_mq_pushglobal(struct message_queue *q);
void skynet_mq_init();
#endif



消息隊列。。


#include "skynet.h"
#include "skynet_mq.h"
#include "skynet_handle.h"
#include "skynet_multicast.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
#define DEFAULT_QUEUE_SIZE 64
#define MAX_GLOBAL_MQ 0x10000
// 0 means mq is not in global mq.
// 1 means mq is in global mq , or the message is dispatching.
// 2 means message is dispatching with locked session set.
// 3 means mq is not in global mq, and locked session has been set.
#define MQ_IN_GLOBAL 1
#define MQ_DISPATCHING 2
#define MQ_LOCKED 3
struct message_queue {
    uint32_t handle;
    int cap;
    int head;
    int tail;
    int lock;
    int release;
    int lock_session;
    int in_global;
    struct skynet_message *queue;
};
struct global_queue {
    uint32_t head;
    uint32_t tail;
    struct message_queue ** queue;
    bool * flag;
};
static struct global_queue *Q = NULL;
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
#define GP(p) ((p) % MAX_GLOBAL_MQ)
static void
skynet_globalmq_push(struct message_queue * queue) {
    struct global_queue *q= Q;
    uint32_t tail = GP(__sync_fetch_and_add(&q->tail,1));
    q->queue[tail] = queue;
    __sync_synchronize();
    q->flag[tail] = true;
}
struct message_queue *
skynet_globalmq_pop() {
    struct global_queue *q = Q;
    uint32_t head =  q->head;
    uint32_t head_ptr = GP(head);
    if (head_ptr == GP(q->tail)) {
        return NULL;
    }
    if(!q->flag[head_ptr]) {
        return NULL;
    }
    __sync_synchronize();
    struct message_queue * mq = q->queue[head_ptr];
    if (!__sync_bool_compare_and_swap(&q->head, head, head+1)) {
        return NULL;
    }
    q->flag[head_ptr] = false;
    return mq;
}
struct message_queue *
skynet_mq_create(uint32_t handle) {
    struct message_queue *q = malloc(sizeof(*q));
    q->handle = handle;
    q->cap = DEFAULT_QUEUE_SIZE;
    q->head = 0;
    q->tail = 0;
    q->lock = 0;
    q->in_global = MQ_IN_GLOBAL;
    q->release = 0;
    q->lock_session = 0;
    q->queue = malloc(sizeof(struct skynet_message) * q->cap);
    return q;
}
static void
_release(struct message_queue *q) {
    free(q->queue);
    free(q);
}
uint32_t
skynet_mq_handle(struct message_queue *q) {
    return q->handle;
}
int
skynet_mq_pop(struct message_queue *q, struct skynet_message *message) {
    int ret = 1;
    LOCK(q)
    if (q->head != q->tail) {
        *message = q->queue[q->head];
        ret = 0;
        if ( ++ q->head >= q->cap) {
            q->head = 0;
        }
    }
    if (ret) {
        q->in_global = 0;
    }
                                                        
    UNLOCK(q)
    return ret;
}
static void
expand_queue(struct message_queue *q) {
    struct skynet_message *new_queue = malloc(sizeof(struct skynet_message) * q->cap * 2);
    int i;
    for (i=0;i<q->cap;i++) {
        new_queue[i] = q->queue[(q->head + i) % q->cap];
    }
    q->head = 0;
    q->tail = q->cap;
    q->cap *= 2;
                                                        
    free(q->queue);
    q->queue = new_queue;
}
static void
_unlock(struct message_queue *q) {
    // this api use in push a unlock message, so the in_global flags must not be 0 ,
    // but the q is not exist in global queue.
    if (q->in_global == MQ_LOCKED) {
        skynet_globalmq_push(q);
        q->in_global = MQ_IN_GLOBAL;
    } else {
        assert(q->in_global == MQ_DISPATCHING);
    }
    q->lock_session = 0;
}
static void
_pushhead(struct message_queue *q, struct skynet_message *message) {
    int head = q->head - 1;
    if (head < 0) {
        head = q->cap - 1;
    }
    if (head == q->tail) {
        expand_queue(q);
        --q->tail;
        head = q->cap - 1;
    }
    q->queue[head] = *message;
    q->head = head;
    _unlock(q);
}
void
skynet_mq_push(struct message_queue *q, struct skynet_message *message) {
    assert(message);
    LOCK(q)
                                                        
    if (q->lock_session !=0 && message->session == q->lock_session) {
        _pushhead(q,message);
    } else {
        q->queue[q->tail] = *message;
        if (++ q->tail >= q->cap) {
            q->tail = 0;
        }
        if (q->head == q->tail) {
            expand_queue(q);
        }
        if (q->lock_session == 0) {
            if (q->in_global == 0) {
                q->in_global = MQ_IN_GLOBAL;
                skynet_globalmq_push(q);
            }
        }
    }
                                                        
    UNLOCK(q)
}
void
skynet_mq_lock(struct message_queue *q, int session) {
    LOCK(q)
    assert(q->lock_session == 0);
    assert(q->in_global == MQ_IN_GLOBAL);
    q->in_global = MQ_DISPATCHING;
    q->lock_session = session;
    UNLOCK(q)
}
void
skynet_mq_unlock(struct message_queue *q) {
    LOCK(q)
    _unlock(q);
    UNLOCK(q)
}
void
skynet_mq_init() {
    struct global_queue *q = malloc(sizeof(*q));
    memset(q,0,sizeof(*q));
    q->queue = malloc(MAX_GLOBAL_MQ * sizeof(struct message_queue *));
    q->flag = malloc(MAX_GLOBAL_MQ * sizeof(bool));
    memset(q->flag, 0, sizeof(bool) * MAX_GLOBAL_MQ);
    Q=q;
}
void
skynet_mq_force_push(struct message_queue * queue) {
    assert(queue->in_global);
    skynet_globalmq_push(queue);
}
void
skynet_mq_pushglobal(struct message_queue *queue) {
    LOCK(queue)
    assert(queue->in_global);
    if (queue->in_global == MQ_DISPATCHING) {
        // lock message queue just now.
        queue->in_global = MQ_LOCKED;
    }
    if (queue->lock_session == 0) {
        skynet_globalmq_push(queue);
        queue->in_global = MQ_IN_GLOBAL;
    }
    UNLOCK(queue)
}
void
skynet_mq_mark_release(struct message_queue *q) {
    LOCK(q)
    assert(q->release == 0);
    q->release = 1;
    if (q->in_global != MQ_IN_GLOBAL) {
        skynet_globalmq_push(q);
    }
    UNLOCK(q)
}
static int
_drop_queue(struct message_queue *q) {
    // todo: send message back to message source
    struct skynet_message msg;
    int s = 0;
    while(!skynet_mq_pop(q, &msg)) {
        ++s;
        int type = msg.sz >> HANDLE_REMOTE_SHIFT;
        if (type == PTYPE_MULTICAST) {
            assert((msg.sz & HANDLE_MASK) == 0);
            skynet_multicast_dispatch((struct skynet_multicast_message *)msg.data, NULL, NULL);
        } else {
            free(msg.data);
        }
    }
    _release(q);
    return s;
}
int
skynet_mq_release(struct message_queue *q) {
    int ret = 0;
    LOCK(q)
                                                        
    if (q->release) {
        UNLOCK(q)
        ret = _drop_queue(q);
    } else {
        skynet_mq_force_push(q);
        UNLOCK(q)
    }
                                                        
    return ret;
}



又是這麼高深,,全局隊列,非全局隊列,locked,unlocked。。。

都集合到一起來了。。

#ifndef SKYNET_GROUP_H
#define SKYNET_GROUP_H
#include <stdint.h>
uint32_t skynet_group_query(int handle);
void skynet_group_enter(int handle, uint32_t node);
void skynet_group_leave(int handle, uint32_t node);
void skynet_group_clear(int handle);
void skynet_group_init();
#endif


#include "skynet_group.h"
#include "skynet_multicast.h"
#include "skynet_server.h"
#include "skynet.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#define HASH_SIZE 1024
struct group_node {
    int handle;
    struct skynet_context *ctx;
    struct group_node * next;
};
struct group {
    int lock;
    struct group_node * node[HASH_SIZE];
};
struct group * _G = NULL;
inline static void
_lock(struct group *g) {
    while (__sync_lock_test_and_set(&g->lock,1)) {}
}
inline static void
_unlock(struct group *g) {
    __sync_lock_release(&g->lock);
}
static struct skynet_context *
_create_group(struct group * g, int handle) {
    int hash = handle % HASH_SIZE;
    struct skynet_context * inst = skynet_context_new("multicast",NULL);
    assert(inst);
    struct group_node * new_node = malloc(sizeof(struct group_node));
    new_node->handle = handle;
    new_node->ctx = inst;
    new_node->next = g->node[hash];
    g->node[hash] = new_node;
    return inst;
}
uint32_t
skynet_group_query(int handle) {
    struct group *g = _G;
    _lock(g);
                                             
    int hash = handle % HASH_SIZE;
    struct group_node * node = g->node[hash];
    while (node) {
        if (node->handle == handle) {
            struct skynet_context * ctx = node->ctx;
            uint32_t addr = skynet_context_handle(ctx);
            _unlock(g);
            return addr;
        }
        node = node->next;
    }
    struct skynet_context * ctx = _create_group(g, handle);
    uint32_t addr = skynet_context_handle(ctx);
    _unlock(g);
    return addr;
}
static void
send_command(struct skynet_context *ctx, const char * cmd, uint32_t node) {
    char * tmp = malloc(16);
    int n = sprintf(tmp, "%s %x", cmd, node);
    skynet_context_send(ctx, tmp, n+1 , 0, PTYPE_SYSTEM, 0);
}
void
skynet_group_enter(int handle, uint32_t n) {
    struct group *g = _G;
    _lock(g);
    int hash = handle % HASH_SIZE;
    struct group_node * node = g->node[hash];
    while (node) {
        if (node->handle == handle) {
            send_command(node->ctx, "E", n);
            _unlock(g);
            return;
        }
        node = node->next;
    }
    struct skynet_context * inst = _create_group(g, handle);
    send_command(inst, "E", n);
    _unlock(g);
}
void
skynet_group_leave(int handle, uint32_t n) {
    struct group *g = _G;
    _lock(g);
    int hash = handle % HASH_SIZE;
    struct group_node * node = g->node[hash];
    while (node) {
        if (node->handle == handle) {
            send_command(node->ctx, "L", n);
            break;
        }
        node = node->next;
    }
    _unlock(g);
}
void
skynet_group_clear(int handle) {
    struct group *g = _G;
    _lock(g);
    int hash = handle % HASH_SIZE;
    struct group_node ** pnode = &g->node[hash];
    while (*pnode) {
        struct group_node * node = *pnode;
        if (node->handle == handle) {
            struct skynet_context * ctx = node->ctx;
                                                     
            char * cmd = malloc(8);
            int n = sprintf(cmd, "C");
            skynet_context_send(ctx, cmd, n+1, 0 , PTYPE_SYSTEM, 0);
            *pnode = node->next;
            free(node);
            break;
        }
        pnode = &node->next;
    }
    _unlock(g);
}
void
skynet_group_init() {
    struct group * g = malloc(sizeof(*g));
    memset(g,0,sizeof(*g));
    _G = g;
}


看來這個就是分佈式,組。。命令定義好簡單,呵呵C,L,E。。。。

#ifndef SKYNET_MULTICAST_H
#define SKYNET_MULTICAST_H
#include <stddef.h>
#include <stdint.h>
struct skynet_multicast_message;
struct skynet_multicast_group;
struct skynet_context;
typedef void (*skynet_multicast_func)(void *ud, uint32_t source, const void * msg, size_t sz);
struct skynet_multicast_message * skynet_multicast_create(const void * msg, size_t sz, uint32_t source);
void skynet_multicast_copy(struct skynet_multicast_message *, int copy);
void skynet_multicast_dispatch(struct skynet_multicast_message * msg, void * ud, skynet_multicast_func func);
void skynet_multicast_cast(struct skynet_context * from, struct skynet_multicast_message *msg, const uint32_t *dests, int n);
struct skynet_multicast_group * skynet_multicast_newgroup();
void skynet_multicast_deletegroup(struct skynet_multicast_group * group);
void skynet_multicast_entergroup(struct skynet_multicast_group * group, uint32_t handle);
void skynet_multicast_leavegroup(struct skynet_multicast_group * group, uint32_t handle);
int skynet_multicast_castgroup(struct skynet_context * from, struct skynet_multicast_group * group, struct skynet_multicast_message *msg);
#endif


廣播組。。。

#include "skynet.h"
#include "skynet_multicast.h"
#include "skynet_server.h"
#include "skynet_handle.h"
#include <stdlib.h>
#include <string.h>
struct skynet_multicast_message {
    int ref;
    const void * msg;
    size_t sz;
    uint32_t source;
};
struct skynet_multicast_message *
skynet_multicast_create(const void * msg, size_t sz, uint32_t source) {
    struct skynet_multicast_message * mc = malloc(sizeof(*mc));
    mc->ref = 0;
    mc->msg = msg;
    mc->sz = sz;
    mc->source = source;
    return mc;
}
void
skynet_multicast_copy(struct skynet_multicast_message *mc, int copy) {
    int r = __sync_add_and_fetch(&mc->ref, copy);
    if (r == 0) {
        free((void *)mc->msg);
        free(mc);
    }
}
void
skynet_multicast_dispatch(struct skynet_multicast_message * msg, void * ud, skynet_multicast_func func) {
    if (func) {
        func(ud, msg->source, msg->msg, msg->sz);
    }
    int ref = __sync_sub_and_fetch(&msg->ref, 1);
    if (ref == 0) {
        free((void *)msg->msg);
        free(msg);
    }
}
struct array {
    int cap;
    int number;
    uint32_t *data;
};
struct skynet_multicast_group {
    struct array enter_queue;
    struct array leave_queue;
    int cap;
    int number;
    uint32_t * data;
};
struct skynet_multicast_group *
skynet_multicast_newgroup() {
    struct skynet_multicast_group * g = malloc(sizeof(*g));
    memset(g,0,sizeof(*g));
    return g;
}
void
skynet_multicast_deletegroup(struct skynet_multicast_group * g) {
    free(g->data);
    free(g->enter_queue.data);
    free(g->leave_queue.data);
    free(g);
}
static void
push_array(struct array * a, uint32_t v) {
    if (a->number >= a->cap) {
        a->cap *= 2;
        if (a->cap == 0) {
            a->cap = 4;
        }
        a->data = realloc(a->data, a->cap * sizeof(uint32_t));
    }
    a->data[a->number++] = v;
}
void
skynet_multicast_entergroup(struct skynet_multicast_group * group, uint32_t handle) {
    push_array(&group->enter_queue, handle);
}
void
skynet_multicast_leavegroup(struct skynet_multicast_group * group, uint32_t handle) {
    push_array(&group->leave_queue, handle);
}
static int
compar_uint(const void *a, const void *b) {
    const uint32_t * aa = a;
    const uint32_t * bb = b;
    return (int)(*aa - *bb);
}
static void
combine_queue(struct skynet_context * from, struct skynet_multicast_group * group) {
    qsort(group->enter_queue.data, group->enter_queue.number, sizeof(uint32_t), compar_uint);
    qsort(group->leave_queue.data, group->leave_queue.number, sizeof(uint32_t), compar_uint);
    int i;
    int enter = group->enter_queue.number;
    uint32_t last = 0;
    int new_size = group->number + enter;
    if (new_size > group->cap) {
        group->data = realloc(group->data, new_size * sizeof(uint32_t));
        group->cap = new_size;
    }
    // combine enter queue
    int old_index = group->number - 1;
    int new_index = new_size - 1;
    for (i= enter - 1;i >=0 ; i--) {
        uint32_t handle = group->enter_queue.data[i];
        if (handle == last)
            continue;
        last = handle;
        if (old_index < 0) {
            group->data[new_index] = handle;
        } else {
            uint32_t p = group->data[old_index];
            if (handle == p)
                continue;
            if (handle > p) {
                group->data[new_index] = handle;
            } else {
                group->data[new_index] = group->data[old_index];
                --old_index;
                last = 0;
                ++i;
            }
        }
        --new_index;
    }
    while (old_index >= 0) {
        group->data[new_index] = group->data[old_index];
        --old_index;
        --new_index;
    }
    group->enter_queue.number = 0;
    // remove leave queue
    old_index = new_index + 1;
    new_index = 0;
    int count = new_size - old_index;
    int leave = group->leave_queue.number;
    for (i=0;i<leave;i++) {
        if (old_index >= new_size) {
            count = 0;
            break;
        }
        uint32_t handle = group->leave_queue.data[i];
        uint32_t p = group->data[old_index];
        if (handle == p) {
            --count;
            ++old_index;
        } else if ( handle > p) {
            group->data[new_index] = group->data[old_index];
            ++new_index;
            ++old_index;
            --i;
        } else {
            skynet_error(from, "Try to remove a none exist handle : %x", handle);
        }
    }
    while (new_index < count) {
        group->data[new_index] = group->data[old_index];
        ++new_index;
        ++old_index;
    }
    group->leave_queue.number = 0;
    group->number = new_index;
}
int
skynet_multicast_castgroup(struct skynet_context * from, struct skynet_multicast_group * group, struct skynet_multicast_message *msg) {
    combine_queue(from, group);
    int release = 0;
    if (group->number > 0) {
        uint32_t source = skynet_context_handle(from);
        skynet_multicast_copy(msg, group->number);
        int i;
        for (i=0;i<group->number;i++) {
            uint32_t p = group->data[i];
            struct skynet_context * ctx = skynet_handle_grab(p);
            if (ctx) {
                skynet_context_send(ctx, msg, 0 , source, PTYPE_MULTICAST , 0);
                skynet_context_release(ctx);
            } else {
                skynet_multicast_leavegroup(group, p);
                ++release;
            }
        }
    }
                             
    skynet_multicast_copy(msg, -release);
                             
    return group->number - release;
}
void
skynet_multicast_cast(struct skynet_context * from, struct skynet_multicast_message *msg, const uint32_t *dests, int n) {
    uint32_t source = skynet_context_handle(from);
    skynet_multicast_copy(msg, n);
    if (n == 0)
        return;
    int i;
    int release = 0;
    for (i=0;i<n;i++) {
        uint32_t p = dests[i];
        struct skynet_context * ctx = skynet_handle_grab(p);
        if (ctx) {
            skynet_context_send(ctx, msg, 0 , source, PTYPE_MULTICAST , 0);
            skynet_context_release(ctx);
        } else {
            ++release;
        }
    }
    if (release != 0) {
        skynet_multicast_copy(msg, -release);
    }
}



哎。。好無註釋。。。看着好悲劇。。。

第一遍,是在看不明白。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章