mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-06 17:20:22 +00:00
threads: introduce git_thread_exit
Introduce `git_thread_exit`, which will allow threads to terminate at an arbitrary time, returning a `void *`. On Windows, this means that we need to store the current `git_thread` in TLS, so that we can set its `return` value when terminating. We cannot simply use `ExitThread`, since Win32 returns `DWORD`s from threads; we return `void *`.
This commit is contained in:
parent
a6763ff93a
commit
82f15896de
@ -16,6 +16,12 @@ typedef struct {
|
|||||||
git_error error_t;
|
git_error error_t;
|
||||||
git_buf error_buf;
|
git_buf error_buf;
|
||||||
char oid_fmt[GIT_OID_HEXSZ+1];
|
char oid_fmt[GIT_OID_HEXSZ+1];
|
||||||
|
|
||||||
|
/* On Windows, this is the current child thread that was started by
|
||||||
|
* `git_thread_create`. This is used to set the thread's exit code
|
||||||
|
* when terminated by `git_thread_exit`. It is unused on POSIX.
|
||||||
|
*/
|
||||||
|
git_thread *current_thread;
|
||||||
} git_global_st;
|
} git_global_st;
|
||||||
|
|
||||||
#ifdef GIT_OPENSSL
|
#ifdef GIT_OPENSSL
|
||||||
|
@ -17,6 +17,8 @@ typedef struct {
|
|||||||
pthread_create(&(git_thread_ptr)->thread, NULL, start_routine, arg)
|
pthread_create(&(git_thread_ptr)->thread, NULL, start_routine, arg)
|
||||||
#define git_thread_join(git_thread_ptr, status) \
|
#define git_thread_join(git_thread_ptr, status) \
|
||||||
pthread_join((git_thread_ptr)->thread, status)
|
pthread_join((git_thread_ptr)->thread, status)
|
||||||
|
#define git_thread_currentid() ((size_t)(pthread_self()))
|
||||||
|
#define git_thread_exit(retval) pthread_exit(retval)
|
||||||
|
|
||||||
/* Git Mutex */
|
/* Git Mutex */
|
||||||
#define git_mutex pthread_mutex_t
|
#define git_mutex pthread_mutex_t
|
||||||
|
@ -26,6 +26,9 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
|
|||||||
{
|
{
|
||||||
git_thread *thread = lpParameter;
|
git_thread *thread = lpParameter;
|
||||||
|
|
||||||
|
/* Set the current thread for `git_thread_exit` */
|
||||||
|
GIT_GLOBAL->current_thread = thread;
|
||||||
|
|
||||||
thread->result = thread->proc(thread->param);
|
thread->result = thread->proc(thread->param);
|
||||||
|
|
||||||
git__free_tls_data();
|
git__free_tls_data();
|
||||||
@ -95,6 +98,21 @@ int git_thread_join(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void git_thread_exit(void *value)
|
||||||
|
{
|
||||||
|
assert(GIT_GLOBAL->current_thread);
|
||||||
|
GIT_GLOBAL->current_thread->result = value;
|
||||||
|
|
||||||
|
git__free_tls_data();
|
||||||
|
|
||||||
|
ExitThread(CLEAN_THREAD_EXIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t git_thread_currentid(void)
|
||||||
|
{
|
||||||
|
return GetCurrentThreadId();
|
||||||
|
}
|
||||||
|
|
||||||
int git_mutex_init(git_mutex *GIT_RESTRICT mutex)
|
int git_mutex_init(git_mutex *GIT_RESTRICT mutex)
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(mutex);
|
InitializeCriticalSection(mutex);
|
||||||
|
@ -41,6 +41,8 @@ int git_thread_create(git_thread *GIT_RESTRICT,
|
|||||||
void *(*) (void *),
|
void *(*) (void *),
|
||||||
void *GIT_RESTRICT);
|
void *GIT_RESTRICT);
|
||||||
int git_thread_join(git_thread *, void **);
|
int git_thread_join(git_thread *, void **);
|
||||||
|
size_t git_thread_currentid(void);
|
||||||
|
void git_thread_exit(void *);
|
||||||
|
|
||||||
int git_mutex_init(git_mutex *GIT_RESTRICT mutex);
|
int git_mutex_init(git_mutex *GIT_RESTRICT mutex);
|
||||||
int git_mutex_free(git_mutex *);
|
int git_mutex_free(git_mutex *);
|
||||||
|
@ -48,3 +48,30 @@ void test_threads_basic__set_error(void)
|
|||||||
{
|
{
|
||||||
run_in_parallel(1, 4, set_error, NULL, NULL);
|
run_in_parallel(1, 4, set_error, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *return_normally(void *param)
|
||||||
|
{
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *exit_abruptly(void *param)
|
||||||
|
{
|
||||||
|
git_thread_exit(param);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_threads_basic__exit(void)
|
||||||
|
{
|
||||||
|
git_thread thread;
|
||||||
|
void *result;
|
||||||
|
|
||||||
|
/* Ensure that the return value of the threadproc is returned. */
|
||||||
|
cl_git_pass(git_thread_create(&thread, return_normally, (void *)424242));
|
||||||
|
cl_git_pass(git_thread_join(&thread, &result));
|
||||||
|
cl_assert_equal_sz(424242, (size_t)result);
|
||||||
|
|
||||||
|
/* Ensure that the return value of `git_thread_exit` is returned. */
|
||||||
|
cl_git_pass(git_thread_create(&thread, return_normally, (void *)232323));
|
||||||
|
cl_git_pass(git_thread_join(&thread, &result));
|
||||||
|
cl_assert_equal_sz(232323, (size_t)result);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user