su_port.h

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 
00088 enum su_port_thread_op {
00089   su_port_thread_op_is_obtained,
00090   su_port_thread_op_release,
00091   su_port_thread_op_obtain
00092 };
00093   
00095 typedef struct su_port_vtable {
00096   unsigned su_vtable_size;
00097   void (*su_port_lock)(su_port_t *port, char const *who);
00098   void (*su_port_unlock)(su_port_t *port, char const *who);
00099   void (*su_port_incref)(su_port_t *port, char const *who);
00100   void (*su_port_decref)(su_port_t *port, int block, char const *who);
00101   struct _GSource *(*su_port_gsource)(su_port_t *port);
00102   int (*su_port_send)(su_port_t *self, su_msg_r rmsg);
00103   int (*su_port_register)(su_port_t *self,
00104                        su_root_t *root, 
00105                        su_wait_t *wait, 
00106                        su_wakeup_f callback,
00107                        su_wakeup_arg_t *arg,
00108                        int priority);
00109   int (*su_port_unregister)(su_port_t *port,
00110                             su_root_t *root, 
00111                             su_wait_t *wait,    
00112                             su_wakeup_f callback, 
00113                             su_wakeup_arg_t *arg);
00114   int (*su_port_deregister)(su_port_t *self, int i);
00115   int (*su_port_unregister_all)(su_port_t *self,
00116                              su_root_t *root);
00117   int (*su_port_eventmask)(su_port_t *self, int index, int socket, int events);
00118   void (*su_port_run)(su_port_t *self);
00119   void (*su_port_break)(su_port_t *self);
00120   su_duration_t (*su_port_step)(su_port_t *self, su_duration_t tout);
00121   
00122   /* Reused slot */
00123   int (*su_port_thread)(su_port_t *port, enum su_port_thread_op op);
00124   
00125   int (*su_port_add_prepoll)(su_port_t *port,
00126                              su_root_t *root, 
00127                              su_prepoll_f *, 
00128                              su_prepoll_magic_t *);
00129   
00130   int (*su_port_remove_prepoll)(su_port_t *port,
00131                                 su_root_t *root);
00132 
00133   su_timer_t **(*su_port_timers)(su_port_t *port);
00134 
00135   int (*su_port_multishot)(su_port_t *port, int multishot);
00136 
00137   int (*su_port_threadsafe)(su_port_t *port);
00138   /* Extension from > 1.12.0 */
00139   int (*su_port_yield)(su_port_t *port);
00140   /* Extension from >= 1.12.4 */
00141   int (*su_port_wait_events)(su_port_t *port, su_duration_t timeout);
00142   int (*su_port_getmsgs)(su_port_t *port);
00143   /* Extension from >= 1.12.5 */
00144   int (*su_port_getmsgs_from)(su_port_t *port, su_port_t *cloneport);
00145   char const *(*su_port_name)(su_port_t const *port);
00146   int (*su_port_start_shared)(su_root_t *root,
00147                               su_clone_r return_clone,
00148                               su_root_magic_t *magic,
00149                               su_root_init_f init,
00150                               su_root_deinit_f deinit);
00151   void (*su_port_wait)(su_clone_r rclone);
00152   int (*su_port_execute)(su_task_r const task,
00153                          int (*function)(void *), void *arg,
00154                          int *return_value);  
00155 } su_port_vtable_t;
00156 
00157 SOFIAPUBFUN su_port_t *su_port_create(void)
00158      __attribute__((__malloc__));
00159 
00160 /* Extension from >= 1.12.5 */
00161 
00162 SOFIAPUBFUN void su_msg_delivery_report(su_msg_r msg);
00163 SOFIAPUBFUN su_duration_t su_timer_next_expires(su_timer_t const * t,
00164                                                 su_time_t now);
00165 SOFIAPUBFUN su_root_t *su_root_create_with_port(su_root_magic_t *magic,
00166                                                 su_port_t *port)
00167   __attribute__((__malloc__));
00168 
00169 /* Extension from >= 1.12.6 */
00170 
00171 SOFIAPUBFUN char const *su_port_name(su_port_t const *port);
00172 
00173 /* ---------------------------------------------------------------------- */
00174 
00175 /* React to multiple events per one poll() to make sure 
00176  * that high-priority events can never completely mask other events.
00177  * Enabled by default on all platforms except WIN32 */
00178 #if !defined(WIN32)
00179 #define SU_ENABLE_MULTISHOT_POLL 1
00180 #else
00181 #define SU_ENABLE_MULTISHOT_POLL 0
00182 #endif
00183 
00184 /* ---------------------------------------------------------------------- */
00185 /* Virtual functions */
00186 
00187 typedef struct su_virtual_port_s {
00188   su_home_t        sup_home[1];
00189   su_port_vtable_t const *sup_vtable;
00190 } su_virtual_port_t;
00191 
00192 su_inline
00193 su_home_t *su_port_home(su_port_t const *self)
00194 {
00195   return (su_home_t *)self;
00196 }
00197 
00198 su_inline
00199 void su_port_lock(su_port_t *self, char const *who)
00200 {
00201   su_virtual_port_t *base = (su_virtual_port_t *)self;
00202   base->sup_vtable->su_port_lock(self, who);
00203 }
00204 
00205 su_inline
00206 void su_port_unlock(su_port_t *self, char const *who)
00207 {
00208   su_virtual_port_t *base = (su_virtual_port_t *)self;
00209   base->sup_vtable->su_port_unlock(self, who);
00210 }
00211 
00212 su_inline
00213 void su_port_incref(su_port_t *self, char const *who)
00214 {
00215   su_virtual_port_t *base = (su_virtual_port_t *)self;
00216   base->sup_vtable->su_port_incref(self, who);
00217 }
00218 
00219 su_inline
00220 void su_port_decref(su_port_t *self, char const *who)
00221 {
00222   su_virtual_port_t *base = (su_virtual_port_t *)self;
00223   base->sup_vtable->su_port_decref(self, 0, who);
00224 }
00225 
00226 su_inline
00227 void su_port_zapref(su_port_t *self, char const *who)
00228 {
00229   su_virtual_port_t *base = (su_virtual_port_t *)self;
00230   base->sup_vtable->su_port_decref(self, 1, who);
00231 }
00232 
00233 su_inline
00234 struct _GSource *su_port_gsource(su_port_t *self)
00235 {
00236   su_virtual_port_t *base = (su_virtual_port_t *)self;
00237   return base->sup_vtable->su_port_gsource(self);
00238 }
00239 
00240 su_inline
00241 int su_port_send(su_port_t *self, su_msg_r rmsg)
00242 {
00243   su_virtual_port_t *base = (su_virtual_port_t *)self;
00244   return base->sup_vtable->su_port_send(self, rmsg);
00245 }
00246 
00247 
00248 su_inline
00249 int su_port_register(su_port_t *self,
00250                      su_root_t *root, 
00251                      su_wait_t *wait, 
00252                      su_wakeup_f callback,
00253                      su_wakeup_arg_t *arg,
00254                      int priority)
00255 {
00256   su_virtual_port_t *base = (su_virtual_port_t *)self;
00257   return base->sup_vtable->
00258     su_port_register(self, root, wait, callback, arg, priority);
00259 }
00260 
00261 su_inline
00262 int su_port_unregister(su_port_t *self,
00263                        su_root_t *root, 
00264                        su_wait_t *wait, 
00265                        su_wakeup_f callback, 
00266                        su_wakeup_arg_t *arg)
00267 {
00268   su_virtual_port_t *base = (su_virtual_port_t *)self;
00269   return base->sup_vtable->
00270     su_port_unregister(self, root, wait, callback, arg);
00271 }
00272 
00273 su_inline
00274 int su_port_deregister(su_port_t *self, int i)
00275 {
00276   su_virtual_port_t *base = (su_virtual_port_t *)self;
00277   return base->sup_vtable->
00278     su_port_deregister(self, i);
00279 }
00280 
00281 su_inline
00282 int su_port_unregister_all(su_port_t *self,
00283                            su_root_t *root)
00284 {
00285   su_virtual_port_t *base = (su_virtual_port_t *)self;
00286   return base->sup_vtable->
00287     su_port_unregister_all(self, root);
00288 }
00289 
00290 su_inline
00291 int su_port_eventmask(su_port_t *self, int index, int socket, int events)
00292 {
00293   su_virtual_port_t *base = (su_virtual_port_t *)self;
00294   return base->sup_vtable->
00295     su_port_eventmask(self, index, socket, events);
00296 }
00297 
00298 su_inline
00299 int su_port_wait_events(su_port_t *self, su_duration_t timeout)
00300 {
00301   su_virtual_port_t *base = (su_virtual_port_t *)self;
00302   if (base->sup_vtable->su_port_wait_events == NULL)
00303     return errno = ENOSYS, -1;
00304   return base->sup_vtable->
00305     su_port_wait_events(self, timeout);
00306 }
00307 
00308 su_inline
00309 void su_port_run(su_port_t *self)
00310 {
00311   su_virtual_port_t *base = (su_virtual_port_t *)self;
00312   base->sup_vtable->su_port_run(self);
00313 }
00314 
00315 su_inline
00316 void su_port_break(su_port_t *self)
00317 {
00318   su_virtual_port_t *base = (su_virtual_port_t *)self;
00319   base->sup_vtable->su_port_break(self);
00320 }
00321 
00322 su_inline
00323 su_duration_t su_port_step(su_port_t *self, su_duration_t tout)
00324 {
00325   su_virtual_port_t *base = (su_virtual_port_t *)self;
00326   return base->sup_vtable->su_port_step(self, tout);
00327 }
00328 
00329 
00330 su_inline
00331 int su_port_own_thread(su_port_t const *self)
00332 {
00333   su_virtual_port_t const *base = (su_virtual_port_t *)self;
00334   return base->sup_vtable->
00335     su_port_thread((su_port_t *)self, su_port_thread_op_is_obtained) == 2;
00336 }
00337 
00338 su_inline int su_port_has_thread(su_port_t *self)
00339 {
00340   su_virtual_port_t *base = (su_virtual_port_t *)self;
00341   return base->sup_vtable->su_port_thread(self, su_port_thread_op_is_obtained);
00342 }
00343 
00344 su_inline int su_port_release(su_port_t *self)
00345 {
00346   su_virtual_port_t *base = (su_virtual_port_t *)self;
00347   return base->sup_vtable->su_port_thread(self, su_port_thread_op_release);
00348 }
00349 
00350 su_inline int su_port_obtain(su_port_t *self)
00351 {
00352   su_virtual_port_t *base = (su_virtual_port_t *)self;
00353   return base->sup_vtable->su_port_thread(self, su_port_thread_op_obtain);
00354 }
00355 
00356 su_inline
00357 int su_port_add_prepoll(su_port_t *self,
00358                         su_root_t *root, 
00359                         su_prepoll_f *prepoll, 
00360                         su_prepoll_magic_t *magic)
00361 {
00362   su_virtual_port_t *base = (su_virtual_port_t *)self;
00363   return base->sup_vtable->su_port_add_prepoll(self, root, prepoll, magic);
00364 }
00365 
00366 su_inline
00367 int su_port_remove_prepoll(su_port_t *self,
00368                            su_root_t *root)
00369 {
00370   su_virtual_port_t *base = (su_virtual_port_t *)self;
00371   return base->sup_vtable->su_port_remove_prepoll(self, root);
00372 }
00373 
00374 su_inline
00375 su_timer_t **su_port_timers(su_port_t *self)
00376 {
00377   su_virtual_port_t *base = (su_virtual_port_t *)self;
00378   return base->sup_vtable->su_port_timers(self);
00379 }
00380 
00381 su_inline
00382 int su_port_multishot(su_port_t *self, int multishot)
00383 {
00384   su_virtual_port_t *base = (su_virtual_port_t *)self;
00385   return base->sup_vtable->su_port_multishot(self, multishot);
00386 }
00387 
00388 su_inline
00389 int su_port_threadsafe(su_port_t *self)
00390 {
00391   su_virtual_port_t *base = (su_virtual_port_t *)self;
00392   return base->sup_vtable->su_port_threadsafe(self);
00393 }
00394 
00395 su_inline
00396 int su_port_getmsgs(su_port_t *self)
00397 {
00398   su_virtual_port_t *base = (su_virtual_port_t *)self;
00399   return base->sup_vtable->su_port_getmsgs(self);
00400 }
00401 
00402 su_inline
00403 int su_port_getmsgs_from(su_port_t *self, su_port_t *cloneport)
00404 {
00405   su_virtual_port_t *base = (su_virtual_port_t *)self;
00406   return base->sup_vtable->su_port_getmsgs_from(self, cloneport);
00407 }
00408 
00409 SOFIAPUBFUN void su_port_wait(su_clone_r rclone);
00410 
00411 SOFIAPUBFUN int su_port_execute(su_task_r const task,
00412                                 int (*function)(void *), void *arg,
00413                                 int *return_value);
00414 
00415 /* ---------------------------------------------------------------------- */
00416 
00422 typedef struct su_base_port_s {
00423   su_home_t        sup_home[1];
00424   su_port_vtable_t const *sup_vtable;
00425 
00426   /* Implementation may vary stuff below, too. */
00427   
00428   /* Pre-poll callback */
00429   su_prepoll_f    *sup_prepoll; 
00430   su_prepoll_magic_t *sup_pp_magic;
00431   su_root_t       *sup_pp_root;
00432 
00433   /* Message list - this is protected by su_port_lock()/su_port_unlock() */
00434   su_msg_t        *sup_head, **sup_tail;
00435 
00436   /* Timer list */
00437   su_timer_t      *sup_timers;
00438 
00439   unsigned         sup_running;   
00440 } su_base_port_t;
00441 
00442 /* Base methods */
00443 
00444 SOFIAPUBFUN int su_base_port_init(su_port_t *, su_port_vtable_t const *);
00445 SOFIAPUBFUN void su_base_port_deinit(su_port_t *self);
00446 
00447 SOFIAPUBFUN void su_base_port_lock(su_port_t *self, char const *who);
00448 SOFIAPUBFUN void su_base_port_unlock(su_port_t *self, char const *who);
00449 
00450 SOFIAPUBFUN int su_base_port_thread(su_port_t const *self,
00451                                     enum su_port_thread_op op);
00452 
00453 SOFIAPUBFUN void su_base_port_incref(su_port_t *self, char const *who);
00454 SOFIAPUBFUN int su_base_port_decref(su_port_t *self,
00455                                     int blocking,
00456                                     char const *who);
00457 
00458 SOFIAPUBFUN struct _GSource *su_base_port_gsource(su_port_t *self);
00459 
00460 SOFIAPUBFUN su_socket_t su_base_port_mbox(su_port_t *self);
00461 SOFIAPUBFUN int su_base_port_send(su_port_t *self, su_msg_r rmsg);
00462 SOFIAPUBFUN int su_base_port_getmsgs(su_port_t *self);
00463 SOFIAPUBFUN int su_base_port_getmsgs_from(su_port_t *self,
00464                                            su_port_t *from);
00465 
00466 SOFIAPUBFUN void su_base_port_run(su_port_t *self);
00467 SOFIAPUBFUN void su_base_port_break(su_port_t *self);
00468 SOFIAPUBFUN su_duration_t su_base_port_step(su_port_t *self,
00469                                             su_duration_t tout);
00470 
00471 SOFIAPUBFUN int su_base_port_add_prepoll(su_port_t *self,
00472                                          su_root_t *root, 
00473                                          su_prepoll_f *, 
00474                                          su_prepoll_magic_t *);
00475 
00476 SOFIAPUBFUN int su_base_port_remove_prepoll(su_port_t *self, su_root_t *root);
00477 
00478 SOFIAPUBFUN su_timer_t **su_base_port_timers(su_port_t *self);
00479 
00480 SOFIAPUBFUN int su_base_port_multishot(su_port_t *self, int multishot);
00481 
00482 SOFIAPUBFUN int su_base_port_threadsafe(su_port_t *self);
00483 
00484 SOFIAPUBFUN int su_base_port_yield(su_port_t *self);
00485 
00486 SOFIAPUBFUN int su_base_port_start_shared(su_root_t *parent,
00487                                           su_clone_r return_clone,
00488                                           su_root_magic_t *magic,
00489                                           su_root_init_f init,
00490                                           su_root_deinit_f deinit);
00491 SOFIAPUBFUN void su_base_port_wait(su_clone_r rclone);
00492 
00493 /* ---------------------------------------------------------------------- */
00494 
00495 #if SU_HAVE_PTHREADS
00496 
00497 #include <pthread.h>
00498 
00500 typedef struct su_pthread_port_s {
00501   su_base_port_t   sup_base[1];
00502   struct su_pthread_port_waiting_parent 
00503                   *sup_waiting_parent;
00504   pthread_t        sup_tid;
00505   pthread_mutex_t  sup_obtained[1];
00506 
00507 #if 0
00508   pthread_mutex_t  sup_runlock[1];
00509   pthread_cond_t   sup_resume[1];
00510   short            sup_paused;  
00511 #endif
00512   short            sup_thread;  
00513 } su_pthread_port_t;
00514 
00515 /* Pthread methods */
00516 
00517 SOFIAPUBFUN int su_pthread_port_init(su_port_t *, su_port_vtable_t const *);
00518 SOFIAPUBFUN void su_pthread_port_deinit(su_port_t *self);
00519 
00520 SOFIAPUBFUN void su_pthread_port_lock(su_port_t *self, char const *who);
00521 SOFIAPUBFUN void su_pthread_port_unlock(su_port_t *self, char const *who);
00522 
00523 SOFIAPUBFUN int su_pthread_port_thread(su_port_t *self,
00524                                        enum su_port_thread_op op);
00525 
00526 #if 0                           /* not yet  */
00527 SOFIAPUBFUN int su_pthread_port_send(su_port_t *self, su_msg_r rmsg);
00528 
00529 SOFIAPUBFUN su_port_t *su_pthread_port_create(void);
00530 SOFIAPUBFUN su_port_t *su_pthread_port_start(su_root_t *parent,
00531                                              su_clone_r return_clone,
00532                                              su_root_magic_t *magic,
00533                                              su_root_init_f init,
00534                                              su_root_deinit_f deinit);
00535 #endif
00536 
00537 SOFIAPUBFUN int su_pthreaded_port_start(su_port_create_f *create,
00538                                         su_root_t *parent,
00539                                         su_clone_r return_clone,
00540                                         su_root_magic_t *magic,
00541                                         su_root_init_f init,
00542                                         su_root_deinit_f deinit);
00543 
00544 SOFIAPUBFUN void su_pthread_port_wait(su_clone_r rclone);
00545 SOFIAPUBFUN int su_pthread_port_execute(su_task_r const task,
00546                                         int (*function)(void *), void *arg,
00547                                         int *return_value);
00548 
00549 
00550 #if 0
00551 SOFIAPUBFUN int su_pthread_port_pause(su_port_t *self);
00552 SOFIAPUBFUN int su_pthread_port_resume(su_port_t *self);
00553 #endif
00554 
00555 #else
00556 
00557 typedef su_base_port_t su_pthread_port_t;
00558 
00559 #define su_pthread_port_init   su_base_port_init
00560 #define su_pthread_port_deinit su_base_port_deinit
00561 #define su_pthread_port_lock   su_base_port_lock
00562 #define su_pthread_port_unlock su_base_port_unlock
00563 #define su_pthread_port_thread su_base_port_thread
00564 #define su_pthread_port_wait   su_base_port_wait
00565 #define su_pthread_port_execute  su_base_port_execute
00566 
00567 #endif
00568 
00569 /* ====================================================================== */
00570 /* Mailbox port using sockets */
00571 
00572 #define SU_MBOX_SIZE 2
00573 
00574 typedef struct su_socket_port_s {
00575   su_pthread_port_t sup_base[1];
00576   int               sup_mbox_index;
00577   su_socket_t       sup_mbox[SU_MBOX_SIZE];
00578 } su_socket_port_t;
00579 
00580 SOFIAPUBFUN int su_socket_port_init(su_socket_port_t *, 
00581                                     su_port_vtable_t const *);
00582 SOFIAPUBFUN void su_socket_port_deinit(su_socket_port_t *self);
00583 SOFIAPUBFUN int su_socket_port_send(su_port_t *self, su_msg_r rmsg);
00584 
00585 SOFIA_END_DECLS
00586 
00587 #endif /* SU_PORT_H */

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