00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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];
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
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
00139 int (*su_port_yield)(su_port_t *port);
00140
00141 int (*su_port_wait_events)(su_port_t *port, su_duration_t timeout);
00142 int (*su_port_getmsgs)(su_port_t *port);
00143
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
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
00170
00171 SOFIAPUBFUN char const *su_port_name(su_port_t const *port);
00172
00173
00174
00175
00176
00177
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
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
00427
00428
00429 su_prepoll_f *sup_prepoll;
00430 su_prepoll_magic_t *sup_pp_magic;
00431 su_root_t *sup_pp_root;
00432
00433
00434 su_msg_t *sup_head, **sup_tail;
00435
00436
00437 su_timer_t *sup_timers;
00438
00439 unsigned sup_running;
00440 } su_base_port_t;
00441
00442
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
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
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
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