📄 su_root.c
字号:
* The function su_root_deregister() deregisters a su_wait_t object. The * wait object, a callback function and a argument are removed from the * root object. The wait object is destroyed. * * @param self pointer to root object * @param index registration index * * @return Index of the wait object, or -1 upon an error. */int su_root_deregister(su_root_t *self, int index){ if (!self) return (void)(errno = EFAULT), -1; if (index == 0 || index == -1) return (void)(errno = EINVAL), -1; assert(self->sur_port); return su_port_deregister(self->sur_port, index);}/** Set mask for a registered event. * * The function su_root_eventmask() sets the mask describing events that can * signal the registered callback. * * @param self pointer to root object * @param index registration index * @param socket socket * @param events new event mask * * @retval 0 when successful, * @retval -1 upon an error. */int su_root_eventmask(su_root_t *self, int index, int socket, int events){ if (!self) return (void)(errno = EFAULT), -1; if (index == 0 || index == -1) return (void)(errno = EINVAL), -1; assert(self->sur_port); return su_port_eventmask(self->sur_port, index, socket, events);}/** Set multishot mode. * * The function su_root_multishot() enables, disables or queries the * multishot mode for the root. The multishot mode determines how the events * are scheduled by root. If multishot mode is enabled, root serves all the * sockets that have received network events. If it is disables, only first * socket event is served. * * @param self pointer to root object * @param multishot multishot mode (0 => disables, 1 => enables, -1 => query) * * @retval 0 multishot mode is disabled * @retval 1 multishot mode is enabled * @retval -1 an error occurred */int su_root_multishot(su_root_t *self, int multishot){ if (!self) return (void)(errno = EFAULT), -1; assert(self->sur_port); return su_port_multishot(self->sur_port, multishot);}/** Run event and message loop. * * The function su_root_run() runs the root main loop. The root loop waits * for wait objects and the timers associated with the root object. When any * wait object is signaled or timer is expired, it invokes the callbacks, * and returns waiting. * * This function returns when su_root_break() is called from a callback. * * @param self pointer to root object * */void su_root_run(su_root_t *self){ if (!self) return /* (void)(errno = EFAULT), -1 */; assert(self->sur_port); /* return */ su_port_run(self->sur_port);}/** Terminate event loop. * * The function su_root_break() is used to terminate execution of * su_root_run(). It can be called from a callback function. * * @param self pointer to root object */void su_root_break(su_root_t *self){ if (!self) return /* (void)(errno = EFAULT), -1 */; assert(self->sur_port); /* return */ su_port_break(self->sur_port);}/** Process events, timers and messages. * * The function su_root_step() waits for wait objects and the timers * associated with the root object. When any wait object is signaled or * timer is expired, it invokes the callbacks. * * This function returns when a callback has been invoked or tout * milliseconds is elapsed. * * @param self pointer to root object * @param tout timeout in milliseconds * * @return Milliseconds to the next invocation of timer * @retval SU_WAIT_FOREVER if there are no active timers or if there was an error */su_duration_t su_root_step(su_root_t *self, su_duration_t tout){ if (self == NULL) return (void)(errno = EFAULT), SU_WAIT_FOREVER; assert(self->sur_port); return su_port_step(self->sur_port, tout);}/**Run event and message loop for given duration. * * The function su_root_sleep() runs event loop for @a duration milliseconds. * The event loop waits for wait objects and the timers associated with the * @a root object. When any wait object is signaled, timer is expired, or * message is received, it invokes the callbacks and returns waiting. * * @param self pointer to root object * @param duration milliseconds to run event loop * * @retval milliseconds until next timer expiration */su_duration_t su_root_sleep(su_root_t *self, su_duration_t duration){ su_duration_t retval, accrued = 0; su_time_t started; if (self == NULL) return (void)(errno = EFAULT), SU_WAIT_FOREVER; assert(self->sur_port); started = su_now(); do { retval = su_port_step(self->sur_port, duration - accrued); accrued = su_duration(su_now(), started); } while (accrued < duration); return retval;}/** Check wait events in callbacks that take lots of time * * This function does a 0 timeout poll() and runs wait objects * * @param self pointer to root object */int su_root_yield(su_root_t *self){ if (self == NULL) return (void)(errno = EFAULT), SU_WAIT_FOREVER; assert(self->sur_port); return su_port_wait_events(self->sur_port, 0);}/** Get task reference. * * Retrieve the task reference related with the root object. * * @param self a pointer to a root object * * @return A reference to the task object. */_su_task_r su_root_task(su_root_t const *self){ if (self) return self->sur_task; else return su_task_null;}/** Get parent task reference. * * Retrieve the task reference of the parent task associated with the root * object. * * @param self a pointer to a root object * * @return A reference to the parent task object. */_su_task_r su_root_parent(su_root_t const *self){ if (self) return self->sur_parent; else return su_task_null;}/** Add a pre-poll callback. */int su_root_add_prepoll(su_root_t *root, su_prepoll_f *callback, su_prepoll_magic_t *magic){ if (root == NULL) return (void)(errno = EFAULT), -1; assert(root->sur_port); return su_port_add_prepoll(root->sur_port, root, callback, magic);}/** Remove a pre-poll callback */int su_root_remove_prepoll(su_root_t *root){ if (root == NULL) return (void)(errno = EFAULT), -1; assert(root->sur_port); return su_port_remove_prepoll(root->sur_port, root);}/** Release the root port for other threads. * * @NEW_1_12_7 */int su_root_release(su_root_t *root){ if (root == NULL || root->sur_port == NULL) return (void)(errno = EFAULT), -1; return su_port_release(root->sur_port);}/** Obtain the root port from other thread. * * @param root pointer to root object * * @retval 0 if successful * @retval -1 upon an error * * @ERRORS * @ERROR EFAULT * @NEW_1_12_7 */int su_root_obtain(su_root_t *root){ if (root == NULL || root->sur_port == NULL) return (void)(errno = EFAULT), -1; return su_port_obtain(root->sur_port);}/**Check if a thread has obtained the root. * * @param root a pointer to root object * * @retval 2 if current thread has obtained the root * @retval 1 if an another thread has obtained the root * @retval 0 if no thread has obtained the root * @retval -1 upon an error * * @NEW_1_12_7 */int su_root_has_thread(su_root_t *root){ if (root == NULL || root->sur_port == NULL) return (void)(errno = EFAULT), -1; return su_port_has_thread(root->sur_port);}/* ========================================================================= * Messages *//** * Allocate a su message of given size. * * Allocate a su message with given data size. * * @param rmsg handle to the new message (may be uninitialized prior calling) * @param size size of the message data * * @retval 0 if successful, * @retval -1 if message allocation fails. * * @NEW_1_12_8 */int su_msg_new(su_msg_r rmsg, size_t size){ su_msg_t *msg; size_t total = sizeof(*msg) + (size_t)size; *rmsg = msg = su_zalloc(NULL, (isize_t)total); if (!*rmsg) return -1; msg->sum_size = total; return 0;}/** * Allocates a message of given size. * * The function @c su_msg_create() allocates a message with given data size. * If successful, it moves the new message handle to the @c rmsg. * * @param rmsg handle to the new message (may be uninitialized prior calling) * @param to the recipient task * @param from the sender task * @param wakeup function that is called when message is delivered * @param size size of the message data * * @retval 0 if successful, * @retval -1 if message allocation fails. */int su_msg_create(su_msg_r rmsg, su_task_r const to, su_task_r const from, su_msg_f wakeup, isize_t size){ if (su_msg_new(rmsg, (size_t) size) == 0) { SU_TASK_COPY(rmsg[0]->sum_to, to, su_msg_create); SU_TASK_COPY(rmsg[0]->sum_from, from, su_msg_create); rmsg[0]->sum_func = wakeup; return 0; } return -1;}/** Add a delivery report function to a message. * * The delivery report funcgtion gets called by the sending task after the * message was delivered and the message function was executed. (The * su_root_t message delivery loop calls su_msg_delivery_report() * */int su_msg_report(su_msg_r msg, su_msg_f report){ if (msg && msg[0] && msg[0]->sum_report == NULL) { msg[0]->sum_report = report; return 0; } return -1;}/** Add a deinitializer function to a message. * * The deinitializer function is called when the message gets destroyed. It * is called even if the message was never delivered. Note that the thread * destroying the message and calling the deinit function is not necessarily * the same that sent the message nor the original recipient. * * @param rmsg message reference * @param deinit pointer to deinitializer function * * @NEW_1_12_8 */int su_msg_deinitializer(su_msg_r rmsg, su_msg_deinit_function *deinit){ if (rmsg && rmsg[0]) { rmsg[0]->sum_deinit = deinit; return 0; } return -1;}/** * Allocates a reply message of given size. * * @param reply handle to the new message (may be uninitialized prior calling) * @param rmsg the incoming message * @param wakeup function that is called when message is delivered * @param size size of the message data * * @retval 0 if successful, * @retval -1 otherwise. */int su_msg_reply(su_msg_r reply, su_msg_cr rmsg, su_msg_f wakeup, isize_t size){ su_msg_r rmsg0; assert(rmsg != reply); *rmsg0 = *(su_msg_t **) rmsg; *reply = NULL; return su_msg_create(reply, su_msg_from(rmsg0), su_msg_to(rmsg0), wakeup, size);}/** Send a delivery report. * * If the sender has attached a delivery report function to message with * su_msg_report(), the message is returned to the message queue of the * sending task. The sending task calls the delivery report function when it * has received the message. */void su_msg_delivery_report(su_msg_r rmsg){ su_task_r swap; if (!rmsg || !rmsg[0]) return; if (!rmsg[0]->sum_report) { su_msg_destroy(rmsg); return; } *swap = *rmsg[0]->sum_from; *rmsg[0]->sum_from = *rmsg[0]->sum_to; *rmsg[0]->sum_to = *swap; rmsg[0]->sum_func = rmsg[0]->sum_report; rmsg[0]->sum_report = NULL; su_msg_send(rmsg);}/** Save a message. */void su_msg_save(su_msg_r save, su_msg_r rmsg){ if (save) { if (rmsg) save[0] = rmsg[0]; else save[0] = NULL; } if (rmsg) rmsg[0] = NULL;}/** * Destroys an unsent message. * * @param rmsg message handle. */void su_msg_destroy(su_msg_r rmsg){ su_msg_t *msg; assert(rmsg); msg = rmsg[0], rmsg[0] = NULL; if (msg) { SU_TASK_ZAP(msg->sum_to, su_msg_destroy); SU_TASK_ZAP(msg->sum_from, su_msg_destroy); if (msg->sum_deinit) msg->sum_deinit(msg->sum_data); su_free(NULL, msg); }}/** Gets a pointer to the message data area. * * The function @c su_msg_data() returns a pointer to the message data * area. If @c rmsg contains a @c NULL handle, or message size is 0, @c NULL * pointer is returned. * * @param rmsg message handle * * @return A pointer to the message data area is returned. */su_msg_arg_t *su_msg_data(su_msg_cr rmsg){ if (rmsg[0] && rmsg[0]->sum_size > sizeof(su_msg_t)) return rmsg[0]->sum_data; else return NULL;}/** Get size of message data area. */isize_t su_msg_size(su_msg_cr rmsg){ return rmsg[0] ? rmsg[0]->sum_size - sizeof(su_msg_t) : 0;}/** Get sending task. * * Returns the task handle belonging to the sender of the message. * * If the message handle contains NULL the function @c su_msg_from * returns NULL. * * @param rmsg message handle * * @return The task handle of the sender is returned. */_su_task_r su_msg_from(su_msg_cr rmsg){ return rmsg[0] ? rmsg[0]->sum_from : NULL;}/** Get destination task. * * The function @c su_msg_from returns the task handle belonging to the * recipient of the message. * * If the message handle contains NULL the function @c su_msg_to * returns NULL. * * @param rmsg message handle * * @return The task handle of the recipient is returned. */_su_task_r su_msg_to(su_msg_cr rmsg){ return rmsg[0] ? rmsg[0]->sum_to : NULL;}/** Remove references to 'from' and 'to' tasks from a message. * * @param rmsg message handle */void su_msg_remove_refs(su_msg_cr rmsg){ if (rmsg[0]) { su_task_deinit(rmsg[0]->sum_to); su_task_deinit(rmsg[0]->sum_from); }}/**Send a message. * * The function @c su_msg_send() sends the message. The message is added to * the recipients message queue, and recipient is waken up. The caller may * not alter the message or the data associated with it after the message * has been sent. * * @param rmsg message handle * * @retval 0 if signal was sent successfully or handle was @c NULL, * @retval -1 otherwise. */int su_msg_send(su_msg_r rmsg){ assert(rmsg); if (rmsg[0]) { su_msg_t *msg = rmsg[0]; if (msg->sum_to->sut_port) return su_port_send(msg->sum_to->sut_port, rmsg); su_msg_destroy(rmsg); errno = EINVAL; return -1; } return 0; }/** Send message to the @a to_task and mark @a from_task as sender. * * @NEW_1_12_8 */SOFIAPUBFUN int su_msg_send_to(su_msg_r rmsg, su_task_r const to_task, su_msg_f wakeup){ assert(rmsg); assert(to_task); if (rmsg[0]) { su_msg_t *msg = rmsg[0]; if (wakeup) msg->sum_func = wakeup; if (msg->sum_to->sut_port && msg->sum_to->sut_port != to_task->sut_port) { SU_TASK_ZAP(msg->sum_to, "su_msg_send_to"); } if (to_task->sut_port != NULL) { msg->sum_to->sut_port = NULL; msg->sum_to->sut_root = to_task->sut_root; return su_port_send(to_task->sut_port, rmsg); } su_msg_destroy(rmsg); errno = EINVAL; return -1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -