📄 su_win32_port.c
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@ingroup su_wait * @CFILE su_win32_port.c * * Port implementation using WSAEVENTs. Incomplete. * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Kai Vehmanen <kai.vehmanen@nokia.com> * * @date Created: Mon Feb 5 20:29:21 2007 ppessi * @date Original: Tue Sep 14 15:51:04 1999 ppessi */#include "config.h"#define su_port_s su_wsaevent_port_s#include "sofia-sip/su.h"#include "su_port.h"#include "sofia-sip/su_alloc.h"#include <stdlib.h>#include <assert.h>#include <stdarg.h>#include <stdio.h>#include <string.h>#include <limits.h>#include <errno.h>/** Port based on su_wait() aka WSAWaitForMultipleEvents. */#define INDEX_MAX (64)struct su_wsaevent_port_s { su_socket_port_t sup_base[1];#define sup_home sup_base->sup_base->sup_base->sup_home unsigned sup_multishot; /**< Multishot operation? */ unsigned sup_registers; /** Counter incremented by su_port_register() or su_port_unregister() */ int sup_n_waits; /**< Active su_wait_t in su_waits */ int sup_size_waits; /**< Size of allocated su_waits */ int sup_pri_offset; /**< Offset to prioritized waits */ /** Indices from index returned by su_root_register() to tables below. * * Free elements are negative. Free elements form a list, value of free * element is (0 - index of next free element). * * First element sup_indices[0] points to first free element. */ int *sup_indices; int *sup_reverses; /** Reverse index */ su_wakeup_f *sup_wait_cbs; su_wakeup_arg_t**sup_wait_args; su_root_t **sup_wait_roots; su_wait_t *sup_waits; };static void su_wsevent_port_decref(su_port_t *, int blocking, char const *who);static int su_wsevent_port_register(su_port_t *self, su_root_t *root, su_wait_t *wait, su_wakeup_f callback, su_wakeup_arg_t *arg, int priority);static int su_wsevent_port_unregister(su_port_t *port, su_root_t *root, su_wait_t *wait, su_wakeup_f callback, su_wakeup_arg_t *arg);static int su_wsevent_port_deregister(su_port_t *self, int i);static int su_wsevent_port_unregister_all(su_port_t *self, su_root_t *root);static int su_wsevent_port_eventmask(su_port_t *self, int index, int socket, int events);static int su_wsevent_port_multishot(su_port_t *self, int multishot);static int su_wsevent_port_wait_events(su_port_t *self, su_duration_t tout);static char const *su_wsevent_port_name(su_port_t const *self);su_port_vtable_t const su_wsevent_port_vtable[1] = {{ /* su_vtable_size: */ sizeof su_wsevent_port_vtable, su_pthread_port_lock, su_pthread_port_unlock, su_base_port_incref, su_wsevent_port_decref, su_base_port_gsource, su_socket_port_send, su_wsevent_port_register, su_wsevent_port_unregister, su_wsevent_port_deregister, su_wsevent_port_unregister_all, su_wsevent_port_eventmask, su_base_port_run, su_base_port_break, su_base_port_step, su_pthread_port_thread, su_base_port_add_prepoll, su_base_port_remove_prepoll, su_base_port_timers, su_wsevent_port_multishot, su_wsevent_port_wait_events, su_base_port_getmsgs, su_base_port_getmsgs_from, su_wsevent_port_name, su_base_port_start_shared, su_pthread_port_wait, su_pthread_port_execute, }};static char const *su_wsevent_port_name(su_port_t const *self){ return "poll";}static void su_wsevent_port_deinit(void *arg){ su_port_t *self = arg; SU_DEBUG_9(("%s(%p) called\n", "su_wsevent_port_deinit", self)); su_socket_port_deinit(self->sup_base);}static void su_wsevent_port_decref(su_port_t *self, int blocking, char const *who){ su_base_port_decref(self, blocking, who);}/** @internal * * Register a @c su_wait_t object. The wait object, a callback function and * an argument pointer is stored in the port object. The callback function * will be called when the wait object is signaled. * * Please note if identical wait objects are inserted, only first one is * ever signalled. * * @param self pointer to port * @param root pointer to root object * @param waits pointer to wait object * @param callback callback function pointer * @param arg argument given to callback function when it is invoked * @param priority relative priority of the wait object * (0 is normal, 1 important, 2 realtime) * * @return * Positive index of the wait object, * or -1 upon an error. */int su_wsevent_port_register(su_port_t *self, su_root_t *root, su_wait_t *wait, su_wakeup_f callback, su_wakeup_arg_t *arg, int priority){ int i, j, n; assert(su_port_own_thread(self)); n = self->sup_n_waits; if (n >= SU_WAIT_MAX) return su_seterrno(ENOMEM); if (n >= self->sup_size_waits) { su_home_t *h = self->sup_home; /* Reallocate size arrays */ int size; int *indices; int *reverses; su_wait_t *waits; su_wakeup_f *wait_cbs; su_wakeup_arg_t **wait_args; su_root_t **wait_tasks; if (self->sup_size_waits == 0) size = su_root_size_hint; else size = 2 * self->sup_size_waits; if (size < SU_WAIT_MIN) size = SU_WAIT_MIN; /* Too large */ if (-3 - size > 0) return (errno = ENOMEM), -1; indices = su_realloc(h, self->sup_indices, (size + 1) * sizeof(*indices)); if (indices) { self->sup_indices = indices; if (self->sup_size_waits == 0) indices[0] = -1; for (i = self->sup_size_waits + 1; i <= size; i++) indices[i] = -1 - i; } reverses = su_realloc(h, self->sup_reverses, size * sizeof(*waits)); if (reverses) { for (i = self->sup_size_waits; i < size; i++) reverses[i] = -1; self->sup_reverses = reverses; } waits = su_realloc(h, self->sup_waits, size * sizeof(*waits)); if (waits) self->sup_waits = waits; wait_cbs = su_realloc(h, self->sup_wait_cbs, size * sizeof(*wait_cbs)); if (wait_cbs) self->sup_wait_cbs = wait_cbs; wait_args = su_realloc(h, self->sup_wait_args, size * sizeof(*wait_args)); if (wait_args) self->sup_wait_args = wait_args; /* Add sup_wait_roots array, if needed */ wait_tasks = su_realloc(h, self->sup_wait_roots, size * sizeof(*wait_tasks)); if (wait_tasks) self->sup_wait_roots = wait_tasks; if (!(indices && reverses && waits && wait_cbs && wait_args && wait_tasks)) { return -1; } self->sup_size_waits = size; } i = -self->sup_indices[0]; assert(i <= self->sup_size_waits); if (priority > 0) { /* Insert */ for (n = self->sup_n_waits; n > 0; n--) { j = self->sup_reverses[n-1]; assert(self->sup_indices[j] == n - 1); self->sup_indices[j] = n; self->sup_reverses[n] = j; self->sup_waits[n] = self->sup_waits[n-1]; self->sup_wait_cbs[n] = self->sup_wait_cbs[n-1]; self->sup_wait_args[n] = self->sup_wait_args[n-1]; self->sup_wait_roots[n] = self->sup_wait_roots[n-1]; } self->sup_pri_offset++; } else { /* Append - no need to move anything */ n = self->sup_n_waits; } self->sup_n_waits++; self->sup_indices[0] = self->sup_indices[i]; /* Free index */ self->sup_indices[i] = n; self->sup_reverses[n] = i; self->sup_waits[n] = *wait; self->sup_wait_cbs[n] = callback; self->sup_wait_args[n] = arg; self->sup_wait_roots[n] = root; self->sup_registers++; /* Just like epoll, we return -1 or positive integer */ return i;}/** Deregister a su_wait_t object. */static int su_wsevent_port_deregister0(su_port_t *self, int i, int destroy_wait){ int n, N, *indices, *reverses; indices = self->sup_indices; reverses = self->sup_reverses; n = indices[i]; assert(n >= 0); if (destroy_wait) su_wait_destroy(&self->sup_waits[n]); N = --self->sup_n_waits; if (n < self->sup_pri_offset) { int j = --self->sup_pri_offset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -