Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
PACTION(3)	       FreeBSD Library Functions Manual		    PACTION(3)

     paction --	actions	in a separate thread

     PDEL Library (libpdel, -lpdel)

     #include <sys/types.h>
     #include <pthread.h>
     #include <pdel/util/paction.h>

     paction_start(struct paction **actionp, pthread_mutex_t *mutex,
	 paction_handler_t *handler, paction_finish_t *finish, void *arg);

     paction_cancel(struct paction **actionp);

     These functions provide support for actions, which	are simply function
     invocations that happen in	separate threads.  This	is just	a simplified
     API for spawning and cancelling threads with built-in support for mutex
     locking and avoiding certain race conditions.

     paction_start() creates a new action and stores a pointer to the action,
     represented by a struct paction, in *actionp.  The	creation of an action
     results in	handler() being	invoked	in a new thread.  paction_cancel()
     cancels an	action by canceling its	associated thread.  In any case, when
     the action	has completed, finish()	is invoked.  If	the action was not
     canceled via paction_cancel(), then *mutex	is acquired before finish() is
     invoked and released afterward.  If paction_cancel() was called, then the
     mutex is not acquired for finish().  The was_canceled argument to
     finish() reflects this.

     handler and finish	must be	pointers to functions having these types:

	typedef	void paction_handler_t(void *arg);
	typedef	void paction_finish_t(void *arg, int was_canceled);

     When paction_start() is invoked, *actionp must be NULL.  As long as the
     action is still in	progress (i.e.,	finish() has not yet been invoked),
     *actionp will be non-NULL.	 When the action completes or is canceled,
     *actionp is set to	NULL again.  Therefore,	*actionp must remain valid and
     unmodified	for the	duration of the	action,	and can	be used	as an indica-
     tor of whether the	action has completed.

     paction_cancel() cancels an outstanding action.  This results in the ac-
     tion thread being canceled	at the next cancellation point.	 Therefore,
     handler() may need	to register thread cleanup hooks in order to free any
     allocated resources in the	case of	cancellation.  Upon return, *actionp
     is	set to NULL.  If *actionp is already NULL when paction_cancel()	is in-
     voked, nothing happens.

     In	any case, finish() is invoked when the action terminates.  There are
     two reasons for an	action terminating: either the action terminated nor-
     mally, or paction_cancel()	was invoked.  If the action terminated nor-
     mally, *mutex is locked, *actionp is set to NULL, and finish() is invoked
     with was_canceled set to zero.  When finish() returns *mutex is unlocked.

     If	the action was canceled	by paction_cancel(), then neither mutex	nor
     actionp are dereferenced; final() is simply called	with was_canceled set
     to	non-zero.  Note	that *actionp will have	already	been set to NULL pre-
     viously by	paction_cancel().

     Cancelling	the action thread directly via pthread_cancel(3) is treated
     just as if	handler() returned early; i.e.,	the first case above.

     There are inherent	race conditions	between	an action's finish() function
     being invoked and reading the value of *actionp or	canceling the action
     with paction_cancel().  The *mutex	should be used to avoid	these problems
     by	using it to protect *actionp.

     The user code should acquire *mutex before	calling	paction_start()	or
     paction_cancel(), or before accessing *actionp.  If this protocol is fol-
     lowed, then *actionp will be non-NULL if and only if the action is	still
     pending, i.e., finish() has not yet been invoked.	In addition, the
     was_canceled argument will	always be accurate, i.e., be non-zero if and
     only if paction_cancel() was called to cancel the action.

     Finally, mutex and	actionp	will not be dereferenced after a call to
     paction_cancel(), so it is	always safe to destroy the memory pointed to
     by	mutex and actionp after	calling	paction_cancel().  However, arg	must
     remain valid until	finish() is invoked, which may occur after
     paction_cancel() returns; alternatively, finish() must not	dereference
     arg if was_canceled is non-zero.

     paction_start() returns -1	if there is an error, with errno set appropri-
     ately.  In	particular, if *actionp	is not equal to	NULL, then errno will
     be	set to EBUSY.

     libpdel(3), pevent(3), pthread_cancel(3), pthread_create(3)

     The PDEL library was developed at Packet Design, LLC.

     Archie Cobbs <>

FreeBSD	13.0			April 22, 2002			  FreeBSD 13.0


Want to link to this manual page? Use this URL:

home | help