7 //#include "buffer_tree.h"
13 /** The number of references to this buffer. */
17 struct btr_buffer_reference
{
18 struct btr_buffer
*btrb
;
20 /* Each buffer reference belongs to the buffer queue list of some buffer tree node. */
21 struct list_head node
;
26 struct btr_node
*parent
;
27 /* The position of this btr node in the buffer tree. */
28 struct list_head node
;
29 /* The children nodes of this btr node are linked together in a list. */
30 struct list_head children
;
32 * The input queue is a list of references to btr buffers. Each item on
33 * the list represents an input buffer which has not been completely
34 * used by this btr node.
36 struct list_head input_queue
;
39 #define FOR_EACH_CHILD(_tn, _btrn) list_for_each_entry((_tn), \
40 &((_btrn)->children), node)
42 #define FOR_EACH_BUFFER_REF(_br, _btrn) \
43 list_for_each_entry((_br), &(_btrn)->input_queue, node)
44 #define FOR_EACH_BUFFER_REF_SAFE(_br, _tmp, _btrn) \
45 list_for_each_entry_safe((_br), (_tmp), &(_btrn)->input_queue, node)
47 INIT_STDERR_LOGGING(0);
49 struct btr_node
*btr_new_node(char *name
, struct btr_node
*parent
)
51 struct btr_node
*btrn
= para_malloc(sizeof(*btrn
));
53 btrn
->name
= para_strdup(name
);
54 btrn
->parent
= parent
;
56 list_add_tail(&btrn
->node
, &parent
->children
);
57 INIT_LIST_HEAD(&btrn
->children
);
58 INIT_LIST_HEAD(&btrn
->input_queue
);
63 * Allocate a new btr buffer.
65 * The freshly allocated buffer will have a zero refcount.
67 static struct btr_buffer
*new_btrb(char *buf
, size_t size
)
69 struct btr_buffer
*btrb
= para_malloc(sizeof(*btrb
));
78 * Deallocate the reference, release the resources if refcount drops to zero.
80 void btr_drop_buffer_reference(struct btr_buffer_reference
*br
)
82 struct btr_buffer
*btrb
= br
->btrb
;
87 if (btrb
->refcount
== 0) {
93 static void add_btrb_to_children(struct btr_buffer
*btrb
, struct btr_node
*btrn
)
97 FOR_EACH_CHILD(ch
, btrn
) {
98 struct btr_buffer_reference
*br
= para_malloc(sizeof(*br
));
101 list_add_tail(&br
->node
, &ch
->input_queue
);
106 void btr_add_output(char *buf
, size_t size
, struct btr_node
*btrn
)
108 struct btr_buffer
*btrb
;
110 btrb
= new_btrb(buf
, size
);
111 add_btrb_to_children(btrb
, btrn
);
114 void btr_pushdown_br(struct btr_buffer_reference
*br
, struct btr_node
*btrn
)
116 add_btrb_to_children(br
->btrb
, btrn
);
117 btr_drop_buffer_reference(br
);
120 void btr_pushdown(struct btr_node
*btrn
)
122 struct btr_buffer_reference
*br
, *tmp
;
124 FOR_EACH_BUFFER_REF_SAFE(br
, tmp
, btrn
)
125 btr_pushdown_br(br
, btrn
);
128 /* Return true if this node has no children. */
129 bool btr_is_leaf_node(struct btr_node
*btrn
)
131 return list_empty(&btrn
->children
);
134 bool btr_no_parent(struct btr_node
*btrn
)
136 return !btrn
->parent
;
139 bool btr_inplace_ok(struct btr_node
*btrn
)
143 return list_is_singular(&btrn
->parent
->children
);
146 struct btr_buffer_reference
*btr_next_br(struct btr_node
*btrn
)
148 if (list_empty(&btrn
->input_queue
))
150 return list_first_entry(&btrn
->input_queue
, struct btr_buffer_reference
, node
);
153 static inline size_t br_available_bytes(struct btr_buffer_reference
*br
)
155 return br
->btrb
->size
- br
->consumed
;
158 size_t btr_get_buffer_by_reference(struct btr_buffer_reference
*br
, char **buf
)
160 *buf
= br
->btrb
->buf
+ br
->consumed
;
161 return br_available_bytes(br
);
164 void btr_increase_used_bytes(struct btr_buffer_reference
*br
, size_t consumed
)
166 br
->consumed
+= consumed
;
167 if (br
->consumed
== br
->btrb
->size
)
168 btr_drop_buffer_reference(br
);
171 static void flush_input_queue(struct btr_node
*btrn
)
173 struct btr_buffer_reference
*br
, *tmp
;
174 FOR_EACH_BUFFER_REF_SAFE(br
, tmp
, btrn
)
175 btr_drop_buffer_reference(br
);
178 void btr_del_node(struct btr_node
*btrn
)
182 FOR_EACH_CHILD(ch
, btrn
)
184 flush_input_queue(btrn
);
186 list_del(&btrn
->node
);
191 size_t btr_get_input_queue_size(struct btr_node
*btrn
)
193 struct btr_buffer_reference
*br
;
196 FOR_EACH_BUFFER_REF(br
, btrn
)
197 size
+= br_available_bytes(br
);