⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fdset.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 2 页
字号:
    gw_assert(gwthread_self() == set->poll_thread);    for (i = 0; i < set->entries; i++) {        if (set->pollinfo[i].fd == fd)            return i;    }    return -1;}static void remove_entry(FDSet *set, int entry){    if (entry != set->entries - 1) {        /* We need to keep the array contiguous, so move the last element         * to fill in the hole. */        set->pollinfo[entry] = set->pollinfo[set->entries - 1];        set->callbacks[entry] = set->callbacks[set->entries - 1];        set->datafields[entry] = set->datafields[set->entries - 1];    }    set->entries--;}static void remove_deleted_entries(FDSet *set){    int i;    i = 0;    while (i < set->entries && set->deleted_entries > 0) {        if (set->pollinfo[i].fd < 0) {            remove_entry(set, i);	    set->deleted_entries--;	} else {	    i++;        }    }}/* Main function for polling thread.  Most its time is spent blocking * in poll().  No-one else is allowed to change the fields it uses, * so other threads just put something on the actions list and wake * up this thread.  That's why it checks the actions list every time * it goes through the loop. */static void poller(void *arg){    FDSet *set = arg;    struct action *action;    int ret;    int i;    gw_assert(set != NULL);    for (;;) {        while ((action = list_extract_first(set->actions)) != NULL) {            /* handle_action returns -1 if the set was destroyed. */            if (handle_action(set, action) < 0)                return;        }        /* Block indefinitely, waiting for activity */        ret = gwthread_poll(set->pollinfo, set->entries, -1.0);        if (ret < 0) {	    if (errno != EINTR) {                error(0, "Poller: can't handle error; sleeping 1 second.");                gwthread_sleep(1.0);            }            continue;        }	/* Callbacks may modify the table while we scan it, so be careful. */	set->scanning = 1;        for (i = 0; i < set->entries; i++) {            if (set->pollinfo[i].revents != 0)                set->callbacks[i](set->pollinfo[i].fd,                                  set->pollinfo[i].revents,                                  set->datafields[i]);        }	set->scanning = 0;	if (set->deleted_entries > 0)	    remove_deleted_entries(set);    }}FDSet *fdset_create(void){    FDSet *new;    new = gw_malloc(sizeof(*new));    /* Start off with space for one element because we can't malloc 0 bytes     * and we don't want to worry about these pointers being NULL. */    new->size = 1;    new->entries = 0;    new->pollinfo = gw_malloc(sizeof(new->pollinfo[0]) * new->size);    new->callbacks = gw_malloc(sizeof(new->callbacks[0]) * new->size);    new->datafields = gw_malloc(sizeof(new->datafields[0]) * new->size);    new->scanning = 0;    new->deleted_entries = 0;    new->actions = list_create();    new->poll_thread = gwthread_create(poller, new);    if (new->poll_thread < 0) {        error(0, "Could not start internal thread for fdset.");        fdset_destroy(new);        return NULL;    }    return new;}void fdset_destroy(FDSet *set){    if (set == NULL)        return;    if (set->poll_thread < 0 || gwthread_self() == set->poll_thread) {        if (set->entries > 0) {            warning(0, "Destroying fdset with %d active entries.",                    set->entries);        }        gw_free(set->pollinfo);        gw_free(set->callbacks);        gw_free(set->datafields);        if (list_len(set->actions) > 0) {            error(0, "Destroying fdset with %ld pending actions.",                  list_len(set->actions));        }        list_destroy(set->actions, action_destroy_item);        gw_free(set);    } else {        long thread = set->poll_thread;        submit_action(set, action_create(DESTROY));	gwthread_join(thread);    }}void fdset_register(FDSet *set, int fd, int events,                    fdset_callback_t callback, void *data){    int new;    gw_assert(set != NULL);    if (gwthread_self() != set->poll_thread) {        struct action *action;        action = action_create(REGISTER);        action->fd = fd;        action->events = events;        action->callback = callback;        action->data = data;	submit_action_nosync(set, action);        return;    }    gw_assert(set->entries <= set->size);    if (set->entries >= set->size) {        int newsize = set->entries + 1;        set->pollinfo = gw_realloc(set->pollinfo,                                   sizeof(set->pollinfo[0]) * newsize);        set->callbacks = gw_realloc(set->callbacks,                                   sizeof(set->callbacks[0]) * newsize);        set->datafields = gw_realloc(set->datafields,                                   sizeof(set->datafields[0]) * newsize);        set->size = newsize;    }    /* We don't check set->scanning.  Adding new entries is not harmful     * because their revents fields are 0. */    new = set->entries++;    set->pollinfo[new].fd = fd;    set->pollinfo[new].events = events;    set->pollinfo[new].revents = 0;    set->callbacks[new] = callback;    set->datafields[new] = data;}void fdset_listen(FDSet *set, int fd, int mask, int events){    int entry;    gw_assert(set != NULL);    if (gwthread_self() != set->poll_thread) {        struct action *action;        action = action_create(LISTEN);        action->fd = fd;	action->mask = mask;        action->events = events;        submit_action(set, action);        return;    }    entry = find_entry(set, fd);       if (entry < 0) {        warning(0, "fdset_listen called on unregistered fd %d.", fd);        return;    }    /* Copy the bits from events specified by the mask, and preserve the     * bits not specified by the mask. */    set->pollinfo[entry].events =	(set->pollinfo[entry].events & ~mask) | (events & mask);    /* If poller is currently scanning the array, then change the     * revents field so that the callback function will not be called     * for events we should no longer listen for.  The idea is the     * same as for the events field, except that we only turn bits off. */    if (set->scanning) {        set->pollinfo[entry].revents =            set->pollinfo[entry].revents & (events | ~mask);    }}void fdset_unregister(FDSet *set, int fd){    int entry;    gw_assert(set != NULL);    if (gwthread_self() != set->poll_thread) {        struct action *action;        action = action_create(UNREGISTER);        action->fd = fd;        submit_action(set, action);        return;    }    /* Remove the entry from the pollinfo array */    entry = find_entry(set, fd);    if (entry < 0) {        warning(0, "fdset_listen called on unregistered fd %d.", fd);        return;    }    if (entry == set->entries - 1) {        /* It's the last entry.  We can safely remove it even while         * the array is being scanned, because the scan checks set->entries. */        set->entries--;    } else if (set->scanning) {        /* We can't remove entries because the array is being         * scanned.  Mark it as deleted.  */        set->pollinfo[entry].fd = -1;        set->deleted_entries++;    } else {        remove_entry(set, entry);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -