changeset 327:187abb9af7e2

Much more elaborate thread-hello.c using mutex and event semaphores, and join. (Much work to accomplish little, but it exercises the thread infrastructure.)
author Rob Landley <rob@landley.net>
date Fri, 09 May 2008 18:04:54 -0500
parents 391ea980fffd
children 6a0788146ccb
files sources/native/src/thread-hello2.c
diffstat 1 files changed, 90 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/native/src/thread-hello2.c	Fri May 09 18:04:54 2008 -0500
@@ -0,0 +1,90 @@
+// Threaded hello world program that uses mutex and event semaphores to pass
+// the string to print from one thread to another, and waits for the child
+// thread to return a result before exiting the program.
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Thread, semaphores, and mailbox
+struct thread_info {
+	pthread_t thread;
+	pthread_mutex_t wakeup_mutex;
+	pthread_cond_t wakeup_send, wakeup_receive;
+	unsigned len;
+	char *data;
+};
+
+// Create a new thread with associated resources.
+struct thread_info *newthread(void *(*func)(void *))
+{
+	struct thread_info *ti = malloc(sizeof(struct thread_info));
+	memset(ti, 0, sizeof(struct thread_info));
+
+	pthread_create(&(ti->thread), NULL, func, ti);
+
+	return ti;
+}
+
+// Send a block of data through mailbox.
+void thread_send(struct thread_info *ti, char *data, unsigned len)
+{
+	pthread_mutex_lock(&(ti->wakeup_mutex));
+	// If consumer hasn't consumed yet, wait for them to do so.
+	if (ti->len)
+		pthread_cond_wait(&(ti->wakeup_send), &(ti->wakeup_mutex));
+	ti->data = data;
+	ti->len = len;
+	pthread_cond_signal(&(ti->wakeup_receive));
+	pthread_mutex_unlock(&(ti->wakeup_mutex));
+}
+
+// Receive a block of data through mailbox.
+void thread_receive(struct thread_info *ti, char **data, unsigned *len)
+{
+	pthread_mutex_lock(&(ti->wakeup_mutex));
+	if (!ti->len)
+		pthread_cond_wait(&(ti->wakeup_receive), &(ti->wakeup_mutex));
+	*data = ti->data;
+	*len = ti->len;
+	// If sender is waiting to send us a second message, wake 'em up.
+	// Note that "if (ti->len)" be used as an unlocked/nonblocking test for
+	// pending data, although you still need call this function to read data.
+	ti->len = 0;
+	pthread_cond_signal(&(ti->wakeup_send));
+	pthread_mutex_unlock(&(ti->wakeup_mutex));
+}
+
+// Function for new thread to execute.
+void *hello_thread(void *thread_data)
+{
+	struct thread_info *ti = (struct thread_info *)thread_data;
+
+	for (;;) {
+		unsigned len;
+		char *data;
+
+		thread_receive(ti, &data, &len);
+		if (!data) break;
+		printf("%.*s", len, data);
+		free(data);
+	}
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	void *result;
+	char *data = strdup("Hello world!\n");
+	struct thread_info *ti = newthread(hello_thread);
+
+	// Send one line of text.
+	thread_send(ti, data, strlen(data));
+	// Signal thread to exit and wait for it to do so.
+	thread_send(ti, NULL, 1);
+	pthread_join(ti->thread, &result);
+
+	return (long)result;
+}