pool.h 4.31 KB
Newer Older
1
/*
Edward Thomson committed
2
 * Copyright (C) the libgit2 contributors. All rights reserved.
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
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */
#ifndef INCLUDE_pool_h__
#define INCLUDE_pool_h__

#include "common.h"

typedef struct git_pool_page git_pool_page;

/**
 * Chunked allocator.
 *
 * A `git_pool` can be used when you want to cheaply allocate
 * multiple items of the same type and are willing to free them
 * all together with a single call.  The two most common cases
 * are a set of fixed size items (such as lots of OIDs) or a
 * bunch of strings.
 *
 * Internally, a `git_pool` allocates pages of memory and then
 * deals out blocks from the trailing unused portion of each page.
 * The pages guarantee that the number of actual allocations done
 * will be much smaller than the number of items needed.
 *
 * For examples of how to set up a `git_pool` see `git_pool_init`.
 */
typedef struct {
	git_pool_page *open; /* pages with space left */
	git_pool_page *full; /* pages with no space left */
	void *free_list;     /* optional: list of freed blocks */
	uint32_t item_size;  /* size of single alloc unit in bytes */
	uint32_t page_size;  /* size of page in bytes */
36
	uint32_t items;
37 38 39 40 41
	unsigned has_string_alloc : 1; /* was the strdup function used */
	unsigned has_multi_item_alloc : 1; /* was items ever > 1 in malloc */
	unsigned has_large_page_alloc : 1; /* are any pages > page_size */
} git_pool;

42 43
#define GIT_POOL_INIT_STRINGPOOL { 0, 0, 0, 1, 4000, 0, 0, 0, 0 }

44 45 46 47 48 49 50 51 52 53 54
/**
 * Initialize a pool.
 *
 * To allocation strings, use like this:
 *
 *     git_pool_init(&string_pool, 1, 0);
 *     my_string = git_pool_strdup(&string_pool, your_string);
 *
 * To allocate items of fixed size, use like this:
 *
 *     git_pool_init(&pool, sizeof(item), 0);
55
 *     my_item = git_pool_malloc(&pool, 1);
56 57 58 59 60 61 62 63 64 65 66 67 68
 *
 * Of course, you can use this in other ways, but those are the
 * two most common patterns.
 */
extern int git_pool_init(
	git_pool *pool, uint32_t item_size, uint32_t items_per_page);

/**
 * Free all items in pool
 */
extern void git_pool_clear(git_pool *pool);

/**
69 70 71 72 73
 * Swap two pools with one another
 */
extern void git_pool_swap(git_pool *a, git_pool *b);

/**
74 75
 * Allocate space for one or more items from a pool.
 */
76
extern void *git_pool_malloc(git_pool *pool, uint32_t items);
77 78

/**
Russell Belfer committed
79 80 81 82 83 84 85 86 87 88 89
 * Allocate space and zero it out.
 */
GIT_INLINE(void *) git_pool_mallocz(git_pool *pool, uint32_t items)
{
	void *ptr = git_pool_malloc(pool, items);
	if (ptr)
		memset(ptr, 0, (size_t)items * (size_t)pool->item_size);
	return ptr;
}

/**
90 91 92 93 94 95 96 97 98 99 100 101 102 103
 * Allocate space and duplicate string data into it.
 *
 * This is allowed only for pools with item_size == sizeof(char)
 */
extern char *git_pool_strndup(git_pool *pool, const char *str, size_t n);

/**
 * Allocate space and duplicate a string into it.
 *
 * This is allowed only for pools with item_size == sizeof(char)
 */
extern char *git_pool_strdup(git_pool *pool, const char *str);

/**
104 105 106 107 108 109 110
 * Allocate space and duplicate a string into it, NULL is no error.
 *
 * This is allowed only for pools with item_size == sizeof(char)
 */
extern char *git_pool_strdup_safe(git_pool *pool, const char *str);

/**
111 112 113 114 115 116 117
 * Allocate space for the concatenation of two strings.
 *
 * This is allowed only for pools with item_size == sizeof(char)
 */
extern char *git_pool_strcat(git_pool *pool, const char *a, const char *b);

/**
118 119 120 121 122 123 124 125 126 127 128
 * Push a block back onto the free list for the pool.
 *
 * This is allowed only if the item_size is >= sizeof(void*).
 *
 * In some cases, it is helpful to "release" an allocated block
 * for reuse.  Pools don't support a general purpose free, but
 * they will keep a simple free blocks linked list provided the
 * native block size is large enough to hold a void pointer
 */
extern void git_pool_free(git_pool *pool, void *ptr);

129 130 131 132 133 134 135
/**
 * Push an array of pool allocated blocks efficiently onto the free list.
 *
 * This has the same constraints as `git_pool_free()` above.
 */
extern void git_pool_free_array(git_pool *pool, size_t count, void **ptrs);

136 137 138 139 140 141 142 143 144 145 146 147
/*
 * Misc utilities
 */

extern uint32_t git_pool__open_pages(git_pool *pool);

extern uint32_t git_pool__full_pages(git_pool *pool);

extern bool git_pool__ptr_in_pool(git_pool *pool, void *ptr);

extern uint32_t git_pool__system_page_size(void);

148 149
extern uint32_t git_pool__suggest_items_per_page(uint32_t item_size);

150
#endif