📄 selector.c
字号:
parent->up = elem; parent->left = tmp1; if (parent->left) parent->left->up = parent; parent->right = tmp2; if (parent->right) parent->right->up = parent; if (*last == elem) *last = parent; parent = elem->up; }}static voidsend_down(sel_timer_t *elem, sel_timer_t **top, sel_timer_t **last){ sel_timer_t *tmp1, *tmp2, *left, *right; left = elem->left; while (left) { right = elem->right; /* Choose the smaller of the two below me to swap with. */ if ((right) && (cmp_timeval(&left->timeout, &right->timeout) > 0)) { if (cmp_timeval(&elem->timeout, &right->timeout) > 0) { /* Swap with the right element. */ tmp1 = right->left; tmp2 = right->right; if (elem->up) { if (elem->up->left == elem) { elem->up->left = right; } else { elem->up->right = right; } } else { *top = right; } right->up = elem->up; elem->up = right; right->left = elem->left; right->right = elem; elem->left = tmp1; elem->right = tmp2; if (right->left) right->left->up = right; if (elem->left) elem->left->up = elem; if (elem->right) elem->right->up = elem; if (*last == right) *last = elem; } else goto done; } else { /* The left element is smaller, or the right doesn't exist. */ if (cmp_timeval(&elem->timeout, &left->timeout) > 0) { /* Swap with the left element. */ tmp1 = left->left; tmp2 = left->right; if (elem->up) { if (elem->up->left == elem) { elem->up->left = left; } else { elem->up->right = left; } } else { *top = left; } left->up = elem->up; elem->up = left; left->left = elem; left->right = elem->right; elem->left = tmp1; elem->right = tmp2; if (left->right) left->right->up = left; if (elem->left) elem->left->up = elem; if (elem->right) elem->right->up = elem; if (*last == left) *last = elem; } else goto done; } left = elem->left; }done: return;}static voidadd_to_heap(sel_timer_t **top, sel_timer_t **last, sel_timer_t *elem){ sel_timer_t **next; sel_timer_t *parent;#ifdef MASSIVE_DEBUG fprintf(*debug_out, "add_to_heap entry\n"); print_tree(*top, *last); check_tree(*top, *last);#endif elem->left = NULL; elem->right = NULL; elem->up = NULL; if (*top == NULL) { *top = elem; *last = elem; goto out; } find_next_pos(*last, &next, &parent); *next = elem; elem->up = parent; *last = elem; if (cmp_timeval(&elem->timeout, &parent->timeout) < 0) { send_up(elem, top, last); } out:#ifdef MASSIVE_DEBUG fprintf(*debug_out, "add_to_heap exit\n"); print_tree(*top, *last); check_tree(*top, *last);#endif return;}static voidremove_from_heap(sel_timer_t **top, sel_timer_t **last, sel_timer_t *elem){ sel_timer_t *to_insert;#ifdef MASSIVE_DEBUG fprintf(*debug_out, "remove_from_head entry\n"); print_tree(*top, *last); check_tree(*top, *last);#endif /* First remove the last element from the tree, if it's not what's being removed, we will use it for insertion into the removal place. */ to_insert = *last; if (! to_insert->up) { /* This is the only element in the heap. */ *top = NULL; *last = NULL; goto out; } else { /* Set the new last position, and remove the item we will insert. */ find_prev_elem(to_insert, last); if (to_insert->up->left == to_insert) { to_insert->up->left = NULL; } else { to_insert->up->right = NULL; } } if (elem == to_insert) { /* We got lucky and removed the last element. We are done. */ goto out; } /* Now stick the formerly last element into the removed element's position. */ if (elem->up) { if (elem->up->left == elem) { elem->up->left = to_insert; } else { elem->up->right = to_insert; } } else { /* The head of the tree is being replaced. */ *top = to_insert; } to_insert->up = elem->up; if (elem->left) elem->left->up = to_insert; if (elem->right) elem->right->up = to_insert; to_insert->left = elem->left; to_insert->right = elem->right; if (*last == elem) *last = to_insert; elem = to_insert; /* Now propigate it to the right place in the tree. */ if (elem->up && cmp_timeval(&elem->timeout, &elem->up->timeout) < 0) { send_up(elem, top, last); } else { send_down(elem, top, last); } out:#ifdef MASSIVE_DEBUG fprintf(*debug_out, "remove_from_head exit\n"); print_tree(*top, *last); check_tree(*top, *last);#endif return;}intsel_alloc_timer(selector_t *sel, sel_timeout_handler_t handler, void *user_data, sel_timer_t **new_timer){ sel_timer_t *timer; timer = malloc(sizeof(*timer)); if (!timer) return ENOMEM; timer->handler = handler; timer->user_data = user_data; timer->in_heap = 0; timer->sel = sel; *new_timer = timer; return 0;}intsel_free_timer(sel_timer_t *timer){ if (timer->in_heap) { sel_stop_timer(timer); } free(timer); return 0;}intsel_start_timer(sel_timer_t *timer, struct timeval *timeout){ if (timer->in_heap) return EBUSY; timer->timeout = *timeout; add_to_heap(&(timer->sel->timer_top), &(timer->sel->timer_last), timer); timer->in_heap = 1; return 0;}intsel_stop_timer(sel_timer_t *timer){ if (!timer->in_heap) return ETIMEDOUT; remove_from_heap(&(timer->sel->timer_top), &(timer->sel->timer_last), timer); timer->in_heap = 0; return 0;}/* The main loop for the program. This will select on the various sets, then scan for any available I/O to process. It also monitors the time and call the timeout handlers periodically. */voidsel_select_loop(selector_t *sel){ fd_set tmp_read_set; fd_set tmp_write_set; fd_set tmp_except_set; int i; int err; sel_timer_t *timer; struct timeval timeout, *to_time; for (;;) { if (sel->timer_top) { struct timeval now; /* Check for timers to time out. */ gettimeofday(&now, NULL); timer = sel->timer_top; while (cmp_timeval(&now, &timer->timeout) >= 0) { remove_from_heap(&(sel->timer_top), &(sel->timer_last), timer); timer->in_heap = 0; timer->handler(sel, timer, timer->user_data); timer = sel->timer_top; gettimeofday(&now, NULL); if (!timer) goto no_timers; } /* Calculate how long to wait now. */ diff_timeval(&timeout, &sel->timer_top->timeout, &now); to_time = &timeout; } else { no_timers: to_time = NULL; } memcpy(&tmp_read_set, &sel->read_set, sizeof(tmp_read_set)); memcpy(&tmp_write_set, &sel->write_set, sizeof(tmp_write_set)); memcpy(&tmp_except_set, &sel->except_set, sizeof(tmp_except_set)); err = select(sel->maxfd+1, &tmp_read_set, &tmp_write_set, &tmp_except_set, to_time); if (err == 0) { /* A timeout occurred. */ } else if (err < 0) { /* An error occurred. */ if (errno == EINTR) { /* EINTR is ok, just restart the operation. */ timeout.tv_sec = 1; timeout.tv_usec = 0; } else { /* An error is bad, we need to abort. */ syslog(LOG_ERR, "select_loop() - select: %m"); exit(1); } } else { /* We got some I/O. */ for (i=0; i<=sel->maxfd; i++) { if (FD_ISSET(i, &tmp_read_set)) { if (sel->fds[i].handle_read == NULL) { /* Somehow we don't have a handler for this. Just shut it down. */ sel_set_fd_read_handler(sel, i, SEL_FD_HANDLER_DISABLED); } else { sel->fds[i].handle_read(i, sel->fds[i].data); } } if (FD_ISSET(i, &tmp_write_set)) { if (sel->fds[i].handle_write == NULL) { /* Somehow we don't have a handler for this. Just shut it down. */ sel_set_fd_write_handler(sel, i, SEL_FD_HANDLER_DISABLED); } else { sel->fds[i].handle_write(i, sel->fds[i].data); } } if (FD_ISSET(i, &tmp_except_set)) { if (sel->fds[i].handle_except == NULL) { /* Somehow we don't have a handler for this. Just shut it down. */ sel_set_fd_except_handler(sel, i, SEL_FD_HANDLER_DISABLED); } else { sel->fds[i].handle_except(i, sel->fds[i].data); } } } } if (got_sighup) { got_sighup = 0; if (user_sighup_handler != NULL) { user_sighup_handler(); } } }}/* Initialize the select code. */intsel_alloc_selector(selector_t **new_selector){ selector_t *sel; int i; sel = malloc(sizeof(*sel)); if (!sel) return ENOMEM; FD_ZERO(&sel->read_set); FD_ZERO(&sel->write_set); FD_ZERO(&sel->except_set); for (i=0; i<FD_SETSIZE; i++) { init_fd(&(sel->fds[i])); } sel->timer_top = NULL; sel->timer_last = NULL; *new_selector = sel; return 0;}static voidfree_heap_element(sel_timer_t *elem){ if (!elem) return; free_heap_element(elem->left); free_heap_element(elem->right); free(elem);}intsel_free_selector(selector_t *sel){ sel_timer_t *heap; heap = sel->timer_top; free(sel); free_heap_element(heap); return 0;}voidset_sighup_handler(t_sighup_handler handler){ user_sighup_handler = handler;}void sighup_handler(int sig){ got_sighup = 1;}voidsetup_sighup(void){ struct sigaction act; int err; act.sa_handler = sighup_handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; err = sigaction(SIGHUP, &act, NULL); if (err) { perror("sigaction"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -