blob: 77664889a3b02b8cc5ce56caef480f64e5b4aa2b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <stdio.h>
#include <qpid/dispatch/ctools.h>
#include "router_core_private.h"
ALLOC_DEFINE(qdr_core_timer_t);
void qdr_process_tick_CT(qdr_core_t *core, qdr_action_t *action, bool discard);
void qdr_process_tick(qdr_core_t *core)
{
qdr_action_t *action = qdr_action(qdr_process_tick_CT, "process_tick");
qdr_action_enqueue(core, action);
}
qdr_core_timer_t *qdr_core_timer_CT(qdr_core_t *core, qdr_timer_cb_t callback, void *timer_context)
{
qdr_core_timer_t *timer = new_qdr_core_timer_t();
if (!timer)
return 0;
ZERO(timer);
timer->handler = callback;
timer->context = timer_context;
DEQ_ITEM_INIT(timer);
return timer;
}
void qdr_core_timer_schedule_CT(qdr_core_t *core, qdr_core_timer_t *timer, uint32_t delay)
{
if (timer->scheduled)
qdr_core_timer_cancel_CT(core, timer);
qdr_core_timer_t *ptr = DEQ_HEAD(core->scheduled_timers);
uint32_t time_before = 0;
while (ptr && time_before + ptr->delta_time_seconds <= delay) {
time_before += ptr->delta_time_seconds;
ptr = DEQ_NEXT(ptr);
}
//
// ptr is the first timer to exceed duration or NULL if we ran out
//
timer->delta_time_seconds = delay - time_before;
timer->scheduled = true;
if (!ptr)
DEQ_INSERT_TAIL(core->scheduled_timers, timer);
else {
ptr->delta_time_seconds -= timer->delta_time_seconds;
ptr = DEQ_PREV(ptr);
if (ptr)
DEQ_INSERT_AFTER(core->scheduled_timers, timer, ptr);
else
DEQ_INSERT_HEAD(core->scheduled_timers, timer);
}
}
void qdr_core_timer_cancel_CT(qdr_core_t *core, qdr_core_timer_t *timer)
{
if (timer->scheduled) {
timer->scheduled = false;
if (DEQ_NEXT(timer)) {
DEQ_NEXT(timer)->delta_time_seconds += timer->delta_time_seconds;
}
DEQ_REMOVE(core->scheduled_timers, timer);
}
}
void qdr_core_timer_free_CT(qdr_core_t *core, qdr_core_timer_t *timer)
{
if (!timer)
return;
qdr_core_timer_cancel_CT(core, timer);
free_qdr_core_timer_t(timer);
}
void qdr_process_tick_CT(qdr_core_t *core, qdr_action_t *action, bool discard)
{
if (discard)
return;
core->uptime_ticks++;
qdr_core_timer_t *timer = DEQ_HEAD(core->scheduled_timers);
qdr_core_timer_t *timer_next = 0;
while (timer && timer->delta_time_seconds == 0) {
assert(timer->scheduled);
timer->scheduled = false;
timer_next = DEQ_NEXT(timer);
DEQ_REMOVE(core->scheduled_timers, timer);
if (timer->handler)
timer->handler(core, timer->context);
timer = timer_next;
}
if (timer)
timer->delta_time_seconds--;
}