Commit e79fbd9e by Carlos Martín Nieto

Merge pull request #2743 from ethomson/init_val

init: return the number of initializations
parents 8bfbe698 6d91dc53
...@@ -126,3 +126,7 @@ v0.21 + 1 ...@@ -126,3 +126,7 @@ v0.21 + 1
* git_threads_init() and git_threads_shutdown() have been renamed to * git_threads_init() and git_threads_shutdown() have been renamed to
git_libgit2_init() and git_libgit2_shutdown() to better explain what 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. 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.
...@@ -17,9 +17,11 @@ GIT_BEGIN_DECL ...@@ -17,9 +17,11 @@ GIT_BEGIN_DECL
* This function must the called before any other libgit2 function in * This function must the called before any other libgit2 function in
* order to set up global state and threading. * 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); GIT_EXTERN(int) git_libgit2_init(void);
...@@ -27,10 +29,14 @@ GIT_EXTERN(int) git_libgit2_init(void); ...@@ -27,10 +29,14 @@ GIT_EXTERN(int) git_libgit2_init(void);
* Shutdown the global state * Shutdown the global state
* *
* Clean up the global state and threading context after calling it as * 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 GIT_END_DECL
......
...@@ -195,19 +195,21 @@ static int synchronized_threads_init(void) ...@@ -195,19 +195,21 @@ static int synchronized_threads_init(void)
int git_libgit2_init(void) int git_libgit2_init(void)
{ {
int error = 0; int ret;
/* Enter the lock */ /* Enter the lock */
while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); } while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); }
/* Only do work on a 0 -> 1 transition of the refcount */ /* Only do work on a 0 -> 1 transition of the refcount */
if (1 == git_atomic_inc(&git__n_inits)) if ((ret = git_atomic_inc(&git__n_inits)) == 1) {
error = synchronized_threads_init(); if (synchronized_threads_init() < 0)
ret = -1;
}
/* Exit the lock */ /* Exit the lock */
InterlockedExchange(&_mutex, 0); InterlockedExchange(&_mutex, 0);
return error; return ret;
} }
static void synchronized_threads_shutdown(void) static void synchronized_threads_shutdown(void)
...@@ -218,17 +220,21 @@ static void synchronized_threads_shutdown(void) ...@@ -218,17 +220,21 @@ static void synchronized_threads_shutdown(void)
git_mutex_free(&git__mwindow_mutex); git_mutex_free(&git__mwindow_mutex);
} }
void git_libgit2_shutdown(void) int git_libgit2_shutdown(void)
{ {
int ret;
/* Enter the lock */ /* Enter the lock */
while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); } while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); }
/* Only do work on a 1 -> 0 transition of the refcount */ /* 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(); synchronized_threads_shutdown();
/* Exit the lock */ /* Exit the lock */
InterlockedExchange(&_mutex, 0); InterlockedExchange(&_mutex, 0);
return ret;
} }
git_global_st *git__global_state(void) git_global_st *git__global_state(void)
...@@ -282,17 +288,22 @@ static void init_once(void) ...@@ -282,17 +288,22 @@ static void init_once(void)
int git_libgit2_init(void) int git_libgit2_init(void)
{ {
int ret;
pthread_once(&_once_init, init_once); pthread_once(&_once_init, init_once);
git_atomic_inc(&git__n_inits); ret = git_atomic_inc(&git__n_inits);
return init_error;
return init_error ? init_error : ret;
} }
void git_libgit2_shutdown(void) int git_libgit2_shutdown(void)
{ {
void *ptr = NULL; void *ptr = NULL;
pthread_once_t new_once = PTHREAD_ONCE_INIT; 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 */ /* Shut down any subsystems that have global state */
git__shutdown(); git__shutdown();
...@@ -304,6 +315,8 @@ void git_libgit2_shutdown(void) ...@@ -304,6 +315,8 @@ void git_libgit2_shutdown(void)
pthread_key_delete(_tls_key); pthread_key_delete(_tls_key);
git_mutex_free(&git__mwindow_mutex); git_mutex_free(&git__mwindow_mutex);
_once_init = new_once; _once_init = new_once;
return ret;
} }
git_global_st *git__global_state(void) git_global_st *git__global_state(void)
...@@ -337,15 +350,18 @@ int git_libgit2_init(void) ...@@ -337,15 +350,18 @@ int git_libgit2_init(void)
ssl_inited = 1; ssl_inited = 1;
} }
git_atomic_inc(&git__n_inits); return git_atomic_inc(&git__n_inits);
return 0;
} }
void git_libgit2_shutdown(void) int git_libgit2_shutdown(void)
{ {
int ret;
/* Shut down any subsystems that have global state */ /* 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(); git__shutdown();
return ret;
} }
git_global_st *git__global_state(void) git_global_st *git__global_state(void)
......
#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());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment