ioloop.c revision eef4c69e0c1759aaaddcef341c817bb1e374ed24
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/*
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen ioloop.c : I/O loop
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen Copyright (c) 2002 Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen Permission is hereby granted, free of charge, to any person obtaining
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen a copy of this software and associated documentation files (the
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen "Software"), to deal in the Software without restriction, including
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen without limitation the rights to use, copy, modify, merge, publish,
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen distribute, sublicense, and/or sell copies of the Software, and to
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen permit persons to whom the Software is furnished to do so, subject to
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen the following conditions:
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen The above copyright notice and this permission notice shall be
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen included in all copies or substantial portions of the Software.
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen*/
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen/* FIXME: inserting IO is slow if there's lots of them. I should add a linked
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen list of priorities pointing to first item in the list with the priority. */
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen#include "lib.h"
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen#include "ioloop-internal.h"
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen#undef timercmp
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen#define timercmp(tvp, uvp) \
5a0ac2e5ef482016e00575a7dce83f52c1704732Timo Sirainen ((tvp)->tv_sec > (uvp)->tv_sec || \
5a0ac2e5ef482016e00575a7dce83f52c1704732Timo Sirainen ((tvp)->tv_sec == (uvp)->tv_sec && \
7823ef73e51bb81a17dcb306aff89016d4ce258fTimo Sirainen (tvp)->tv_usec > (uvp)->tv_usec))
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainentime_t ioloop_time = 0;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenstruct timeval ioloop_timeval;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenstruct timezone ioloop_timezone;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenstatic IOLoop current_ioloop = NULL;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenstatic void update_highest_fd(IOLoop ioloop)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen{
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen IO io;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen int max_highest_fd;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen max_highest_fd = ioloop->highest_fd-1;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen ioloop->highest_fd = -1;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen for (io = ioloop->ios; io != NULL; io = io->next) {
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (!io->destroyed && io->fd > ioloop->highest_fd) {
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen ioloop->highest_fd = io->fd;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (ioloop->highest_fd == max_highest_fd)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen break;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen}
4ce6338bf945cccfff9e4ce7cc6aa2246851b84aTimo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenstatic void io_list_insert(IOLoop ioloop, IO io)
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen{
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen IO prev, next;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen prev = NULL;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen for (next = ioloop->ios; next != NULL; next = next->next) {
4ce6338bf945cccfff9e4ce7cc6aa2246851b84aTimo Sirainen if (next->priority >= io->priority)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen break;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen prev = next;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen }
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen
64055bc6d2ed9e25b3b1db3b5b90d0bdb77cd715Timo Sirainen if (prev == NULL)
64055bc6d2ed9e25b3b1db3b5b90d0bdb77cd715Timo Sirainen ioloop->ios = io;
64055bc6d2ed9e25b3b1db3b5b90d0bdb77cd715Timo Sirainen else {
64055bc6d2ed9e25b3b1db3b5b90d0bdb77cd715Timo Sirainen io->prev = prev;
64055bc6d2ed9e25b3b1db3b5b90d0bdb77cd715Timo Sirainen prev->next = io;
64055bc6d2ed9e25b3b1db3b5b90d0bdb77cd715Timo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen if (next != NULL) {
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen io->next = next;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen next->prev = io;
4ce6338bf945cccfff9e4ce7cc6aa2246851b84aTimo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen}
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo SirainenIO io_add(int fd, int condition, IOFunc func, void *data)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen{
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen return io_add_priority(fd, IO_PRIORITY_DEFAULT,
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen condition, func, data);
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen}
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo SirainenIO io_add_priority(int fd, int priority, int condition,
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen IOFunc func, void *context)
7026c16186f543e11af12b8b87f396006db93297Timo Sirainen{
7026c16186f543e11af12b8b87f396006db93297Timo Sirainen IO io;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
7026c16186f543e11af12b8b87f396006db93297Timo Sirainen i_assert(fd >= 0);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen i_assert(func != NULL);
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen io = p_new(current_ioloop->pool, struct _IO, 1);
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen io->fd = fd;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen io->priority = priority;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen io->condition = condition;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen io->func = func;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen io->context = context;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen if (io->fd > current_ioloop->highest_fd)
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen current_ioloop->highest_fd = io->fd;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen io_loop_handle_add(current_ioloop, io->fd, io->condition);
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen io_list_insert(current_ioloop, io);
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen return io;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen}
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenvoid io_remove(IO io)
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen{
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen i_assert(io != NULL);
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen i_assert(io->fd >= 0);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen i_assert(io->fd <= current_ioloop->highest_fd);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen /* notify the real I/O handler */
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen io_loop_handle_remove(current_ioloop, io->fd, io->condition);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen /* check if we removed the highest fd */
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (io->fd == current_ioloop->highest_fd)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen update_highest_fd(current_ioloop);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen io->destroyed = TRUE;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen io->fd = -1;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen}
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenvoid io_destroy(IOLoop ioloop, IO io)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen{
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen /* remove from list */
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (io->prev == NULL)
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen ioloop->ios = io->next;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen else
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen io->prev->next = io->next;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen if (io->next != NULL)
4ce6338bf945cccfff9e4ce7cc6aa2246851b84aTimo Sirainen io->next->prev = io->prev;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen p_free(ioloop->pool, io);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen}
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenstatic void timeout_list_insert(IOLoop ioloop, Timeout timeout)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen{
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen Timeout *t;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen struct timeval *next_run;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen next_run = &timeout->next_run;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen for (t = &ioloop->timeouts; *t != NULL; t = &(*t)->next) {
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen if (timercmp(&(*t)->next_run, next_run))
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen break;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen }
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen timeout->next = *t;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen *t = timeout;
4ce6338bf945cccfff9e4ce7cc6aa2246851b84aTimo Sirainen}
4ce6338bf945cccfff9e4ce7cc6aa2246851b84aTimo Sirainen
4ce6338bf945cccfff9e4ce7cc6aa2246851b84aTimo Siraineninline static void timeout_update_next(Timeout timeout, struct timeval *tv_now)
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen{
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen if (tv_now == NULL)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen gettimeofday(&timeout->next_run, NULL);
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen else {
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->next_run.tv_sec = tv_now->tv_sec;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->next_run.tv_usec = tv_now->tv_usec;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen /* we don't want microsecond accuracy or this function will be
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen called all the time - millisecond is more than enough */
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->next_run.tv_usec /= 1000;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->next_run.tv_usec *= 1000;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->next_run.tv_sec += timeout->msecs/1000;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->next_run.tv_usec += (timeout->msecs%1000)*1000;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (timeout->next_run.tv_usec > 1000000) {
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->next_run.tv_sec++;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->next_run.tv_usec -= 1000000;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen}
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo SirainenTimeout timeout_add(int msecs, TimeoutFunc func, void *context)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen{
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen Timeout timeout;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout = p_new(current_ioloop->pool, struct _Timeout, 1);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->msecs = msecs;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->func = func;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->context = context;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout_update_next(timeout, current_ioloop->running ?
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen NULL : &ioloop_timeval);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout_list_insert(current_ioloop, timeout);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen return timeout;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen}
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenvoid timeout_remove(Timeout timeout)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen{
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen i_assert(timeout != NULL);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->destroyed = TRUE;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen}
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenvoid timeout_destroy(IOLoop ioloop, Timeout timeout)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen{
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen Timeout *t;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen for (t = &ioloop->timeouts; *t != NULL; t = &(*t)->next) {
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (*t == timeout)
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen break;
beffc30d933c5e134c45cc871852a8427eba7e70Timo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen *t = timeout->next;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen p_free(ioloop->pool, timeout);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen}
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenint io_loop_get_wait_time(Timeout timeout, struct timeval *tv,
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen struct timeval *tv_now)
7026c16186f543e11af12b8b87f396006db93297Timo Sirainen{
7026c16186f543e11af12b8b87f396006db93297Timo Sirainen if (timeout == NULL)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen return INT_MAX;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (tv_now == NULL)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen gettimeofday(tv, NULL);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen else {
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen tv->tv_sec = tv_now->tv_sec;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen tv->tv_usec = tv_now->tv_usec;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen tv->tv_sec = timeout->next_run.tv_sec - tv->tv_sec;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen tv->tv_usec = timeout->next_run.tv_usec - tv->tv_usec;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (tv->tv_usec < 0) {
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen tv->tv_sec--;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen tv->tv_usec += 1000000;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (tv->tv_sec > 0 || (tv->tv_sec == 0 && tv->tv_usec > 0))
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen return tv->tv_sec*1000 + tv->tv_usec/1000;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen /* no need to calculate the times again with this timeout */
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen tv->tv_sec = tv->tv_usec = 0;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout->run_now = TRUE;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen return 0;
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen}
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainenvoid io_loop_handle_timeouts(IOLoop ioloop)
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen{
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen Timeout t, next;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen struct timeval tv;
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen unsigned int t_id;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen gettimeofday(&ioloop_timeval, &ioloop_timezone);
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen ioloop_time = ioloop_timeval.tv_sec;
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen if (ioloop->timeouts == NULL || !ioloop->timeouts->run_now)
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen return;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen for (t = ioloop->timeouts; t != NULL; t = next) {
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen next = t->next;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (t->destroyed) {
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout_destroy(ioloop, t);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen continue;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (!t->run_now) {
4ce6338bf945cccfff9e4ce7cc6aa2246851b84aTimo Sirainen io_loop_get_wait_time(t, &tv, &ioloop_timeval);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (!t->run_now)
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen break;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen }
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen t->run_now = FALSE;
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen timeout_update_next(t, &ioloop_timeval);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen t_id = t_push();
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen t->func(t->context, t);
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainen if (t_pop() != t_id)
da2aa032ccfa8e7e4a4380ef738014549f4d2c2dTimo Sirainen i_panic("Leaked a t_pop() call!");
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen }
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen}
9511a40d933181045343110c8101b75887062aaeTimo Sirainen
f89cb43088c8b46d12d66ac924724b53ab14ce66Timo Sirainenvoid io_loop_run(IOLoop ioloop)
{
ioloop->running = TRUE;
while (ioloop->running)
io_loop_handler_run(ioloop);
}
void io_loop_stop(IOLoop ioloop)
{
ioloop->running = FALSE;
}
void io_loop_set_running(IOLoop ioloop)
{
ioloop->running = TRUE;
}
IOLoop io_loop_create(Pool pool)
{
IOLoop ioloop;
/* initialize time */
gettimeofday(&ioloop_timeval, &ioloop_timezone);
ioloop_time = ioloop_timeval.tv_sec;
ioloop = p_new(pool, struct _IOLoop, 1);
pool_ref(pool);
ioloop->pool = pool;
ioloop->highest_fd = -1;
io_loop_handler_init(ioloop);
ioloop->prev = current_ioloop;
current_ioloop = ioloop;
return ioloop;
}
void io_loop_destroy(IOLoop ioloop)
{
while (ioloop->ios != NULL) {
IO io = ioloop->ios;
if (!io->destroyed) {
i_warning("I/O leak: %p (%d)",
(void *) io->func, io->fd);
io_remove(io);
}
io_destroy(ioloop, io);
}
while (ioloop->timeouts != NULL) {
Timeout to = ioloop->timeouts;
if (!to->destroyed) {
i_warning("Timeout leak: %p", (void *) to->func);
timeout_remove(to);
}
timeout_destroy(ioloop, to);
}
io_loop_handler_deinit(ioloop);
/* ->prev won't work unless loops are destroyed in create order */
i_assert(ioloop == current_ioloop);
current_ioloop = current_ioloop->prev;
pool_unref(ioloop->pool);
}