summaryrefslogtreecommitdiffstats
path: root/src/vppinfra/fheap.h
blob: 6d4965f1beaf52e1e6a16fb1b0306b55fa01e759 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * Copyright (c) 2015 Cisco and/or its affiliates.
 * Licensed 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.
 */
#ifndef included_clib_fheap_h
#define included_clib_fheap_h

/* Fibonacci Heaps Fredman, M. L.; Tarjan (1987).
   "Fibonacci heaps and their uses in improved network optimization algorithms" */

#include <vppinfra/vec.h>

typedef struct
{
  /* Node index of parent. */
  u32 parent;

  /* Node index of first child. */
  u32 first_child;

  /* Next and previous nodes in doubly linked list of siblings. */
  u32 next_sibling, prev_sibling;

  /* Key (distance) for this node.  Parent always has key
     <= than keys of children. */
  u32 key;

  /* Number of children (as opposed to descendents). */
  u32 rank;

  u32 is_marked;

  /* Set to one when node is inserted; zero when deleted. */
  u32 is_valid;
} fheap_node_t;

#define foreach_fheap_node_sibling(f,ni,first_ni,body)			\
do {									\
  u32 __fheap_foreach_first_ni = (first_ni);				\
  u32 __fheap_foreach_ni = __fheap_foreach_first_ni;			\
  u32 __fheap_foreach_next_ni;						\
  fheap_node_t * __fheap_foreach_n;					\
  if (__fheap_foreach_ni != ~0)						\
    while (1)								\
      {									\
	__fheap_foreach_n = fheap_get_node ((f), __fheap_foreach_ni);	\
	__fheap_foreach_next_ni = __fheap_foreach_n -> next_sibling;	\
	(ni) = __fheap_foreach_ni;					\
									\
	body;								\
									\
	/* End of circular list? */					\
	if (__fheap_foreach_next_ni == __fheap_foreach_first_ni)	\
	  break;							\
									\
	__fheap_foreach_ni = __fheap_foreach_next_ni;			\
									\
      }									\
} while (0)

typedef struct
{
  u32 min_root;

  /* Vector of nodes. */
  fheap_node_t *nodes;

  u32 *root_list_by_rank;

  u32 enable_validate;

  u32 validate_serial;
} fheap_t;

/* Initialize empty heap. */
always_inline void
fheap_init (fheap_t * f, u32 n_nodes)
{
  fheap_node_t *save_nodes = f->nodes;
  u32 *save_root_list = f->root_list_by_rank;

  memset (f, 0, sizeof (f[0]));

  f->nodes = save_nodes;
  f->root_list_by_rank = save_root_list;

  vec_validate (f->nodes, n_nodes - 1);
  vec_reset_length (f->root_list_by_rank);

  f->min_root = ~0;
}

always_inline void
fheap_free (fheap_t * f)
{
  vec_free (f->nodes);
  vec_free (f->root_list_by_rank);
}

always_inline u32
fheap_find_min (fheap_t * f)
{
  return f->min_root;
}

always_inline u32
fheap_is_empty (fheap_t * f)
{
  return f->min_root == ~0;
}

/* Add/delete nodes. */
void fheap_add (fheap_t * f, u32 ni, u32 key);
void fheap_del (fheap_t * f, u32 ni);

/* Delete and return minimum. */
u32 fheap_del_min (fheap_t * f, u32 * min_key);

/* Change key value. */
void fheap_decrease_key (fheap_t * f, u32 ni, u32 new_key);

#endif /* included_clib_fheap_h */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
> u16 fast_ring_offset; /** slow ring offset, only valid in the glacier ring */ u16 slow_ring_offset; #endif #if (TW_TIMER_WHEELS == 2) /** fast ring offset, only valid in the slow ring */ u16 fast_ring_offset; /** slow ring offset, only valid in the glacier ring */ u16 pad; #endif }; #if (TW_OVERFLOW_VECTOR > 0) u64 expiration_time; #endif }; /** user timer handle */ u32 user_handle; } TWT (tw_timer); /* * These structures ar used by all geometries, * so they need a private #include block... */ #ifndef __defined_tw_timer_wheel_slot__ #define __defined_tw_timer_wheel_slot__ typedef struct { /** Listhead of timers which expire in this interval */ u32 head_index; } tw_timer_wheel_slot_t; typedef enum { /** Fast timer ring ID */ TW_TIMER_RING_FAST, /** Slow timer ring ID */ TW_TIMER_RING_SLOW, /** Glacier ring ID */ TW_TIMER_RING_GLACIER, } tw_ring_index_t; #endif /* __defined_tw_timer_wheel_slot__ */ typedef CLIB_PACKED (struct { u8 timer_id; u32 pool_index; u32 handle; }) TWT (trace); typedef struct { /** Timer pool */ TWT (tw_timer) * timers; /** Next time the wheel should run */ f64 next_run_time; /** Last time the wheel ran */ f64 last_run_time; /** Timer ticks per second */ f64 ticks_per_second; /** Timer interval, also needed to avoid fp divide in speed path */ f64 timer_interval; /** current tick */ u64 current_tick; /** first expiration time */ u64 first_expires_tick; /** current wheel indices */ u32 current_index[TW_TIMER_WHEELS]; /** wheel arrays */ tw_timer_wheel_slot_t w[TW_TIMER_WHEELS][TW_SLOTS_PER_RING]; #if TW_OVERFLOW_VECTOR > 0 tw_timer_wheel_slot_t overflow; #endif #if TW_FAST_WHEEL_BITMAP > 0 /** Fast wheel slot occupancy bitmap */ uword *fast_slot_bitmap; #endif /** expired timer callback, receives a vector of handles */ void (*expired_timer_callback) (u32 * expired_timer_handles); /** vectors of expired timers */ u32 *expired_timer_handles; /** maximum expirations */ u32 max_expirations; /** current trace index */ #if TW_START_STOP_TRACE_SIZE > 0 /* Start/stop/expire tracing */ u32 trace_index; u32 trace_wrapped; TWT (trace) traces[TW_START_STOP_TRACE_SIZE]; #endif } TWT (tw_timer_wheel); u32 TW (tw_timer_start) (TWT (tw_timer_wheel) * tw, u32 pool_index, u32 timer_id, u64 interval); void TW (tw_timer_stop) (TWT (tw_timer_wheel) * tw, u32 handle); int TW (tw_timer_handle_is_free) (TWT (tw_timer_wheel) * tw, u32 handle); void TW (tw_timer_update) (TWT (tw_timer_wheel) * tw, u32 handle, u64 interval); void TW (tw_timer_wheel_init) (TWT (tw_timer_wheel) * tw, void *expired_timer_callback, f64 timer_interval, u32 max_expirations); void TW (tw_timer_wheel_free) (TWT (tw_timer_wheel) * tw); u32 *TW (tw_timer_expire_timers) (TWT (tw_timer_wheel) * tw, f64 now); u32 *TW (tw_timer_expire_timers_vec) (TWT (tw_timer_wheel) * tw, f64 now, u32 * vec); #if TW_FAST_WHEEL_BITMAP u32 TW (tw_timer_first_expires_in_ticks) (TWT (tw_timer_wheel) * tw); #endif #if TW_START_STOP_TRACE_SIZE > 0 void TW (tw_search_trace) (TWT (tw_timer_wheel) * tw, u32 handle); void TW (tw_timer_trace) (TWT (tw_timer_wheel) * tw, u32 timer_id, u32 pool_index, u32 handle); #endif /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */