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

📄 fdset.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ====================================================================  * The Kannel Software License, Version 1.0  *  * Copyright (c) 2001-2004 Kannel Group   * Copyright (c) 1998-2001 WapIT Ltd.    * All rights reserved.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  *  * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  *  * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in  *    the documentation and/or other materials provided with the  *    distribution.  *  * 3. The end-user documentation included with the redistribution,  *    if any, must include the following acknowledgment:  *       "This product includes software developed by the  *        Kannel Group (http://www.kannel.org/)."  *    Alternately, this acknowledgment may appear in the software itself,  *    if and wherever such third-party acknowledgments normally appear.  *  * 4. The names "Kannel" and "Kannel Group" must not be used to  *    endorse or promote products derived from this software without  *    prior written permission. For written permission, please   *    contact org@kannel.org.  *  * 5. Products derived from this software may not be called "Kannel",  *    nor may "Kannel" appear in their name, without prior written  *    permission of the Kannel Group.  *  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,   * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT   * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE   * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  * ====================================================================  *  * This software consists of voluntary contributions made by many  * individuals on behalf of the Kannel Group.  For more information on   * the Kannel Group, please see <http://www.kannel.org/>.  *  * Portions of this software are based upon software originally written at   * WapIT Ltd., Helsinki, Finland for the Kannel project.   */ /* * fdset.c - module for managing a large collection of file descriptors */#include <stdlib.h>#include <unistd.h>#include <errno.h>#include "gwlib/gwlib.h"struct FDSet{    /* Thread ID of the set's internal thread, which will spend most     * of its time blocking on poll().  This is set when the thread     * is created, and not changed after that.  It's not protected     * by any lock. */    long poll_thread;    /* The following fields are for use by the polling thread only.     * No-one else may touch them.  It's not protected by any lock. */    /* Array for use with poll().  Elements 0 through size-1 are allocated.     * Elements 0 through entries-1 are in use. */    struct pollfd *pollinfo;    int size;    int entries;    /* Arrays of callback and data fields.  They are kept in sync with     * the pollinfo array, and are basically extra fields that we couldn't     * put in struct pollfd because that structure is defined externally. */    fdset_callback_t **callbacks;    void **datafields;    /* The poller function loops over the table after poll() returns,     * and calls callback functions that may modify the table that is     * being scanned.  We can't just copy the table to avoid interference,     * because fdset_unregister and fdset_listen guarantee that their     * operations are complete when they return -- that does not work     * if poller() is scanning an outdated copy of the table.     * To solve this, we have a field that marks when the table is     * being scanned.  If this field is true, fdset_unregister merely     * sets the fd to -1 instead of deleting the whole entry.     * fdset_listen will takes care to modify revents as well as     * events. fdset_register always adds to the end of the table,     * so it does not have to do anything special.     */    int scanning;    /* This field keeps track of how many fds were set to -1 by     * fdset_unregister while "scanning" is true.  That way we can     * efficiently check if we need to scan the table to really      * delete those entries. */    int deleted_entries;        /* The following fields are for general use, and are of types that     * have internal locks. */    /* List of struct action.  Used by other threads to make requests     * of the polling thread. */    List *actions;};/* Datatype to describe changes to the fdset fields that only the polling * thread may touch.  Other threads use this type to submit requests to * change those fields. *//* Action life cycle: Created, then pushed on set->actions list by * action_submit.  Poller thread wakes up and takes it from the list, * then calls handle_action, which performs the action and pushes it * on the action's done list.  action_submit then takes it back and * destroys it. *//* If no synchronization is needed, action_submit_nosync can be used. * In that case handle_action will destroy the action itself instead * of putting it on any list. */struct action{    enum { REGISTER, LISTEN, UNREGISTER, DESTROY } type;    int fd;                     /* Used by REGISTER, LISTEN, and UNREGISTER */    int mask;                   /* Used by LISTEN */    int events;                 /* Used by REGISTER and LISTEN */    fdset_callback_t *callback; /* Used by REGISTER */    void *data;                 /* Used by REGISTER */    /* When the request has been handled, an element is produced on this     * list, so that the submitter can synchronize.  Can be left NULL. */    List *done;                 /* Used by LISTEN, UNREGISTER, and DESTROY */};/* Return a new action structure of the given type, with all fields empty. */static struct action *action_create(int type){    struct action *new;    new = gw_malloc(sizeof(*new));    new->type = type;    new->fd = -1;    new->mask = 0;    new->events = 0;    new->callback = NULL;    new->data = NULL;    new->done = NULL;    return new;}static void action_destroy(struct action *action){    if (action == NULL)        return;    list_destroy(action->done, NULL);    gw_free(action);}/* For use with list_destroy */static void action_destroy_item(void *action){    action_destroy(action);}/* * Submit an action for this set, and wait for the polling thread to * confirm that it's been done, by pushing the action on its done list. */static void submit_action(FDSet *set, struct action *action){    List *done;    void *sync;    gw_assert(set != NULL);    gw_assert(action != NULL);    done = list_create();    list_add_producer(done);    action->done = done;    list_append(set->actions, action);    gwthread_wakeup(set->poll_thread);    sync = list_consume(done);    gw_assert(sync == action);    action_destroy(action);}/*  * As above, but don't wait for confirmation. */static void submit_action_nosync(FDSet *set, struct action *action){    list_append(set->actions, action);    gwthread_wakeup(set->poll_thread);}/* Do one action for this thread and confirm that it's been done by * appending the action to its done list.  May only be called by * the polling thread.  Returns 0 normally, and returns -1 if the * action destroyed the set. */static int handle_action(FDSet *set, struct action *action){    int result;    gw_assert(set != NULL);    gw_assert(set->poll_thread == gwthread_self());    gw_assert(action != NULL);    result = 0;    switch (action->type) {    case REGISTER:        fdset_register(set, action->fd, action->events,                       action->callback, action->data);        break;    case LISTEN:        fdset_listen(set, action->fd, action->mask, action->events);        break;    case UNREGISTER:        fdset_unregister(set, action->fd);        break;    case DESTROY:        fdset_destroy(set);        result = -1;        break;    default:        panic(0, "fdset: handle_action got unknown action type %d.",              action->type);    }    if (action->done == NULL)	action_destroy(action);    else        list_produce(action->done, action);    return result;}/* Look up the entry number in the pollinfo array for this fd. * Right now it's a linear search, this may have to be improved. */static int find_entry(FDSet *set, int fd){    int i;    gw_assert(set != NULL);

⌨️ 快捷键说明

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