Ejemplo n.º 1
0
Archivo: ae.c Proyecto: flygoast/verben
/* Process time events. */
static int process_time_events(ae_event_loop *el) {
    int processed = 0;
    ae_time_event *te;
    long long maxid;

    te = el->time_event_head;
    maxid = el->time_event_next_id - 1;
    while (te) {
        long now_sec, now_ms;
        long long id;
        /* Don't process the time event registered during this process. */
        if (te->id > maxid) { 
            te = te->next;
            continue;
        }
        ae_get_time(&now_sec, &now_ms);
        /* timeout */
        if (now_sec > te->when_sec ||
            (now_sec == te->when_sec && now_ms >= te->when_ms)) {
            int ret;
            id = te->id;
            ret = te->time_proc(el, id, te->client_data);
            processed++;
            /* After an event is processed our time event list 
               may no longer be the same, so we restart from head.
               Still we make sure to don't process events registered
               by event handlers itself in order to don't loop
               forever. To do so we saved the max ID we want to 
               handle.

               FUTURE OPTIMIZATIONS:
               Note that this is NOT great algorithmically. Redis
               uses a single time event so it's not a problem but
               the right way to do this is to add the new elements
               on head, and to flag deleted elements in a special
               way for later deletion(putting references to the 
               nodes to delete into another linked list). */
            if (ret > 0) {
                ae_add_milliseconds_to_now(ret, &te->when_sec, 
                        &te->when_ms);
            } else {
                ae_delete_time_event(el, id);
            }
            te = el->time_event_head;
        } else {
            te = te->next;
        }
    }
    return processed;
}
Ejemplo n.º 2
0
Archivo: ae.c Proyecto: flygoast/verben
static void ae_add_milliseconds_to_now(long long milliseconds, 
        long *sec, long *ms) {
    long cur_sec, cur_ms, when_sec, when_ms;
    ae_get_time(&cur_sec, &cur_ms);
    when_sec = cur_sec + milliseconds / 1000;
    when_ms = cur_ms + milliseconds % 1000;
    /* cur_ms < 1000, when_ms < 2000, so just one time is enough. */
    if (when_ms >= 1000) {
        ++when_sec;
        when_ms -= 1000;
    }
    *sec = when_sec;
    *ms = when_ms;
}
Ejemplo n.º 3
0
static int process_time_event(ae_event_loop * ev_loop)
{
	int processed = 0;
	ae_time_event * te;
	long long maxid;
	time_t now = time(NULL);

	if (now < ev_loop->last_time) {
		te = ev_loop->time_event_head;
		while (te) {
			te->when_sec = 0;
			te = te->next;
		}
	}

	ev_loop->last_time = now;
	te = ev_loop->time_event_head;
	maxid = ev_loop->time_event_next_id - 1;
	while (te) {
		long now_sec, now_ms;
		long long id;

		if (te->id > maxid) {
			te = te->next;
			continue;
		}
		ae_get_time(&now_sec, &now_ms);
		if (now_sec > te->when_sec || 
				(now_sec == te->when_sec && now_ms >= te->when_ms))
		{
			int retval;
			
			id = te->id;
			retval = te->time_func(ev_loop, id, te->client_data);
			processed++;

			if (retval != AE_NOMORE) 
				ae_add_milliseconds_to_now(retval, &te->when_sec, &te->when_ms);
			else
				ae_delete_time_event(ev_loop, id);

			te = ev_loop->time_event_head;
		} else {
			te = te->next;
		}
	}

	return processed;
}
Ejemplo n.º 4
0
static void ae_add_milliseconds_to_now(long long milliseconds, long * sec, long * ms)
{
	long cur_sec, cur_ms, when_sec, when_ms;

	ae_get_time(&cur_sec, &cur_ms);
	when_sec = cur_sec + milliseconds / 1000;
	when_ms = cur_ms + milliseconds % 1000;

	if (when_ms >= 1000) {
		when_sec++;
		when_ms -= 1000;
	}

	*sec = when_sec;
	*ms = when_ms;
}
Ejemplo n.º 5
0
Archivo: ae.c Proyecto: flygoast/verben
/* Process every pending time event, then every pending file event
   (that may be registered by time event callbacks just processed).
   Without special flags the function sleeps until some file event
   fires, or when the next time event occurs (if any).

   If flag is 0, the function does nothing and returns.
   if flag has AE_ALL_EVENTS set, all the kind of events are processed.
   if flag has AE_FILE_EVENTS set, file events are processed.
   if flag has AE_TIME_EVENTS set, time events are processed.
   if flag has AE_DONT_WAIT set, the function returns ASAP (As soon
   as possible) until all the events that's possible to process 
   without to wait are processed.

   The function returns the number of events processed. */
