GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages
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>

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

void
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 indicator of whether the action has completed.

paction_cancel() cancels an outstanding action. This results in the action 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 invoked, nothing happens.

In any case, finish() is invoked when the action terminates. There are two reasons for an action terminating: either the action terminated normally, or paction_cancel() was invoked. If the action terminated normally, *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 previously 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 followed, 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 appropriately. 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. http://www.packetdesign.com/

Archie Cobbs ⟨archie@freebsd.org⟩
April 22, 2002 FreeBSD 13.1-RELEASE

Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with ManDoc.