mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-09 18:22:16 +00:00

This adds a `git_pool` object that can do simple paged memory allocation with free for the entire pool at once. Using this, you can replace many small allocations with large blocks that can then cheaply be doled out in small pieces. This is best used when you plan to free the small blocks all at once - for example, if they represent the parsed state from a file or data stream that are either all kept or all discarded. There are two real patterns of usage for `git_pools`: either for "string" allocation, where the item size is a single byte and you end up just packing the allocations in together, or for "fixed size" allocation where you are allocating a large object (e.g. a `git_oid`) and you generally just allocation single objects that can be tightly packed. Of course, you can use it for other things, but those two cases are the easiest.
135 lines
2.6 KiB
C
135 lines
2.6 KiB
C
/*
|
|
* Copyright (C) 2009-2012 the libgit2 contributors
|
|
*
|
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
|
* a Linking Exception. For full terms see the included COPYING file.
|
|
*/
|
|
#include "common.h"
|
|
#include "global.h"
|
|
#include "git2/threads.h"
|
|
#include "thread-utils.h"
|
|
|
|
/**
|
|
* Handle the global state with TLS
|
|
*
|
|
* If libgit2 is built with GIT_THREADS enabled,
|
|
* the `git_threads_init()` function must be called
|
|
* before calling any other function of the library.
|
|
*
|
|
* This function allocates a TLS index (using pthreads
|
|
* or the native Win32 API) to store the global state
|
|
* on a per-thread basis.
|
|
*
|
|
* Any internal method that requires global state will
|
|
* then call `git__global_state()` which returns a pointer
|
|
* to the global state structure; this pointer is lazily
|
|
* allocated on each thread.
|
|
*
|
|
* Before shutting down the library, the
|
|
* `git_threads_shutdown` method must be called to free
|
|
* the previously reserved TLS index.
|
|
*
|
|
* If libgit2 is built without threading support, the
|
|
* `git__global_statestate()` call returns a pointer to a single,
|
|
* statically allocated global state. The `git_thread_`
|
|
* functions are not available in that case.
|
|
*/
|
|
|
|
#if defined(GIT_THREADS) && defined(GIT_WIN32)
|
|
|
|
static DWORD _tls_index;
|
|
static int _tls_init = 0;
|
|
|
|
void git_threads_init(void)
|
|
{
|
|
if (_tls_init)
|
|
return;
|
|
|
|
_tls_index = TlsAlloc();
|
|
_tls_init = 1;
|
|
}
|
|
|
|
void git_threads_shutdown(void)
|
|
{
|
|
TlsFree(_tls_index);
|
|
_tls_init = 0;
|
|
}
|
|
|
|
git_global_st *git__global_state(void)
|
|
{
|
|
void *ptr;
|
|
|
|
if ((ptr = TlsGetValue(_tls_index)) != NULL)
|
|
return ptr;
|
|
|
|
ptr = git__malloc(sizeof(git_global_st));
|
|
if (!ptr)
|
|
return NULL;
|
|
|
|
memset(ptr, 0x0, sizeof(git_global_st));
|
|
TlsSetValue(_tls_index, ptr);
|
|
return ptr;
|
|
}
|
|
|
|
#elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
|
|
|
|
static pthread_key_t _tls_key;
|
|
static int _tls_init = 0;
|
|
|
|
static void cb__free_status(void *st)
|
|
{
|
|
git__free(st);
|
|
}
|
|
|
|
void git_threads_init(void)
|
|
{
|
|
if (_tls_init)
|
|
return;
|
|
|
|
pthread_key_create(&_tls_key, &cb__free_status);
|
|
_tls_init = 1;
|
|
}
|
|
|
|
void git_threads_shutdown(void)
|
|
{
|
|
pthread_key_delete(_tls_key);
|
|
_tls_init = 0;
|
|
}
|
|
|
|
git_global_st *git__global_state(void)
|
|
{
|
|
void *ptr;
|
|
|
|
if ((ptr = pthread_getspecific(_tls_key)) != NULL)
|
|
return ptr;
|
|
|
|
ptr = git__malloc(sizeof(git_global_st));
|
|
if (!ptr)
|
|
return NULL;
|
|
|
|
memset(ptr, 0x0, sizeof(git_global_st));
|
|
pthread_setspecific(_tls_key, ptr);
|
|
return ptr;
|
|
}
|
|
|
|
#else
|
|
|
|
static git_global_st __state;
|
|
|
|
void git_threads_init(void)
|
|
{
|
|
/* noop */
|
|
}
|
|
|
|
void git_threads_shutdown(void)
|
|
{
|
|
/* noop */
|
|
}
|
|
|
|
git_global_st *git__global_state(void)
|
|
{
|
|
return &__state;
|
|
}
|
|
|
|
#endif /* GIT_THREADS */
|