コード例 #1
0
ファイル: event.cpp プロジェクト: nonolith/connect
void Event::notify(){
	for (std::set<EventListener*>::iterator it=listeners.begin(); it!=listeners.end();){
		EventListener* e = *it;
		it++; // Increment before calling handler in case the handler removes this listener,
		      // which would invalidate the iterator.
		e->handler();
	}
}
コード例 #2
0
ファイル: sys.c プロジェクト: sdwarak/AtomVM
extern void sys_waitevents(struct ListHead *listeners_list)
{
    struct timespec now;
    clock_gettime(CLOCK_MONOTONIC, &now);

    EventListener *listeners = GET_LIST_ENTRY(listeners_list, EventListener, listeners_list_head);
    EventListener *last_listener = GET_LIST_ENTRY(listeners_list->prev, EventListener, listeners_list_head);

    int min_timeout = INT_MAX;
    int count = 0;

    //first: find maximum allowed sleep time, and count file descriptor listeners
    EventListener *listener = listeners;
    do {
        if (listener->expires) {
            int wait_ms = timespec_diff_to_ms(&listener->expiral_timestamp, &now);
            if (wait_ms <= 0) {
                min_timeout = 0;
            } else if (min_timeout > wait_ms) {
                min_timeout = wait_ms;
            }
        }
        if (listener->fd >= 0) {
            count++;
        }

        listener = GET_LIST_ENTRY(listener->listeners_list_head.next, EventListener, listeners_list_head);
    } while (listener != listeners);

    //second: use either poll or nanosleep
    if (count > 0) {
        struct pollfd *fds = calloc(count, sizeof(struct pollfd));
        if (IS_NULL_PTR(fds)) {
            fprintf(stderr, "Cannot allocate memory for pollfd, aborting.\n");
            abort();
        }
        int poll_fd_index = 0;

        //build pollfd array
        EventListener *listener = listeners;
        do {
            if (listener->fd >= 0) {
                fds[poll_fd_index].fd = listener->fd;
                fds[poll_fd_index].events = POLLIN;
                fds[poll_fd_index].revents = 0;
            }

            poll_fd_index++;

            listener = GET_LIST_ENTRY(listener->listeners_list_head.next, EventListener, listeners_list_head);
        } while (listener != listeners);

        poll(fds, poll_fd_index, min_timeout);

        //check which event happened
        listener = listeners;
        do {
            EventListener *next_listener = GET_LIST_ENTRY(listener->listeners_list_head.next, EventListener, listeners_list_head);
            for (int i = 0; i < poll_fd_index; i++) {
                if ((fds[i].fd == listener->fd) && (fds[i].revents & fds[i].events)) {
                    //it is completely safe to free a listener in the callback, we are going to not use it after this call
                    listener->handler(listener);
                }
            }

            listener = next_listener;
        } while (listener != listeners);

        free(fds);

    //just need to wait for a certain timespan
    } else {
        struct timespec t;
        t.tv_sec = min_timeout / 1000;
        t.tv_nsec = (min_timeout % 1000) * 1000000;

        struct timespec rem;
        int nanosleep_result = nanosleep(&t, &rem);
        while (nanosleep_result == -1) {
            nanosleep_result = nanosleep(&rem, &rem);
        }
    }

    //third: execute handlers for expiered timers
    if (min_timeout != INT_MAX) {
        listener = listeners;
        clock_gettime(CLOCK_MONOTONIC, &now);
        do {
            EventListener *next_listener = GET_LIST_ENTRY(listener->listeners_list_head.next, EventListener, listeners_list_head);
            if (listener->expires) {
                int wait_ms = timespec_diff_to_ms(&listener->expiral_timestamp, &now);
                if (wait_ms <= 0) {
                    //it is completely safe to free a listener in the callback, we are going to not use it after this call
                    listener->handler(listener);
                    //TODO check if one shot
                }
            }

            listener = next_listener;
        } while (listener != last_listener);
    }
}