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