init: return the number of initializations
1 2 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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4b9d924..7bc40c5 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 4f90c4c..ce5bdf4 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 006202a..b3e75a0 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 0000000..e17b784
--- /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());
+}
+