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

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