From 6d91dc53514aa9eec4bdf2326d1f7657ac2426b3 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 3 Dec 2014 15:28:44 -0500 Subject: [PATCH] init: return the number of initializations --- CHANGELOG.md | 4 ++++ include/git2/global.h | 14 ++++++++++---- src/global.c | 44 +++++++++++++++++++++++++++++-------------- tests/core/init.c | 14 ++++++++++++++ 4 files changed, 58 insertions(+), 18 deletions(-) create mode 100644 tests/core/init.c diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b9d92442..7bc40c511 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -126,3 +126,7 @@ v0.21 + 1 * git_threads_init() and git_threads_shutdown() have been renamed to git_libgit2_init() and git_libgit2_shutdown() to better explain what their purpose is, as it's grown to be more than just about threads. + +* git_libgit2_init() and git_libgit2_shutdown() now return the number of + initializations of the library, so consumers may schedule work on the + first initialization. diff --git a/include/git2/global.h b/include/git2/global.h index 4f90c4c20..ce5bdf444 100644 --- a/include/git2/global.h +++ b/include/git2/global.h @@ -17,9 +17,11 @@ GIT_BEGIN_DECL * This function must the called before any other libgit2 function in * order to set up global state and threading. * - * This function may be called multiple times. + * This function may be called multiple times - it will return the number + * of times the initialization has been called (including this one) that have + * not subsequently been shutdown. * - * @return 0 or an error code + * @return the number of initializations of the library, or an error code. */ GIT_EXTERN(int) git_libgit2_init(void); @@ -27,10 +29,14 @@ GIT_EXTERN(int) git_libgit2_init(void); * Shutdown the global state * * Clean up the global state and threading context after calling it as - * many times as `git_libgit2_init()` was called. + * many times as `git_libgit2_init()` was called - it will return the + * number of remainining initializations that have not been shutdown + * (after this one). * + * @return the number of remaining initializations of the library, or an + * error code. */ -GIT_EXTERN(void) git_libgit2_shutdown(void); +GIT_EXTERN(int) git_libgit2_shutdown(void); /** @} */ GIT_END_DECL diff --git a/src/global.c b/src/global.c index 006202a2c..b3e75a0e2 100644 --- a/src/global.c +++ b/src/global.c @@ -194,19 +194,21 @@ static int synchronized_threads_init(void) int git_libgit2_init(void) { - int error = 0; + int ret; /* Enter the lock */ while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); } /* Only do work on a 0 -> 1 transition of the refcount */ - if (1 == git_atomic_inc(&git__n_inits)) - error = synchronized_threads_init(); + if ((ret = git_atomic_inc(&git__n_inits)) == 1) { + if (synchronized_threads_init() < 0) + ret = -1; + } /* Exit the lock */ InterlockedExchange(&_mutex, 0); - return error; + return ret; } static void synchronized_threads_shutdown(void) @@ -217,17 +219,21 @@ static void synchronized_threads_shutdown(void) git_mutex_free(&git__mwindow_mutex); } -void git_libgit2_shutdown(void) +int git_libgit2_shutdown(void) { + int ret; + /* Enter the lock */ while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); } /* Only do work on a 1 -> 0 transition of the refcount */ - if (0 == git_atomic_dec(&git__n_inits)) + if ((ret = git_atomic_dec(&git__n_inits)) == 0) synchronized_threads_shutdown(); /* Exit the lock */ InterlockedExchange(&_mutex, 0); + + return ret; } git_global_st *git__global_state(void) @@ -281,17 +287,22 @@ static void init_once(void) int git_libgit2_init(void) { + int ret; + pthread_once(&_once_init, init_once); - git_atomic_inc(&git__n_inits); - return init_error; + ret = git_atomic_inc(&git__n_inits); + + return init_error ? init_error : ret; } -void git_libgit2_shutdown(void) +int git_libgit2_shutdown(void) { void *ptr = NULL; pthread_once_t new_once = PTHREAD_ONCE_INIT; + int ret; - if (git_atomic_dec(&git__n_inits) > 0) return; + if ((ret = git_atomic_dec(&git__n_inits)) > 0) + return ret; /* Shut down any subsystems that have global state */ git__shutdown(); @@ -303,6 +314,8 @@ void git_libgit2_shutdown(void) pthread_key_delete(_tls_key); git_mutex_free(&git__mwindow_mutex); _once_init = new_once; + + return ret; } git_global_st *git__global_state(void) @@ -336,15 +349,18 @@ int git_libgit2_init(void) ssl_inited = 1; } - git_atomic_inc(&git__n_inits); - return 0; + return git_atomic_inc(&git__n_inits); } -void git_libgit2_shutdown(void) +int git_libgit2_shutdown(void) { + int ret; + /* Shut down any subsystems that have global state */ - if (0 == git_atomic_dec(&git__n_inits)) + if (ret = git_atomic_dec(&git__n_inits)) git__shutdown(); + + return ret; } git_global_st *git__global_state(void) diff --git a/tests/core/init.c b/tests/core/init.c new file mode 100644 index 000000000..e17b7845f --- /dev/null +++ b/tests/core/init.c @@ -0,0 +1,14 @@ +#include "clar_libgit2.h" + +void test_core_init__returns_count(void) +{ + /* libgit2_clar initializes us first, so we have an existing + * initialization. + */ + cl_assert_equal_i(2, git_libgit2_init()); + cl_assert_equal_i(3, git_libgit2_init()); + + cl_assert_equal_i(2, git_libgit2_shutdown()); + cl_assert_equal_i(1, git_libgit2_shutdown()); +} +