int ae_process_events(ae_event_loop *el, int flags) {
    int processed = 0, numevents;

    /* Nothing to do ? return ASAP */
    if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) {
        return 0;
    }

    /* Note that we want call select() even if there are no file
       events to process as long as we want to process time events,
       in order to sleep until the next time event is ready to fire. */
    if (el->maxfd != -1 ||
        ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) {
        int j;
        ae_time_event *shortest = NULL;
        struct timeval tv, *tvp;
        
        if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT)) {
            shortest = ae_search_nearest_timer(el);
        } 
        if (shortest) {
            long now_sec, now_ms;

            /* Calculate the time missing for the nearest timer 
               to fire. */
            ae_get_time(&now_sec, &now_ms);
            tvp = &tv;
            tvp->tv_sec = shortest->when_sec - now_sec;
            if (shortest->when_ms < now_ms) {
                tvp->tv_usec = ((shortest->when_ms + 1000) 
                        - now_ms) * 1000;
                --tvp->tv_sec;
            } else {
                tvp->tv_usec = (shortest->when_ms - now_ms) * 1000;
            }
            if (tvp->tv_sec < 0) {
                tvp->tv_sec = 0;
            } 
            if (tvp->tv_usec < 0) {
                tvp->tv_usec = 0;
            }
        } else {
            /* If we have to check for events but need to return
               ASAP because of AE_DONT_WAIT we need to set the 
               timeout to zero. */
            if (flags & AE_DONT_WAIT) {
                tv.tv_sec = tv.tv_usec = 0;
                tvp = &tv;
            } else {
                /* Otherwise we can block. */
                tvp = NULL; /* wait forever */
            }
        }
        numevents = ae_api_poll(el, tvp);
        for (j = 0; j < numevents; ++j) {
            ae_file_event *fe = &el->events[el->fired[j].fd];
            int mask = el->fired[j].mask;
            int fd = el->fired[j].fd;
            int rfired = 0;
            
            /* Note the fe->mask & mask & ... code: maybe an already
               processed event removed an element that fired and we
               still didn't processed, so we check if the events is 
               still valid. */
            if (fe->mask & mask & AE_READABLE) {
                rfired = 1;
                fe->r_file_proc(el, fd, fe->client_data, mask);
            } 
            if (fe->mask & mask & AE_WRITABLE) {
                if (!rfired || fe->w_file_proc != fe->r_file_proc) {
                    fe->w_file_proc(el, fd, fe->client_data, mask);
                }
            }

            ++processed;
        }
    }
    /* Check time events */
    if (flags & AE_TIME_EVENTS) {
        processed += process_time_events(el);
    }
    /* Return the number of processed file/time events */
    return processed; 
}
Ejemplo n.º 6
0
int ae_process_events(ae_event_loop * ev_loop, int flags)
{
	int processed = 0, numevents = 0;
	struct timeval * tvp = NULL;
	if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0;

	// There is some fd registered
	if (ev_loop->maxfd != -1 ||
		((flags & AE_TIME_EVENTS) && (flags & AE_DONT_WAIT))) {
		int j;
		ae_time_event * shortest = NULL;
		struct timeval tv, *tvp = NULL;


		if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT))
			shortest = ae_search_nearest_timer(ev_loop);

		if (shortest) {
			long now_sec, now_ms;

			ae_get_time(&now_sec, &now_ms);
			tvp = &tv;
			tvp->tv_sec = shortest->when_sec - now_sec;
			if (shortest->when_ms < now_ms) {
							tvp->tv_usec = ((shortest->when_ms+1000) - now_ms)*1000;
							tvp->tv_sec --;
			} else {
							tvp->tv_usec = (shortest->when_ms - now_ms)*1000;
			}
			if (tvp->tv_sec < 0) tvp->tv_sec = 0;
			if (tvp->tv_usec < 0) tvp->tv_usec = 0;
		} else {
			if (flags & AE_DONT_WAIT) {
				tv.tv_sec = tv.tv_usec = 0;
				tvp = &tv;
			} else {
				tvp = NULL;
			}
		}

		numevents = ae_api_poll(ev_loop, tvp);
		for (j = 0; j < numevents; j++) {
			// Registered event
			ae_file_event * fe = &ev_loop->events[ev_loop->fired[j].fd];
			// Fired event
			int mask = ev_loop->fired[j].mask;
			int fd = ev_loop->fired[j].fd;
			int rfired = 0;
		
			if (fe != NULL && (fe->mask & mask & AE_READABLE)) {
				rfired = 1;
				fe->r_file_func(ev_loop, fd, fe->client_data, mask);
			}
			
			if (fe != NULL && (fe->mask & mask & AE_WRITABLE)) {
				if (!rfired || fe->w_file_func != fe->r_file_func)
					fe->w_file_func(ev_loop, fd, fe->client_data, mask);
			}

			processed++;
		}
	}

	if (flags & AE_TIME_EVENTS)
		processed += process_time_event(ev_loop);

	return processed;
}