1
0
Fork 0
arangodb/3rdParty/czmq-1.1.0/doc/zthread.txt

112 lines
3.6 KiB
Plaintext

zthread(7)
==========
NAME
----
zthread - working with system threads
SYNOPSIS
--------
----
// Detached threads follow POSIX pthreads API
typedef void *(zthread_detached_fn) (void *args);
// Attached threads get context and pipe from parent
typedef void (zthread_attached_fn) (void *args, zctx_t *ctx, void *pipe);
// Create a detached thread. A detached thread operates autonomously
// and is used to simulate a separate process. It gets no ctx, and no
// pipe.
void
zthread_new (zthread_detached_fn *thread_fn, void *args);
// Create an attached thread. An attached thread gets a ctx and a PAIR
// pipe back to its parent. It must monitor its pipe, and exit if the
// pipe becomes unreadable.
void *
zthread_fork (zctx_t *ctx, zthread_attached_fn *thread_fn, void *args);
// Self test of this class
int
zthread_test (Bool verbose);
----
DESCRIPTION
-----------
The zthread class wraps OS thread creation. It creates detached threads
that look like normal OS threads, or attached threads that share the
caller's 0MQ context, and get a pipe to talk back to the parent thread.
One problem is when our application needs child threads. If we simply
use pthreads_create() we're faced with several issues. First, it's not
portable to legacy OSes like win32. Second, how can a child thread get
access to our zctx object? If we just pass it around, we'll end up
sharing the pipe socket (which we use to talk to the agent) between
threads, and that will then crash 0MQ. Sockets cannot be used from more
than one thread at a time.
So each child thread needs its own pipe to the agent. For the agent,
this is fine, it can talk to a million threads. But how do we create
those pipes in the child thread? We can't, not without help from the
main thread. The solution is to wrap thread creation, like we wrap
socket creation. To create a new thread, the app calls zctx_thread_new()
and this method creates a dedicated zctx object, with a pipe, and then
it passes that object to the newly minted child thread.
The neat thing is we can hide non-portable aspects. Windows is really a
mess when it comes to threads. Three different APIs, none of which is
really right, so you have to do rubbish like manually cleaning up when
a thread finishes. Anyhow, it's hidden in this class so you don't need
to worry.
Second neat thing about wrapping thread creation is we can make it a
more enriching experience for all involved. One thing I do often is use
a PAIR-PAIR pipe to talk from a thread to/from its parent. So this class
will automatically create such a pair for each thread you start.
EXAMPLE
-------
.From zthread_test method
----
static void *
s_test_detached (void *args)
{
// Create a socket to check it'll be automatically deleted
zctx_t *ctx = zctx_new ();
void *push = zsocket_new (ctx, ZMQ_PUSH);
zctx_destroy (&ctx);
return NULL;
}
static void
s_test_attached (void *args, zctx_t *ctx, void *pipe)
{
// Create a socket to check it'll be automatically deleted
zsocket_new (ctx, ZMQ_PUSH);
// Wait for our parent to ping us, and pong back
free (zstr_recv (pipe));
zstr_send (pipe, "pong");
}
zctx_t *ctx = zctx_new ();
// Create a detached thread, let it run
zthread_new (s_test_detached, NULL);
zclock_sleep (100);
// Create an attached thread, check it's safely alive
void *pipe = zthread_fork (ctx, s_test_attached, NULL);
zstr_send (pipe, "ping");
char *pong = zstr_recv (pipe);
assert (streq (pong, "pong"));
free (pong);
// Everything should be cleanly closed now
zctx_destroy (&ctx);
----
SEE ALSO
--------
linkczmq:czmq[7]