skynet---3---看看

2020-01-06 11:27:36 浏览数 (1)

代码语言:javascript复制
#ifndef SKYNET_HARBOR_H
#define SKYNET_HARBOR_H
#include <stdint.h>
#include <stdlib.h>
#define GLOBALNAME_LENGTH 16
#define REMOTE_MAX 256
// reserve high 8 bits for remote id
#define HANDLE_MASK 0xffffff
#define HANDLE_REMOTE_SHIFT 24
struct remote_name {
    char name[GLOBALNAME_LENGTH];
    uint32_t handle;
};
struct remote_message {
    struct remote_name destination;
    const void * message;
    size_t sz;
};
void skynet_harbor_send(struct remote_message *rmsg, uint32_t source, int session);
void skynet_harbor_register(struct remote_name *rname);
int skynet_harbor_message_isremote(uint32_t handle);
void skynet_harbor_init(int harbor);
int skynet_harbor_start(const char * master, const char *local);
#endif

harbor----港口。。。干嘛的。。。待解。。

代码语言:javascript复制
#include "skynet.h"
#include "skynet_harbor.h"
#include "skynet_server.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
static struct skynet_context * REMOTE = 0;
static unsigned int HARBOR = 0;
void
skynet_harbor_send(struct remote_message *rmsg, uint32_t source, int session) {
    int type = rmsg->sz >> HANDLE_REMOTE_SHIFT;
    rmsg->sz &= HANDLE_MASK;
    assert(type != PTYPE_SYSTEM && type != PTYPE_HARBOR);
    skynet_context_send(REMOTE, rmsg, sizeof(*rmsg) , source, type , session);
}
void
skynet_harbor_register(struct remote_name *rname) {
    int i;
    int number = 1;
    for (i=0;i<GLOBALNAME_LENGTH;i  ) {
        char c = rname->name[i];
        if (!(c >= '0' && c <='9')) {
            number = 0;
            break;
        }
    }
    assert(number == 0);
    skynet_context_send(REMOTE, rname, sizeof(*rname), 0, PTYPE_SYSTEM , 0);
}
int
skynet_harbor_message_isremote(uint32_t handle) {
    int h = (handle & ~HANDLE_MASK);
    return h != HARBOR && h !=0;
}
void
skynet_harbor_init(int harbor) {
    HARBOR = (unsigned int)harbor << HANDLE_REMOTE_SHIFT;
}
int
skynet_harbor_start(const char * master, const char *local) {
    size_t sz = strlen(master)   strlen(local)   32;
    char args[sz];
    sprintf(args, "%s %s %d",master,local,HARBOR >> HANDLE_REMOTE_SHIFT);
    struct skynet_context * inst = skynet_context_new("harbor",args);
    if (inst == NULL) {
        return 1;
    }
    REMOTE = inst;
    return 0;
}

skynet_context都是用这个结构,来交互。。

代码语言:javascript复制
#ifndef SKYNET_CONTEXT_HANDLE_H
#define SKYNET_CONTEXT_HANDLE_H
#include <stdint.h>
#include "skynet_harbor.h"
struct skynet_context;
uint32_t skynet_handle_register(struct skynet_context *);
void skynet_handle_retire(uint32_t handle);
struct skynet_context * skynet_handle_grab(uint32_t handle);
void skynet_handle_retireall();
uint32_t skynet_handle_findname(const char * name);
const char * skynet_handle_namehandle(uint32_t handle, const char *name);
void skynet_handle_init(int harbor);
#endif

哎。。要是有个说明多好。。。刚开始不入门看着真空虚啊。

代码语言:javascript复制
#include "skynet_handle.h"
#include "skynet_server.h"
#include "rwlock.h"
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define DEFAULT_SLOT_SIZE 4
struct handle_name {
    char * name;
    uint32_t handle;
};
struct handle_storage {
    struct rwlock lock;
    uint32_t harbor;
    uint32_t handle_index;
    int slot_size;
    struct skynet_context ** slot;
                                                   
