Skip to content
This repository has been archived by the owner on Nov 20, 2022. It is now read-only.

Commit

Permalink
Expanded on thread outline and basics
Browse files Browse the repository at this point in the history
  • Loading branch information
nikhilm committed Jun 21, 2012
1 parent f17fab7 commit 881f7e8
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 2 deletions.
3 changes: 2 additions & 1 deletion code/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ examples=\
idle-basic\
uvcat\
uvtee\
onchange
onchange\
thread-create

all: libuv
for dir in $(examples); do cd $$dir; echo "--- `pwd`"; gcc -g -Wall -I$(UV_PATH)/include $(UV_PATH)/uv.a -o $$dir main.c; cd ..; done
Expand Down
36 changes: 36 additions & 0 deletions code/thread-create/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <stdio.h>
#include <unistd.h>

#include <uv.h>

void hare(void *arg) {
int tracklen = *((int *) arg);
while (tracklen) {
tracklen--;
sleep(1);
fprintf(stderr, "Hare ran another step\n");
}
fprintf(stderr, "Hare done running!\n");
}

void tortoise(void *arg) {
int tracklen = *((int *) arg);
while (tracklen) {
tracklen--;
fprintf(stderr, "Tortoise ran another step\n");
sleep(3);
}
fprintf(stderr, "Tortoise done running!\n");
}

int main() {
int tracklen = 10;
uv_thread_t hare_id;
uv_thread_t tortoise_id;
uv_thread_create(&hare_id, hare, &tracklen);
uv_thread_create(&tortoise_id, tortoise, &tracklen);

uv_thread_join(&hare_id);
uv_thread_join(&tortoise_id);
return 0;
}
95 changes: 94 additions & 1 deletion source/threads.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,104 @@
Threads
=======

single event loop
Wait a minute? Why are we on threads? Aren't event loops supposed to be **the
way** to do *web-scale programming*? Well no. Threads are still the medium in
which the processor does its job, and threads are mighty useful sometimes, even
though you might have to wade through scary looking mutexes. TODO rework this
a bit

Threads are used internally to fake the asynchronous nature of all the system
calls. libuv also uses threads to allow you, the application, to perform a task
asynchronously that is actually blocking, by spawning a thread and collecting
the result when it is done.

Today there are two predominant thread libraries. The Windows threads
implementation and `pthreads`_. libuv's thread API is analogous to
the pthread API and often has similar semantics.

A notable aspect of libuv's thread facilities is that it is a self contained
section within libuv. Whereas other features intimately depend on the event
loop and callback principles, threads are complete agnostic, they block as
required, signal errors directly via return values and, as shown in the
:ref:`first example <thread-create-example>`, don't even require a running
event loop.

This chapter makes the following assumption: **There is only one event loop,
running in one thread (the main thread)**. No other thread interacts
with the event loop (except using `uv_async_send`). :doc:`multiple` covers
running event loops in different threads and managing them.

Core thread operations
----------------------

There isn't much here, you just start a thread using `uv_thread_create()` and
wait for it to close using `uv_thread_join()`.

.. _thread-create-example:

.. rubric:: thread-create/main.c
.. literalinclude:: ../code/thread-create/main.c
:linenos:
:lines: 26-37
:emphasize-lines: 3-7

.. tip::

`uv_thread_t` is just an alias for `pthread_t` on Unix, but this is an
implementation detail, avoid depending on it to always be true.

The second parameter is the function which will serve as the entry point for
the thread, the last parameter is a `void *` argument which can be used to pass
custom parameters to the thread. The function `hare` will now run in a separate
thread, scheduled pre-emptively by the operating system:

.. rubric:: thread-create/main.c
.. literalinclude:: ../code/thread-create/main.c
:linenos:
:lines: 6-14
:emphasize-lines: 2

Unlike ``pthread_join()`` which allows the target thread to pass back a value to
the calling thread using a second parameter, ``uv_thread_join()`` does not. To
send values use :ref:`inter-thread-communication`.

Synchronization Primitives
--------------------------

This section is purposely spartan. This book is not about threads, so I only
catalogue any surprises in the libuv APIs here. For the rest you can look at
the pthreads `man pages <pthreads>`_

Mutexes
~~~~~~~

Recursive mutexes not allowed

Locks
~~~~~

Others
~~~~~~

Semaphores not dne
The problem with condition variables

libuv work queue
----------------

uv_queue_work

.. _inter-thread-communication:

Inter-thread communication
--------------------------

inter thread communication using uv_async
synchronization
parallel downloads example?

note about recursive mutexes not supported
note about bad error of just aborting
uv_once

.. _pthreads: http://man7.org/linux/man-pages/man7/pthreads.7.html

0 comments on commit 881f7e8

Please sign in to comment.