timer_head_t ordered; //!< A list of timer events to be executed.
struct {
fr_rb_tree_t *rb; //!< a tree of raw pointers
+ fr_rb_tree_t *deferred; //!< a tree of deferred things
size_t time_offset; //!< offset from uctx to the fr_time_t it contains
size_t node_offset; //!< offset from uctx to the fr_rb_node it contains
fr_timer_cb_t callback; //!< the callback to run
static int timer_list_lst_deferred(fr_timer_list_t *tl);
static int timer_list_ordered_deferred(fr_timer_list_t *tl);
+static int timer_list_shared_deferred(fr_timer_list_t *tl);
static uint64_t timer_list_lst_num_events(fr_timer_list_t *tl);
static uint64_t timer_list_ordered_num_events(fr_timer_list_t *tl);
.run = timer_list_shared_run,
// .head = timer_list_shared_head,
-// .deferred = timer_list_shared_deferred,
+ .deferred = timer_list_shared_deferred,
.num_events = timer_list_shared_num_events
},
};
*
* The events don't need to be modified as they
* were initialised completely before being
- * placed in the deffered list.
+ * placed in the deferred list.
*/
if (timer_num_elements(&tl->deferred) > 0) {
if (unlikely(timer_funcs[tl->type].deferred(tl) < 0)) return -1;
return ret;
}
-/** Return the head of the event list
+/** Return the head of the lst
*
* @param[in] tl to get the head of.
* @return
return timer_head(&tl->ordered);
}
-/** Insert a timer event into a the lst
+
+/** Move all deferred events into the lst
*
* @param[in] tl to move events in.
* @return
return 0;
}
+/** Move all deferred events into the shared list
+ *
+ * @param[in] tl to move events in.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+static int timer_list_shared_deferred(fr_timer_list_t *tl)
+{
+ void *uctx;
+
+ while((uctx = fr_rb_first(tl->shared.deferred)) != NULL) {
+ fr_rb_remove_by_inline_node(tl->shared.deferred,
+ (fr_rb_node_t *) (((uintptr_t) (uctx)) + tl->shared.node_offset));
+
+ fr_rb_insert(tl->shared.deferred, uctx);
+ }
+
+ return 0;
+}
+
+
static uint64_t timer_list_lst_num_events(fr_timer_list_t *tl)
{
return fr_lst_num_elements(tl->lst);
if (tl->parent_ev) if (unlikely(fr_timer_delete(&tl->parent_ev) < 0)) return -1;
- switch (tl->type) {
- default:
- while ((ev = timer_funcs[tl->type].head(tl))) {
- if (talloc_free(ev) < 0) return -1;
- }
- break;
+ if (tl->type == TIMER_LIST_TYPE_SHARED) return 0;
- case TIMER_LIST_TYPE_SHARED: /* the caller owns the memory for uctx */
- break;
+ while ((ev = timer_funcs[tl->type].head(tl))) {
+ if (talloc_free(ev) < 0) return -1;
}
return 0;
{
fr_timer_list_t *tl;
+ fr_assert(!parent || (parent->type != TIMER_LIST_TYPE_SHARED));
+
tl = talloc_zero(ctx, fr_timer_list_t);
if (unlikely(tl == NULL)) {
fr_strerror_const("Out of memory");
return NULL;
}
+ tl->shared.deferred = _fr_rb_alloc(tl, node_offset, NULL, cmp, NULL);
+ if (!tl->shared.deferred) {
+ talloc_free(tl);
+ return NULL;
+ }
+
return tl;
}
{
fr_assert(tl->type == TIMER_LIST_TYPE_SHARED);
+ if (tl->in_handler) {
+ if (!fr_rb_insert(tl->shared.deferred, uctx)) return -1;
+
+ return 0;
+ }
+
if (!fr_rb_insert(tl->shared.rb, uctx)) return -1;
return timer_list_parent_update(tl);
* @param[in] tl Timer list to insert into.
* @param[in] uctx to remove
* @return
- * - 1 uctx was successfully removed
- * - 0 uctx wasn't in the list, nothing happened
+ * - 0 uctx was successfully removed.
* - -1 uctx was removed, but the parent timer was not updated
*/
int fr_timer_uctx_remove(fr_timer_list_t *tl, void *uctx)
fr_rb_remove_by_inline_node(tl->shared.rb,
(fr_rb_node_t *) (((uintptr_t) (uctx)) + tl->shared.node_offset));
- if (timer_list_parent_update(tl) < 0) return -1;
-
- return 1;
+ return timer_list_parent_update(tl);
}
void *fr_timer_uctx_peek(fr_timer_list_t *tl)