    int name_cap;
    int name_count;
    struct handle_name *name;
};
static struct handle_storage *H = NULL;
uint32_t
skynet_handle_register(struct skynet_context *ctx) {
    struct handle_storage *s = H;
    rwlock_wlock(&s->lock);
                                                   
    for (;;) {
        int i;
        for (i=0;i<s->slot_size;i  ) {
            uint32_t handle = (i s->handle_index) & HANDLE_MASK;
            int hash = handle & (s->slot_size-1);
            if (s->slot[hash] == NULL) {
                s->slot[hash] = ctx;
                s->handle_index = handle   1;
                rwlock_wunlock(&s->lock);
                handle |= s->harbor;
                skynet_context_init(ctx, handle);
                return handle;
            }
        }
        assert((s->slot_size*2 - 1) <= HANDLE_MASK);
        struct skynet_context ** new_slot = malloc(s->slot_size * 2 * sizeof(struct skynet_context *));
        memset(new_slot, 0, s->slot_size * 2 * sizeof(struct skynet_context *));
        for (i=0;i<s->slot_size;i  ) {
            int hash = skynet_context_handle(s->slot[i]) & (s->slot_size * 2 - 1);
            assert(new_slot[hash] == NULL);
            new_slot[hash] = s->slot[i];
        }
        free(s->slot);
        s->slot = new_slot;
        s->slot_size *= 2;
    }
}
void
skynet_handle_retire(uint32_t handle) {
    struct handle_storage *s = H;
    rwlock_wlock(&s->lock);
    uint32_t hash = handle & (s->slot_size-1);
    struct skynet_context * ctx = s->slot[hash];
    if (ctx != NULL && skynet_context_handle(ctx) == handle) {
        skynet_context_release(ctx);
        s->slot[hash] = NULL;
        int i;
        int j=0, n=s->name_count;
        for (i=0; i<n;   i) {
            if (s->name[i].handle == handle) {
                free(s->name[i].name);
                continue;
            } else if (i!=j) {
                s->name[j] = s->name[i];
            }
              j;
        }
        s->name_count = j;
    }
    rwlock_wunlock(&s->lock);
}
void
skynet_handle_retireall() {
    struct handle_storage *s = H;
    for (;;) {
        int n=0;
        int i;
        for (i=0;i<s->slot_size;i  ) {
            rwlock_rlock(&s->lock);
            struct skynet_context * ctx = s->slot[i];
            rwlock_runlock(&s->lock);
            if (ctx != NULL) {
                  n;
                skynet_handle_retire(skynet_context_handle(ctx));
            }
        }
        if (n==0)
            return;
    }
}
struct skynet_context *
skynet_handle_grab(uint32_t handle) {
    struct handle_storage *s = H;
    struct skynet_context * result = NULL;
    rwlock_rlock(&s->lock);
    uint32_t hash = handle & (s->slot_size-1);
    struct skynet_context * ctx = s->slot[hash];
    if (ctx && skynet_context_handle(ctx) == handle) {
        result = ctx;
        skynet_context_grab(result);
    }
    rwlock_runlock(&s->lock);
    return result;
}
uint32_t
skynet_handle_findname(const char * name) {
    struct handle_storage *s = H;
    rwlock_rlock(&s->lock);
    uint32_t handle = 0;
    int begin = 0;
    int end = s->name_count - 1;
    while (begin<=end) {
        int mid = (begin end)/2;
        struct handle_name *n = &s->name[mid];
        int c = strcmp(n->name, name);
        if (c==0) {
            handle = n->handle;
            break;
        }
        if (c<0) {
            begin = mid   1;
        } else {
            end = mid - 1;
        }
    }
    rwlock_runlock(&s->lock);
    return handle;
}
static void
_insert_name_before(struct handle_storage *s, char *name, uint32_t handle, int before) {
    if (s->name_count >= s->name_cap) {
        s->name_cap *= 2;
        struct handle_name * n = malloc(s->name_cap * sizeof(struct handle_name));
        int i;
        for (i=0;i<before;i  ) {
            n[i] = s->name[i];
        }
        for (i=before;i<s->name_count;i  ) {
            n[i 1] = s->name[i];
        }
        free(s->name);
        s->name = n;
    } else {
        int i;
        for (i=s->name_count;i>before;i--) {
            s->name[i] = s->name[i-1];
        }
    }
    s->name[before].name = name;
    s->name[before].handle = handle;
    s->name_count   ;
}
static const char *
_insert_name(struct handle_storage *s, const char * name, uint32_t handle) {
    int begin = 0;
    int end = s->name_count - 1;
    while (begin<=end) {
        int mid = (begin end)/2;
        struct handle_name *n = &s->name[mid];
        int c = strcmp(n->name, name);
        if (c==0) {
            return NULL;
        }
        if (c<0) {
            begin = mid   1;
        } else {
            end = mid - 1;
        }
    }
    char * result = strdup(name);
    _insert_name_before(s, result, handle, begin);
    return result;
}
const char *
skynet_handle_namehandle(uint32_t handle, const char *name) {
    rwlock_wlock(&H->lock);
    const char * ret = _insert_name(H, name, handle);
    rwlock_wunlock(&H->lock);
    return ret;
}
void
skynet_handle_init(int harbor) {
    assert(H==NULL);
    struct handle_storage * s = malloc(sizeof(*H));
    s->slot_size = DEFAULT_SLOT_SIZE;
    s->slot = malloc(s->slot_size * sizeof(struct skynet_context *));
    memset(s->slot, 0, s->slot_size * sizeof(struct skynet_context *));
    rwlock_init(&s->lock);
    // reserve 0 for system
    s->harbor = (uint32_t) (harbor & 0xff) << HANDLE_REMOTE_SHIFT;
    s->handle_index = 1;
    s->name_cap = 2;
    s->name_count = 0;
    s->name = malloc(s->name_cap * sizeof(struct handle_name));
    H = s;
    // Don't need to free H
}

