su_port.h

Go to the documentation of this file.
00001 /*
00002  * This file is part of the Sofia-SIP package
00003  *
00004  * Copyright (C) 2005 Nokia Corporation.
00005  *
00006  * Contact: Pekka Pessi <pekka.pessi@nokia-email.address.hidden>
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public License
00010  * as published by the Free Software Foundation; either version 2.1 of
00011  * the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00021  * 02110-1301 USA
00022  *
00023  */
00024 
00025 #ifndef SU_PORT_H
00026 
00027 #define SU_PORT_H
00028 
00040 #ifndef SU_MSG_ARG_T
00041 #define SU_MSG_ARG_T union { char anoymous[4]; }
00042 #endif
00043 
00044 #ifndef SU_WAIT_H
00045 #include "sofia-sip/su_wait.h"
00046 #endif
00047 
00048 #ifndef SU_MODULE_DEBUG_H
00049 #include "su_module_debug.h"
00050 #endif
00051 
00052 #ifndef SU_ALLOC_H
00053 #include <sofia-sip/su_alloc.h>
00054 #endif
00055 
00056 #include <assert.h>
00057 
00058 #define SU_WAIT_MIN    (16)
00059 
00060 SOFIA_BEGIN_DECLS
00061 
00063 struct su_msg_s {
00064   isize_t        sum_size;
00065   su_msg_t      *sum_next;
00066   su_task_r      sum_to;
00067   su_task_r      sum_from;
00068   su_msg_f       sum_func;
00069   su_msg_f       sum_report;
00070   su_msg_arg_t   sum_data[1];           /* minimum size, may be extended */
00071 };
00072 
00073 struct _GSource;
00074 
00076 struct su_root_s {
00077   int              sur_size;
00078   su_root_magic_t *sur_magic;
00079   su_root_deinit_f sur_deinit;
00080   su_task_r        sur_task;
00081   su_task_r        sur_parent;
00082   unsigned         sur_threading : 1;
00083   unsigned         sur_deiniting : 1;
00084 };
00085 
00086 #define SU_ROOT_MAGIC(r) ((r) ? (r)->sur_magic : NULL)
00087 
00089 typedef struct su_port_vtable {
00090   unsigned su_vtable_size;
00091   void (*su_port_lock)(su_port_t *port, char const *who);
00092   void (*su_port_unlock)(su_port_t *port, char const *who);
00093   void (*su_port_incref)(su_port_t *port, char const *who);
00094   void (*su_port_decref)(su_port_t *port, int block, char const *who);
00095   struct _GSource *(*su_port_gsource)(su_port_t *port);
00096   int (*su_port_send)(su_port_t *self, su_msg_r rmsg);
00097   int (*su_port_register)(su_port_t *self,
00098                        su_root_t *root, 
00099                        su_wait_t *wait, 
00100                        su_wakeup_f callback,
00101                        su_wakeup_arg_t *arg,
00102                        int priority);
00103   int (*su_port_unregister)(su_port_t *port,
00104                             su_root_t *root, 
00105                             su_wait_t *wait,    
00106                             su_wakeup_f callback, 
00107                             su_wakeup_arg_t *arg);
00108   int (*su_port_deregister)(su_port_t *self, int i);
00109   int (*su_port_unregister_all)(su_port_t *self,
00110                              su_root_t *root);
00111   int (*su_port_eventmask)(su_port_t *self, int index, int socket, int events);
00112   void (*su_port_run)(su_port_t *self);
00113   void (*su_port_break)(su_port_t *self);
00114   su_duration_t (*su_port_step)(su_port_t *self, su_duration_t tout);
00115   
00116   int (*su_port_own_thread)(su_port_t const *port);
00117   
00118   int (*su_port_add_prepoll)(su_port_t *port,
00119                              su_root_t *root, 
00120                              su_prepoll_f *, 
00121                              su_prepoll_magic_t *);
00122   
00123   int (*su_port_remove_prepoll)(su_port_t *port,
00124                                 su_root_t *root);
00125 
00126   su_timer_t **(*su_port_timers)(su_port_t *port);
00127 
00128   int (*su_port_multishot)(su_port_t *port, int multishot);
00129 
00130   int (*su_port_threadsafe)(su_port_t *port);
00131   /* Extension from > 1.12.0 */
00132   int (*su_port_yield)(su_port_t *port);
00133   /* Extension from >= 1.12.4 */
00134   int (*su_port_wait_events)(su_port_t *port, su_duration_t timeout);
00135   int (*su_port_getmsgs)(su_port_t *port);
00136   /* Extension from >= 1.12.5 */
00137   int (*su_port_getmsgs_from)(su_port_t *port, su_port_t *cloneport);
00138   char const *(*su_port_name)(su_port_t const *port);
00139   int (*su_port_start_shared)(su_root_t *root,
00140                               su_clone_r return_clone,
00141                               su_root_magic_t *magic,
00142                               su_root_init_f init,
00143                               su_root_deinit_f deinit);
00144   void (*su_port_wait)(su_clone_r rclone);
00145   int (*su_port_execute)(su_task_r const task,
00146                          int (*function)(void *), void *arg,
00147                          int *return_value);  
00148 } su_port_vtable_t;
00149 
00150 SOFIAPUBFUN su_port_t *su_port_create(void)
00151      __attribute__((__malloc__));
00152 
00153 /* Extension from >= 1.12.5 */
00154 
00155 SOFIAPUBFUN void su_msg_delivery_report(su_msg_r msg);
00156 SOFIAPUBFUN su_duration_t su_timer_next_expires(su_timer_t const * t,
00157                                                 su_time_t now);
00158 SOFIAPUBFUN su_root_t *su_root_create_with_port(su_root_magic_t *magic,
00159                                                 su_port_t *port)
00160   __attribute__((__malloc__));
00161 
00162 /* Extension from >= 1.12.6 */
00163 
00164 SOFIAPUBFUN char const *su_port_name(su_port_t const *port);
00165 
00166 /* ---------------------------------------------------------------------- */
00167 
00168 /* React to multiple events per one poll() to make sure 
00169  * that high-priority events can never completely mask other events.
00170  * Enabled by default on all platforms except WIN32 */
00171 #if !defined(WIN32)
00172 #define SU_ENABLE_MULTISHOT_POLL 1
00173 #else
00174 #define SU_ENABLE_MULTISHOT_POLL 0
00175 #endif
00176 
00177 /* ---------------------------------------------------------------------- */
00178 /* Virtual functions */
00179 
00180 typedef struct su_virtual_port_s {
00181   su_home_t        sup_home[1];
00182   su_port_vtable_t const *sup_vtable;
00183 } su_virtual_port_t;
00184 
00185 su_inline
00186 su_home_t *su_port_home(su_port_t const *self)
00187 {
00188   return (su_home_t *)self;
00189 }
00190 
00191 su_inline
00192 void su_port_lock(su_port_t *self, char const *who)
00193 {
00194   su_virtual_port_t *base = (su_virtual_port_t *)self;
00195   if (base) base->sup_vtable->su_port_lock(self, who);
00196 }
00197 
00198 su_inline
00199 void su_port_unlock(su_port_t *self, char const *who)
00200 {
00201   su_virtual_port_t *base = (su_virtual_port_t *)self;
00202   if (base) base->sup_vtable->su_port_unlock(self, who);
00203 }
00204 
00205 su_inline
00206 void su_port_incref(su_port_t *self, char const *who)
00207 {
00208   su_virtual_port_t *base = (su_virtual_port_t *)self;
00209   if (base) base->sup_vtable->su_port_incref(self, who);
00210 }
00211 
00212 su_inline
00213 void su_port_decref(su_port_t *self, char const *who)
00214 {
00215   su_virtual_port_t *base = (su_virtual_port_t *)self;
00216   if (base) base->sup_vtable->su_port_decref(self, 0, who);
00217 }
00218 
00219 su_inline
00220 void su_port_zapref(su_port_t *self, char const *who)
00221 {
00222   su_virtual_port_t *base = (su_virtual_port_t *)self;
00223   if (base) base->sup_vtable->su_port_decref(self, 1, who);
00224 }
00225 
00226 su_inline
00227 struct _GSource *su_port_gsource(su_port_t *self)
00228 {
00229   su_virtual_port_t *base = (su_virtual_port_t *)self;
00230   return base ? base->sup_vtable->su_port_gsource(self) : NULL;
00231 }
00232 
00233 su_inline
00234 int su_port_send(su_port_t *self, su_msg_r rmsg)
00235 {
00236   su_virtual_port_t *base = (su_virtual_port_t *)self;
00237   if (base) 
00238     return base->sup_vtable->su_port_send(self, rmsg);
00239   errno = EINVAL;
00240   return -1;
00241 }
00242 
00243 
00244 su_inline
00245 int su_port_register(su_port_t *self,
00246                      su_root_t *root, 
00247                      su_wait_t *wait, 
00248                      su_wakeup_f callback,
00249                      su_wakeup_arg_t *arg,
00250                      int priority)
00251 {
00252   su_virtual_port_t *base = (su_virtual_port_t *)self;
00253   if (base)
00254     return base->sup_vtable->su_port_register(self, root, wait,
00255                                               callback, arg, priority);
00256   errno = EINVAL;
00257   return -1;
00258 }
00259 
00260 su_inline
00261 int su_port_unregister(su_port_t *self,
00262                        su_root_t *root, 
00263                        su_wait_t *wait, 
00264                        su_wakeup_f callback, 
00265                        su_wakeup_arg_t *arg)
00266 {
00267   su_virtual_port_t *base = (su_virtual_port_t *)self;
00268   if (base)
00269     return base->sup_vtable->
00270       su_port_unregister(self, root, wait, callback, arg);
00271   errno = EINVAL;
00272   return -1;
00273 }
00274 
00275 su_inline
00276 int su_port_deregister(su_port_t *self, int i)
00277 {
00278   su_virtual_port_t *base = (su_virtual_port_t *)self;
00279   if (base)
00280     return base->sup_vtable->su_port_deregister(self, i);
00281   errno = EINVAL;
00282   return -1;
00283 }
00284 
00285 su_inline
00286 int su_port_unregister_all(su_port_t *self,
00287                            su_root_t *root)
00288 {
00289   su_virtual_port_t *base = (su_virtual_port_t *)self;
00290   if (base)
00291     return base->sup_vtable->
00292       su_port_unregister_all(self, root);
00293   errno = EINVAL;
00294   return -1;
00295 }
00296 
00297 su_inline
00298 int su_port_eventmask(su_port_t *self, int index, int socket, int events)
00299 {
00300   su_virtual_port_t *base = (su_virtual_port_t *)self;
00301   if (base)
00302     return base->sup_vtable->
00303       su_port_eventmask(self, index, socket, events);
00304   assert(base);
00305   errno = EINVAL;
00306   return -1;
00307 }
00308 
00309 su_inline
00310 void su_port_run(su_port_t *self)
00311 {
00312   su_virtual_port_t *base = (su_virtual_port_t *)self;
00313   if (base)
00314     base->sup_vtable->su_port_run(self);
00315 }
00316 
00317 su_inline
00318 void su_port_break(su_port_t *self)
00319 {
00320   su_virtual_port_t *base = (su_virtual_port_t *)self;
00321   if (base)
00322     base->sup_vtable->su_port_break(self);
00323 }
00324 
00325 su_inline
00326 su_duration_t su_port_step(su_port_t *self, su_duration_t tout)
00327 {
00328   su_virtual_port_t *base = (su_virtual_port_t *)self;
00329   if (base)
00330     return base->sup_vtable->su_port_step(self, tout);
00331   errno = EINVAL;
00332   return (su_duration_t)-1;
00333 }
00334 
00335 
00336 su_inline
00337 int su_port_own_thread(su_port_t const *self)
00338 {
00339   su_virtual_port_t const *base = (su_virtual_port_t *)self;
00340   return base == NULL || base->sup_vtable->su_port_own_thread(self);
00341 }
00342 
00343 su_inline
00344 int su_port_add_prepoll(su_port_t *self,
00345                         su_root_t *root, 
00346                         su_prepoll_f *prepoll, 
00347                         su_prepoll_magic_t *magic)
00348 {
00349   su_virtual_port_t *base = (su_virtual_port_t *)self;
00350   if (base)
00351     return base->sup_vtable->
00352       su_port_add_prepoll(self, root, prepoll, magic);
00353   errno = EINVAL;
00354   return -1;
00355 }
00356 
00357 su_inline
00358 int su_port_remove_prepoll(su_port_t *self,
00359                            su_root_t *root)
00360 {
00361   su_virtual_port_t *base = (su_virtual_port_t *)self;
00362   if (base)
00363     return base->sup_vtable->su_port_remove_prepoll(self, root);
00364   errno = EINVAL;
00365   return -1;
00366 }
00367 
00368 su_inline
00369 su_timer_t **su_port_timers(su_port_t *self)
00370 {
00371   su_virtual_port_t *base = (su_virtual_port_t *)self;
00372   if (base)
00373     return base->sup_vtable->su_port_timers(self);
00374   errno = EINVAL;
00375   return NULL;
00376 }
00377 
00378 su_inline
00379 int su_port_multishot(su_port_t *self, int multishot)
00380 {
00381   su_virtual_port_t *base = (su_virtual_port_t *)self;
00382   if (base)
00383     return base->sup_vtable->su_port_multishot(self, multishot);
00384 
00385   assert(base);
00386   errno = EINVAL;
00387   return -1;
00388 }
00389 
00390 su_inline
00391 int su_port_threadsafe(su_port_t *self)
00392 {
00393   su_virtual_port_t *base = (su_virtual_port_t *)self;
00394   if (base)
00395     return base->sup_vtable->su_port_threadsafe(self);
00396 
00397   assert(base);
00398   errno = EINVAL;
00399   return -1;
00400 }
00401 
00402 su_inline
00403 int su_port_getmsgs(su_port_t *self)
00404 {
00405   su_virtual_port_t *base = (su_virtual_port_t *)self;
00406 
00407   return base->sup_vtable->su_port_getmsgs(self);
00408 }
00409 
00410 su_inline
00411 int su_port_getmsgs_from(su_port_t *self, su_port_t *cloneport)
00412 {
00413   su_virtual_port_t *base = (su_virtual_port_t *)self;
00414 
00415   return base->sup_vtable->su_port_getmsgs_from(self, cloneport);
00416 }
00417 
00418 SOFIAPUBFUN void su_port_wait(su_clone_r rclone);
00419 
00420 SOFIAPUBFUN int su_port_execute(su_task_r const task,
00421                                 int (*function)(void *), void *arg,
00422                                 int *return_value);
00423 
00424 /* ---------------------------------------------------------------------- */
00425 
00431 typedef struct su_base_port_s {
00432   su_home_t        sup_home[1];
00433   su_port_vtable_t const *sup_vtable;
00434 
00435   /* Implementation may vary stuff below, too. */
00436   
00437   /* Pre-poll callback */
00438   su_prepoll_f    *sup_prepoll; 
00439   su_prepoll_magic_t *sup_pp_magic;
00440   su_root_t       *sup_pp_root;
00441 
00442   /* Message list - this is protected by su_port_lock()/su_port_unlock() */
00443   su_msg_t        *sup_head, **sup_tail;
00444 
00445   /* Timer list */
00446   su_timer_t      *sup_timers;
00447 
00448   unsigned         sup_running;   
00449 } su_base_port_t;
00450 
00451 /* Base methods */
00452 
00453 SOFIAPUBFUN int su_base_port_init(su_port_t *, su_port_vtable_t const *);
00454 SOFIAPUBFUN void su_base_port_deinit(su_port_t *self);
00455 
00456 SOFIAPUBFUN void su_base_port_lock(su_port_t *self, char const *who);
00457 SOFIAPUBFUN void su_base_port_unlock(su_port_t *self, char const *who);
00458 
00459 SOFIAPUBFUN int su_base_port_own_thread(su_port_t const *self);
00460 
00461 SOFIAPUBFUN void su_base_port_incref(su_port_t *self, char const *who);
00462 SOFIAPUBFUN int su_base_port_decref(su_port_t *self,
00463                                     int blocking,
00464                                     char const *who);
00465 
00466 SOFIAPUBFUN struct _GSource *su_base_port_gsource(su_port_t *self);
00467 
00468 SOFIAPUBFUN su_socket_t su_base_port_mbox(su_port_t *self);
00469 SOFIAPUBFUN int su_base_port_send(su_port_t *self, su_msg_r rmsg);
00470 SOFIAPUBFUN int su_base_port_getmsgs(su_port_t *self);
00471 SOFIAPUBFUN int su_base_port_getmsgs_from(su_port_t *self,
00472                                            su_port_t *from);
00473 
00474 SOFIAPUBFUN void su_base_port_run(su_port_t *self);
00475 SOFIAPUBFUN void su_base_port_break(su_port_t *self);
00476 SOFIAPUBFUN su_duration_t su_base_port_step(su_port_t *self,
00477                                             su_duration_t tout);
00478 
00479 SOFIAPUBFUN int su_base_port_add_prepoll(su_port_t *self,
00480                                          su_root_t *root, 
00481                                          su_prepoll_f *, 
00482                                          su_prepoll_magic_t *);
00483 
00484 SOFIAPUBFUN int su_base_port_remove_prepoll(su_port_t *self, su_root_t *root);
00485 
00486 SOFIAPUBFUN su_timer_t **su_base_port_timers(su_port_t *self);
00487 
00488 SOFIAPUBFUN int su_base_port_multishot(su_port_t *self, int multishot);
00489 SOFIAPUBFUN int su_base_port_threadsafe(su_port_t *self);
00490 SOFIAPUBFUN int su_base_port_yield(su_port_t *self);
00491 
00492 SOFIAPUBFUN int su_base_port_start_shared(su_root_t *parent,
00493                                           su_clone_r return_clone,
00494                                           su_root_magic_t *magic,
00495                                           su_root_init_f init,
00496                                           su_root_deinit_f deinit);
00497 SOFIAPUBFUN void su_base_port_wait(su_clone_r rclone);
00498 
00499 /* ---------------------------------------------------------------------- */
00500 
00501 #if SU_HAVE_PTHREADS
00502 
00503 #include <pthread.h>
00504 
00506 typedef struct su_pthread_port_s {
00507   su_base_port_t   sup_base[1];
00508   struct su_pthread_port_waiting_parent 
00509                   *sup_waiting_parent;
00510   pthread_t        sup_tid;
00511 #if 0
00512   pthread_mutex_t  sup_runlock[1];
00513   pthread_cond_t   sup_resume[1];
00514   short            sup_paused;  
00515 #endif
00516   short            sup_thread;  
00517 } su_pthread_port_t;
00518 
00519 /* Pthread methods */
00520 
00521 SOFIAPUBFUN int su_pthread_port_init(su_port_t *, su_port_vtable_t const *);
00522 SOFIAPUBFUN void su_pthread_port_deinit(su_port_t *self);
00523 
00524 SOFIAPUBFUN void su_pthread_port_lock(su_port_t *self, char const *who);
00525 SOFIAPUBFUN void su_pthread_port_unlock(su_port_t *self, char const *who);
00526 
00527 SOFIAPUBFUN int su_pthread_port_own_thread(su_port_t const *self);
00528 
00529 #if 0                           /* not yet  */
00530 SOFIAPUBFUN int su_pthread_port_send(su_port_t *self, su_msg_r rmsg);
00531 
00532 SOFIAPUBFUN su_port_t *su_pthread_port_create(void);
00533 SOFIAPUBFUN su_port_t *su_pthread_port_start(su_root_t *parent,
00534                                              su_clone_r return_clone,
00535                                              su_root_magic_t *magic,
00536                                              su_root_init_f init,
00537                                              su_root_deinit_f deinit);
00538 #endif
00539 
00540 SOFIAPUBFUN int su_pthreaded_port_start(su_port_create_f *create,
00541                                         su_root_t *parent,
00542                                         su_clone_r return_clone,
00543                                         su_root_magic_t *magic,
00544                                         su_root_init_f init,
00545                                         su_root_deinit_f deinit);
00546 
00547 SOFIAPUBFUN void su_pthread_port_wait(su_clone_r rclone);
00548 SOFIAPUBFUN int su_pthread_port_execute(su_task_r const task,
00549                                         int (*function)(void *), void *arg,
00550                                         int *return_value);
00551 
00552 
00553 #if 0
00554 SOFIAPUBFUN int su_pthread_port_pause(su_port_t *self);
00555 SOFIAPUBFUN int su_pthread_port_resume(su_port_t *self);
00556 #endif
00557 
00558 #else
00559 
00560 typedef su_base_port_t su_pthread_port_t;
00561 
00562 #define su_pthread_port_init   su_base_port_init
00563 #define su_pthread_port_deinit su_base_port_deinit
00564 #define su_pthread_port_lock   su_base_port_lock
00565 #define su_pthread_port_unlock su_base_port_unlock
00566 #define su_pthread_port_own_thread su_base_port_own_thread
00567 #define su_pthread_port_wait   su_base_port_wait
00568 #define su_pthread_port_execute  su_base_port_execute
00569 
00570 #endif
00571 
00572 /* ====================================================================== */
00573 /* Mailbox port using sockets */
00574 
00575 #define SU_MBOX_SIZE 2
00576 
00577 typedef struct su_socket_port_s {
00578   su_pthread_port_t sup_base[1];
00579   int               sup_mbox_index;
00580   su_socket_t       sup_mbox[SU_MBOX_SIZE];
00581 } su_socket_port_t;
00582 
00583 SOFIAPUBFUN int su_socket_port_init(su_socket_port_t *, 
00584                                     su_port_vtable_t const *);
00585 SOFIAPUBFUN void su_socket_port_deinit(su_socket_port_t *self);
00586 SOFIAPUBFUN int su_socket_port_send(su_port_t *self, su_msg_r rmsg);
00587 
00588 SOFIA_END_DECLS
00589 
00590 #endif /* SU_PORT_H */

Sofia-SIP 1.12.6 - Copyright (C) 2006 Nokia Corporation. All rights reserved. Licensed under the terms of the GNU Lesser General Public License.