Exemple #1
0
static void io_loop_handle_timeouts_real(struct ioloop *ioloop)
{
	struct priorityq_item *item;
	struct timeval tv, tv_call;
	unsigned int t_id;

	if (gettimeofday(&ioloop_timeval, NULL) < 0)
		i_fatal("gettimeofday(): %m");

	/* Don't bother comparing usecs. */
	if (unlikely(ioloop_time > ioloop_timeval.tv_sec)) {
		/* time moved backwards */
		io_loops_timeouts_update(-(long)(ioloop_time -
						 ioloop_timeval.tv_sec));
		ioloop->time_moved_callback(ioloop_time,
					    ioloop_timeval.tv_sec);
		/* the callback may have slept, so check the time again. */
		if (gettimeofday(&ioloop_timeval, NULL) < 0)
			i_fatal("gettimeofday(): %m");
	} else if (unlikely(ioloop_timeval.tv_sec >
			    ioloop->next_max_time)) {
		io_loops_timeouts_update(ioloop_timeval.tv_sec -
					ioloop->next_max_time);
		/* time moved forwards */
		ioloop->time_moved_callback(ioloop->next_max_time,
					    ioloop_timeval.tv_sec);
	}

	ioloop_time = ioloop_timeval.tv_sec;
	tv_call = ioloop_timeval;

	while ((item = priorityq_peek(ioloop->timeouts)) != NULL) {
		struct timeout *timeout = (struct timeout *)item;

		/* use tv_call to make sure we don't get to infinite loop in
		   case callbacks update ioloop_timeval. */
		if (timeout_get_wait_time(timeout, &tv, &tv_call) > 0)
			break;

		/* update timeout's next_run and reposition it in the queue */
		timeout_reset_timeval(timeout, &tv_call);

		if (timeout->log != NULL) {
			ioloop->cur_log = timeout->log;
			io_loop_log_ref(ioloop->cur_log);
			i_set_failure_prefix(timeout->log->prefix);
		}
                t_id = t_push();
		timeout->callback(timeout->context);
		if (t_pop() != t_id) {
			i_panic("Leaked a t_pop() call in timeout handler %p",
				(void *)timeout->callback);
		}
		if (ioloop->cur_log != NULL) {
			io_loop_log_unref(&ioloop->cur_log);
			i_set_failure_prefix(ioloop->default_log_prefix);
		}
	}
}
Exemple #2
0
struct priorityq_item *priorityq_pop(struct priorityq *pq)
{
	struct priorityq_item *item;

	item = priorityq_peek(pq);
	if (item != NULL) {
		priorityq_remove_idx(pq, 0);
		item->idx = UINT_MAX;
	}
	return item;
}
Exemple #3
0
int io_loop_get_wait_time(struct ioloop *ioloop, struct timeval *tv_r)
{
	struct timeval tv_now;
	struct priorityq_item *item;
	struct timeout *timeout;
	int msecs;

	item = priorityq_peek(ioloop->timeouts);
	timeout = (struct timeout *)item;
	if (timeout == NULL) {
		/* no timeouts. use INT_MAX msecs for timeval and
		   return -1 for poll/epoll infinity. */
		tv_r->tv_sec = INT_MAX / 1000;
		tv_r->tv_usec = 0;
							/* APPLE */
		ioloop->next_max_time = (1ULL << (time_t_max_bits()-1)) - 1;
		return -1;
	}

	tv_now.tv_sec = 0;
	msecs = timeout_get_wait_time(timeout, tv_r, &tv_now);
	ioloop->next_max_time = (tv_now.tv_sec + msecs/1000) + 1;
	return msecs;
}
Exemple #4
0
void test_priorityq(void)
{
#define PQ_MAX_ITEMS 100
	static const int input[] = {
		1, 2, 3, 4, 5, 6, 7, 8, -1,
		8, 7, 6, 5, 4, 3, 2, 1, -1,
		8, 7, 5, 6, 1, 3, 4, 2, -1,
		-1
	};
	static const int output[] = {
		1, 2, 3, 4, 5, 6, 7, 8
	};
	struct pq_test_item *item, items[PQ_MAX_ITEMS];
	struct priorityq_item *const *all_items;
	unsigned int i, j;
	struct priorityq *pq;
	pool_t pool;
	int prev;

	pool = pool_alloconly_create("priorityq items", 1024);

	/* simple tests with popping only */
	test_begin("priorityq");
	for (i = 0; input[i] != -1; i++) {
		p_clear(pool);
		pq = priorityq_init(cmp_int, 1);
		for (j = 0; input[i] != -1; i++, j++) {
			test_assert(priorityq_count(pq) == j);
			item = p_new(pool, struct pq_test_item, 1);
			item->num = input[i];
			priorityq_add(pq, &item->item);
		}
		all_items = priorityq_items(pq);
		test_assert(priorityq_count(pq) == N_ELEMENTS(output));
		item = (struct pq_test_item *)all_items[0];
		test_assert(item->num == output[0]);
		for (j = 1; j < N_ELEMENTS(output); j++) {
			item = (struct pq_test_item *)all_items[j];
			test_assert(item->num > output[0]);
			test_assert(item->num <= output[N_ELEMENTS(output)-1]);
		}
		for (j = 0; j < N_ELEMENTS(output); j++) {
			test_assert(priorityq_count(pq) == N_ELEMENTS(output) - j);

			item = (struct pq_test_item *)priorityq_peek(pq);
			test_assert(output[j] == item->num);
			item = (struct pq_test_item *)priorityq_pop(pq);
			test_assert(output[j] == item->num);
		}
		test_assert(priorityq_count(pq) == 0);
		test_assert(priorityq_peek(pq) == NULL);
		test_assert(priorityq_pop(pq) == NULL);
		priorityq_deinit(&pq);
	}
	test_end();

	/* randomized tests, remove elements */
	test_begin("priorityq randomized");
	for (i = 0; i < 100; i++) {
		pq = priorityq_init(cmp_int, 1);
		for (j = 0; j < PQ_MAX_ITEMS; j++) {
			items[j].num = rand();
			priorityq_add(pq, &items[j].item);
		}
		for (j = 0; j < PQ_MAX_ITEMS; j++) {
			if (rand() % 3 == 0) {
				priorityq_remove(pq, &items[j].item);
				items[j].num = -1;
			}
		}
		prev = 0;
		while (priorityq_count(pq) > 0) {
			item = (struct pq_test_item *)priorityq_pop(pq);
			test_assert(item->num >= 0 && prev <= item->num);
			prev = item->num;
			item->num = -1;
		}
		for (j = 0; j < PQ_MAX_ITEMS; j++) {
			test_assert(items[j].num == -1);
		}
		priorityq_deinit(&pq);
	}
	test_end();
	pool_unref(&pool);
}