貌似是把handle,name和context对应起来。。。好吧。我没耐心了。。

代码语言:javascript复制
#ifndef SKYNET_MODULE_H
#define SKYNET_MODULE_H
struct skynet_context;
typedef void * (*skynet_dl_create)(void);
typedef int (*skynet_dl_init)(void * inst, struct skynet_context *, const char * parm);
typedef void (*skynet_dl_release)(void * inst);
struct skynet_module {
    const char * name;
    void * module;
    skynet_dl_create create;
    skynet_dl_init init;
    skynet_dl_release release;
};
void skynet_module_insert(struct skynet_module *mod);
struct skynet_module * skynet_module_query(const char * name);
void * skynet_module_instance_create(struct skynet_module *);
int skynet_module_instance_init(struct skynet_module *, void * inst, struct skynet_context *ctx, const char * parm);
void skynet_module_instance_release(struct skynet_module *, void *inst);
void skynet_module_init(const char *path);
#endif

这么抽象的东西。。。模块。。。可以自己实现。。。?

代码语言:javascript复制
#include "skynet_module.h"
#include <assert.h>
#include <string.h>
#include <dlfcn.h>//这个好陌生。。。dll相关函数:dlopen-打开动态链接库
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#define MAX_MODULE_TYPE 32
struct modules {
    int count;
    int lock;
    const char * path;
    struct skynet_module m[MAX_MODULE_TYPE];
};
static struct modules * M = NULL;
static void *
_try_open(struct modules *m, const char * name) {
    const char * path = m->path;
    size_t path_size = strlen(path);
    size_t name_size = strlen(name);
    int sz = path_size   name_size;
    char tmp[sz];
    int i;
    for (i=0;path[i]!='?' && path[i]!='';i  ) {
        tmp[i] = path[i];
    }
    memcpy(tmp i,name,name_size);
    if (path[i] == '?') {
        strcpy(tmp i name_size,path i 1);
    } else {
        fprintf(stderr,"Invalid C service pathn");
        exit(1);
    }
    void * dl = dlopen(tmp, RTLD_NOW | RTLD_GLOBAL);
    if (dl == NULL) {
        fprintf(stderr, "try open %s failed : %sn",tmp,dlerror());
    }
    return dl;
}
static struct skynet_module *
_query(const char * name) {
    int i;
    for (i=0;i<M->count;i  ) {
        if (strcmp(M->m[i].name,name)==0) {
            return &M->m[i];
        }
    }
    return NULL;
}
static int
_open_sym(struct skynet_module *mod) {
    size_t name_size = strlen(mod->name);
    char tmp[name_size   9]; // create/init/release , longest name is release (7)
    memcpy(tmp, mod->name, name_size);
    strcpy(tmp name_size, "_create");
    mod->create = dlsym(mod->module, tmp);
    strcpy(tmp name_size, "_init");
    mod->init = dlsym(mod->module, tmp);
    strcpy(tmp name_size, "_release");
    mod->release = dlsym(mod->module, tmp);
    return mod->init == NULL;
}
struct skynet_module *
skynet_module_query(const char * name) {
    struct skynet_module * result = _query(name);
    if (result)
        return result;
    while(__sync_lock_test_and_set(&M->lock,1)) {}
    result = _query(name); // double check
    if (result == NULL && M->count < MAX_MODULE_TYPE) {
        int index = M->count;
        void * dl = _try_open(M,name);
        if (dl) {
            M->m[index].name = name;
            M->m[index].module = dl;
            if (_open_sym(&M->m[index]) == 0) {
                M->m[index].name = strdup(name);
                M->count   ;
                result = &M->m[index];
            }
        }
    }
    __sync_lock_release(&M->lock);
    return result;
}
void
skynet_module_insert(struct skynet_module *mod) {
    while(__sync_lock_test_and_set(&M->lock,1)) {}
    struct skynet_module * m = _query(mod->name);
    assert(m == NULL && M->count < MAX_MODULE_TYPE);
    int index = M->count;
    M->m[index] = *mod;
      M->count;
    __sync_lock_release(&M->lock);
}
void *
skynet_module_instance_create(struct skynet_module *m) {
    if (m->create) {
        return m->create();
    } else {
        return (void *)(intptr_t)(~0);
    }
}
int
skynet_module_instance_init(struct skynet_module *m, void * inst, struct skynet_context *ctx, const char * parm) {
    return m->init(inst, ctx, parm);
}
void
skynet_module_instance_release(struct skynet_module *m, void *inst) {
    if (m->release) {
        m->release(inst);
    }
}
void
skynet_module_init(const char *path) {
    struct modules *m = malloc(sizeof(*m));
    m->count = 0;
    m->path = strdup(path);
    m->lock = 0;
    M = m;
}

打开dll,模块。。。

0 人点赞