]> git.proxmox.com Git - libgit2.git/blob - src/threadstate.c
New upstream version 1.3.0+dfsg.1
[libgit2.git] / src / threadstate.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include "threadstate.h"
9 #include "runtime.h"
10
11 /**
12 * Handle the thread-local state
13 *
14 * `git_threadstate_global_init` will be called as part
15 * of `git_libgit2_init` (which itself must be called
16 * before calling any other function in the library).
17 *
18 * This function allocates a TLS index to store the per-
19 * thread state.
20 *
21 * Any internal method that requires thread-local state
22 * will then call `git_threadstate_get()` which returns a
23 * pointer to the thread-local state structure; this
24 * structure is lazily allocated on each thread.
25 *
26 * This mechanism will register a shutdown handler
27 * (`git_threadstate_global_shutdown`) which will free the
28 * TLS index. This shutdown handler will be called by
29 * `git_libgit2_shutdown`.
30 */
31
32 static git_tlsdata_key tls_key;
33
34 static void threadstate_dispose(git_threadstate *threadstate)
35 {
36 if (!threadstate)
37 return;
38
39 if (threadstate->error_t.message != git_buf__initbuf)
40 git__free(threadstate->error_t.message);
41 threadstate->error_t.message = NULL;
42 }
43
44 static void GIT_SYSTEM_CALL threadstate_free(void *threadstate)
45 {
46 threadstate_dispose(threadstate);
47 git__free(threadstate);
48 }
49
50 static void git_threadstate_global_shutdown(void)
51 {
52 git_threadstate *threadstate;
53
54 threadstate = git_tlsdata_get(tls_key);
55 git_tlsdata_set(tls_key, NULL);
56
57 threadstate_dispose(threadstate);
58 git__free(threadstate);
59
60 git_tlsdata_dispose(tls_key);
61 }
62
63 int git_threadstate_global_init(void)
64 {
65 if (git_tlsdata_init(&tls_key, &threadstate_free) != 0)
66 return -1;
67
68 return git_runtime_shutdown_register(git_threadstate_global_shutdown);
69 }
70
71 git_threadstate *git_threadstate_get(void)
72 {
73 git_threadstate *threadstate;
74
75 if ((threadstate = git_tlsdata_get(tls_key)) != NULL)
76 return threadstate;
77
78 if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL ||
79 git_buf_init(&threadstate->error_buf, 0) < 0)
80 return NULL;
81
82 git_tlsdata_set(tls_key, threadstate);
83 return threadstate;
84 }