<commit_before>#include "util/thread.h"
#include "util/memory.h"

#include <errno.h>

bedrock_list thread_list = LIST_INIT;
bedrock_pipe thread_notify_pipe;

static bedrock_list thread_exited_list = LIST_INIT;

static void do_exit_threads(void bedrock_attribute_unused *unused)
{
	bedrock_node *node, *node2;

	LIST_FOREACH_SAFE(&thread_exited_list, node, node2)
	{
		struct bedrock_thread *thread = node->data;
		bedrock_thread_join(thread);
	}

	bedrock_assert(thread_exited_list.count == 0, ;);
}

void bedrock_threadengine_start()
{
	bedrock_pipe_open(&thread_notify_pipe, "thread exit pipe", do_exit_threads, NULL);
}

void bedrock_threadengine_stop()
{
	bedrock_pipe_close(&thread_notify_pipe);
}

static void *thread_entry(void *data)
{
	struct bedrock_thread *thread = data;
	thread->entry(thread, thread->data);
	bedrock_thread_set_exit(thread);
	pthread_exit(NULL);
	return NULL;
}

struct bedrock_thread *bedrock_thread_start(bedrock_thread_entry entry, bedrock_thread_exit at_exit, void *data)
{
	struct bedrock_thread *thread = bedrock_malloc(sizeof(struct bedrock_thread));
	int err;

	thread->entry = entry;
	thread->at_exit = at_exit;
	thread->data = data;

	bedrock_list_add(&thread_list, thread);

	err = pthread_create(&thread->handle, NULL, thread_entry, thread);
	if (err)
	{
		bedrock_log(LEVEL_CRIT, "thread: Unable to create thread - %s", strerror(errno));
		bedrock_list_del(&thread_list, thread);
		bedrock_free(thread);
	}
	else
		bedrock_log(LEVEL_THREAD, "thread: Created thread %d", thread->handle);

	return thread;
}

bool bedrock_thread_want_exit(struct bedrock_thread *thread)
{
	return bedrock_list_has_data(&thread_exited_list, thread);
}

void bedrock_thread_set_exit(struct bedrock_thread *thread)
{
	if (bedrock_thread_want_exit(thread) == false)
	{
		bedrock_list_add(&thread_exited_list, thread);
		bedrock_pipe_notify(&thread_notify_pipe);
	}
}

void bedrock_thread_join(struct bedrock_thread *thread)
{
	bedrock_thread_set_exit(thread);<commit_msg>Don't return bad pointer when thread creation fails<commit_after>#include "util/thread.h"
#include "util/memory.h"

#include <errno.h>

bedrock_list thread_list = LIST_INIT;
bedrock_pipe thread_notify_pipe;

static bedrock_list thread_exited_list = LIST_INIT;

static void do_exit_threads(void bedrock_attribute_unused *unused)
{
	bedrock_node *node, *node2;

	LIST_FOREACH_SAFE(&thread_exited_list, node, node2)
	{
		struct bedrock_thread *thread = node->data;
		bedrock_thread_join(thread);
	}

	bedrock_assert(thread_exited_list.count == 0, ;);
}

void bedrock_threadengine_start()
{
	bedrock_pipe_open(&thread_notify_pipe, "thread exit pipe", do_exit_threads, NULL);
}

void bedrock_threadengine_stop()
{
	bedrock_pipe_close(&thread_notify_pipe);
}

static void *thread_entry(void *data)
{
	struct bedrock_thread *thread = data;
	thread->entry(thread, thread->data);
	bedrock_thread_set_exit(thread);
	pthread_exit(NULL);
	return NULL;
}

struct bedrock_thread *bedrock_thread_start(bedrock_thread_entry entry, bedrock_thread_exit at_exit, void *data)
{
	struct bedrock_thread *thread = bedrock_malloc(sizeof(struct bedrock_thread));
	int err;

	thread->entry = entry;
	thread->at_exit = at_exit;
	thread->data = data;

	bedrock_list_add(&thread_list, thread);

	err = pthread_create(&thread->handle, NULL, thread_entry, thread);
	if (err)
	{
		bedrock_log(LEVEL_CRIT, "thread: Unable to create thread - %s", strerror(errno));
		bedrock_list_del(&thread_list, thread);
		bedrock_free(thread);
		thread = NULL;
	}
	else
		bedrock_log(LEVEL_THREAD, "thread: Created thread %d", thread->handle);

	return thread;
}

bool bedrock_thread_want_exit(struct bedrock_thread *thread)
{
	return bedrock_list_has_data(&thread_exited_list, thread);
}

void bedrock_thread_set_exit(struct bedrock_thread *thread)
{
	if (bedrock_thread_want_exit(thread) == false)
	{
		bedrock_list_add(&thread_exited_list, thread);
		bedrock_pipe_notify(&thread_notify_pipe);
	}
}

void bedrock_thread_join(struct bedrock_thread *thread)
{
	bedrock_thread_set_exit(thread);
{'fraction_non_alphanumeric': 0.10824869952935348, 'fraction_numerical': 0.0014862521674510775, 'mean_word_length': 7.190669371196755, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7175215', 'n_tokens_mistral': 1487, 'n_tokens_neox': 1456, 'n_words': 268}