struct btr_buffer_reference, node);
}
+static struct btr_buffer_reference *get_last_input_br(struct btr_node *btrn)
+{
+ if (list_empty(&btrn->input_queue))
+ return NULL;
+ return list_last_entry(&btrn->input_queue,
+ struct btr_buffer_reference, node);
+}
+
/*
* Deallocate the reference, release the resources if refcount drops to zero.
*/
}
}
+static bool may_merge_btrb(const struct btr_buffer *btrb,
+ const struct btr_buffer_reference *br)
+{
+ if (!br)
+ return false;
+ if (br->consumed > 0)
+ return false;
+ if (br->btrb->buf + br->btrb->size != btrb->buf)
+ return false;
+ if (!br->btrb->pool)
+ return true;
+ return br->btrb->size + btrb->size < btr_pool_size(br->btrb->pool) / 3;
+}
+
static void add_btrb_to_children(struct btr_buffer *btrb,
struct btr_node *btrn, size_t consumed)
{
if (btrn->start.tv_sec == 0)
btrn->start = *now;
FOR_EACH_CHILD(ch, btrn) {
- struct btr_buffer_reference *br = zalloc(sizeof(*br));
- br->btrb = btrb;
- br->consumed = consumed;
- list_add_tail(&br->node, &ch->input_queue);
- btrb->refcount++;
+ struct btr_buffer_reference *br = get_last_input_br(ch);
+ if (may_merge_btrb(btrb, br)) {
+ br->btrb->size += btrb->size;
+ free(btrb);
+ } else {
+ br = zalloc(sizeof(*br));
+ br->btrb = btrb;
+ br->consumed = consumed;
+ list_add_tail(&br->node, &ch->input_queue);
+ btrb->refcount++;
+ }
if (ch->start.tv_sec == 0)
ch->start = *now;
}
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
+#define list_last_entry(ptr, type, member) \
+ list_entry((ptr)->prev, type, member)