ioloop.c revision 007d354a674fb3ddf49db160cf050cf61270a1a0
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen Copyright (c) 2002 Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen Permission is hereby granted, free of charge, to any person obtaining
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen a copy of this software and associated documentation files (the
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "Software"), to deal in the Software without restriction, including
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen without limitation the rights to use, copy, modify, merge, publish,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen distribute, sublicense, and/or sell copies of the Software, and to
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen permit persons to whom the Software is furnished to do so, subject to
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen the following conditions:
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen The above copyright notice and this permission notice shall be
1d738cce754bc64bbc66d3355ebdaf3f6eac55f1Timo Sirainen included in all copies or substantial portions of the Software.
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
f9f30736bc6e4cf535085824e7e124506fe2dbbbTimo Sirainen IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainenstatic void update_highest_fd(struct ioloop *ioloop)
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen for (io = ioloop->ios; io != NULL; io = io->next) {
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen if (!io->destroyed && io->fd > ioloop->highest_fd) {
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainenstruct io *io_add(int fd, int condition, io_callback_t *callback, void *context)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io = p_new(current_ioloop->pool, struct io, 1);
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen io_loop_handle_add(current_ioloop, io->fd, io->condition);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_assert(io->fd <= current_ioloop->highest_fd);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* notify the real I/O handler */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_loop_handle_remove(current_ioloop, io->fd, io->condition);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* check if we removed the highest fd */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid io_destroy(struct ioloop *ioloop, struct io **io_p)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* remove from list */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic void timeout_list_insert(struct ioloop *ioloop, struct timeout *timeout)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen for (t = &ioloop->timeouts; *t != NULL; t = &(*t)->next) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic void timeout_update_next(struct timeout *timeout, struct timeval *tv_now)
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen if (gettimeofday(&timeout->next_run, NULL) < 0)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* we don't want microsecond accuracy or this function will be
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen called all the time - millisecond is more than enough */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen timeout->next_run.tv_usec -= timeout->next_run.tv_usec % 1000;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout->next_run.tv_sec += timeout->msecs/1000;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout->next_run.tv_usec += (timeout->msecs%1000)*1000;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenstruct timeout *timeout_add(unsigned int msecs, timeout_callback_t *callback,
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen timeout = p_new(current_ioloop->pool, struct timeout, 1);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout_update_next(timeout, current_ioloop->running ?
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenvoid timeout_destroy(struct ioloop *ioloop, struct timeout **timeout_p)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenint io_loop_get_wait_time(struct timeout *timeout, struct timeval *tv,
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen /* no timeouts. give it INT_MAX msecs. */
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen tv->tv_sec = timeout->next_run.tv_sec - tv->tv_sec;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen tv->tv_usec = timeout->next_run.tv_usec - tv->tv_usec;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (tv->tv_sec > 0 || (tv->tv_sec == 0 && tv->tv_usec > 0))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* no need to calculate the times again with this timeout */
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainenvoid io_loop_handle_timeouts(struct ioloop *ioloop)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen unsigned int t_id;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ioloop->timeouts == NULL || !ioloop->timeouts->run_now)
57dd2621d4230bc2e06c69a4b9f8cf8f0ff2bc93Timo Sirainen for (t = ioloop->timeouts; t != NULL; t = *t_p) {
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen io_loop_get_wait_time(t, &tv, &ioloop_timeval);
1ff03d2244dd08effadfecec365bec28793a1aa0Timo Sirainenvoid io_loop_set_running(struct ioloop *ioloop)
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen /* initialize time */
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen i_warning("Timeout leak: %p", (void *) to->callback);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* ->prev won't work unless loops are destroyed in create order */