ウォンツテック

そでやまのーと

bucketのheapに関する操作

static apr_status_t heap_bucket_read(apr_bucket *b, const char **str,                                     apr_size_t *len, apr_read_type_e block)
{
    apr_bucket_heap *h = b->data;

    *str = h->base + b->start;
    *len = b->length;
    return APR_SUCCESS;
}

bucketからデータを*strに読み込む。

static void heap_bucket_destroy(void *data)
{
    apr_bucket_heap *h = data;

    if (apr_bucket_shared_destroy(h)) {
        (*h->free_func)(h->base);
        apr_bucket_free(h);
    }
}

//apr_buckets_refcount.c
APU_DECLARE(int) apr_bucket_shared_destroy(void *data)
{
    apr_bucket_refcount *r = data;
    r->refcount--;
    return (r->refcount == 0);
}
||
refcountが0(どこからも参照されていない)ならばデータをfreeする

-apr_bucket_heap_make
>|c|
APU_DECLARE(apr_bucket *) apr_bucket_heap_make(apr_bucket *b, const char *buf,                                               apr_size_t length,                                               void (*free_func)(void *data))
||
1. apr_bucket_allocでメモリを確保する
2. free_funcがNULLならばデフォルトのfree処理(apr_bucket_free)をセットし新しいheap領域にデータbufをコピーする
3. free_funcが引数で渡されていればそれをセット
4. apr_bucket_shared_makeを呼び出す

-apr_bucket_shared_make
(apr_buckets_refcoount.c)
>|c|
APU_DECLARE(apr_bucket *) apr_bucket_shared_make(apr_bucket *b, void *data,                                                 apr_off_t start,                                                 apr_size_t length)
{
    apr_bucket_refcount *r = data;

    b->data   = r;
    b->start  = start;
    b->length = length;
    /* caller initializes the type field */
    r->refcount = 1;

    return b;
}

共有bucketの作成

APU_DECLARE(apr_bucket *) apr_bucket_heap_create(const char *buf,                                                 apr_size_t length,                                                 void (*free_func)(void *data),                                                 apr_bucket_alloc_t *list)

1. apr_bucket_allocでメモリ確保
2. APR_BUCKET_INITの呼び出し

#define APR_BUCKET_INIT(e) APR_RING_ELEM_INIT((e), link)
#define APR_RING_ELEM_INIT(ep, link) do {
APR_RING_NEXT((ep), link) = (ep);
APR_RING_PREV((ep), link) = (ep);
} while (0)

3. apr_bucket_heap_makeの呼び出し

APU_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t size,                                            apr_bucket_alloc_t *list)
{
    node_header_t *node;
    apr_memnode_t *active = list->blocks;
    char *endp;

    size += SIZEOF_NODE_HEADER_T;
    if (size <= SMALL_NODE_SIZE) {
        if (list->freelist) {
            node = list->freelist;
            list->freelist = node->next;
        }
        else {
            endp = active->first_avail + SMALL_NODE_SIZE;
            if (endp >= active->endp) {
                list->blocks = apr_allocator_alloc(list->allocator, ALLOC_AMT);
                list->blocks->next = active;
                active = list->blocks;
                endp = active->first_avail + SMALL_NODE_SIZE;
            }
            node = (node_header_t *)active->first_avail;
            node->alloc = list;
            node->memnode = active;
            node->size = SMALL_NODE_SIZE;
            active->first_avail = endp;
        }
    }
    else {
        apr_memnode_t *memnode = apr_allocator_alloc(list->allocator, size);
        node = (node_header_t *)memnode->first_avail;
        node->alloc = list;
        node->memnode = memnode;
        node->size = size;
    }
    return ((char *)node) + SIZEOF_NODE_HEADER_T;
}

freeリストから空いているメモリ領域の位置を取得。
空きがなければfreeリストを拡張する。