nunc-stans.h File Reference

Nunc Stans public API. More...

#include "nspr.h"

Go to the source code of this file.

Data Structures

struct  ns_thrpool_config
 

Macros

#define NS_JOB_NONE   0x0
 
#define NS_JOB_ACCEPT   0x1
 
#define NS_JOB_CONNECT   0x2
 
#define NS_JOB_READ   0x4
 
#define NS_JOB_WRITE   0x8
 
#define NS_JOB_TIMER   0x10
 
#define NS_JOB_SIGNAL   0x20
 
#define NS_JOB_PERSIST   0x40
 
#define NS_JOB_THREAD   0x80
 
#define NS_JOB_PRESERVE_FD   0x100
 
#define NS_JOB_IS_ACCEPT(eee)   ((eee)&NS_JOB_ACCEPT)
 
#define NS_JOB_IS_READ(eee)   ((eee)&NS_JOB_READ)
 
#define NS_JOB_IS_CONNECT(eee)   ((eee)&NS_JOB_CONNECT)
 
#define NS_JOB_IS_WRITE(eee)   ((eee)&NS_JOB_WRITE)
 
#define NS_JOB_IS_TIMER(eee)   ((eee)&NS_JOB_TIMER)
 
#define NS_JOB_IS_SIGNAL(eee)   ((eee)&NS_JOB_SIGNAL)
 
#define NS_JOB_IS_PERSIST(eee)   ((eee)&NS_JOB_PERSIST)
 
#define NS_JOB_IS_IO(eee)   (NS_JOB_IS_ACCEPT(eee)||NS_JOB_IS_READ(eee)||NS_JOB_IS_CONNECT(eee)||NS_JOB_IS_WRITE(eee))
 
#define NS_JOB_IS_THREAD(eee)   ((eee)&NS_JOB_THREAD)
 
#define NS_JOB_IS_PRESERVE_FD(eee)   ((eee)&NS_JOB_PRESERVE_FD)
 
#define NS_JOB_SET_READ(eee)   ((eee) |= NS_JOB_READ)
 
#define NS_JOB_SET_WRITE(eee)   ((eee) |= NS_JOB_WRITE)
 
#define NS_JOB_SET_THREAD(eee)   ((eee) |= NS_JOB_THREAD)
 
#define NS_JOB_UNSET_READ(eee)   ((eee) &= ~NS_JOB_READ)
 
#define NS_JOB_UNSET_WRITE(eee)   ((eee) &= ~NS_JOB_WRITE)
 
#define NS_JOB_UNSET_THREAD(eee)   ((eee) &= ~NS_JOB_THREAD)
 

Typedefs

typedef struct ns_thrpool_t ns_thrpool_t
 
typedef void(* ns_job_func_t) (struct ns_job_t *)
 
typedef unsigned short ns_job_type_t
 

Functions

void ns_thrpool_config_init (struct ns_thrpool_config *tp_config)
 
PRStatus ns_job_done (struct ns_job_t *job)
 
PRStatus ns_create_job (struct ns_thrpool_t *tp, ns_job_type_t job_type, ns_job_func_t func, struct ns_job_t **job)
 
PRStatus ns_add_io_job (struct ns_thrpool_t *tp, PRFileDesc *fd, ns_job_type_t job_type, ns_job_func_t func, void *data, struct ns_job_t **job)
 
PRStatus ns_add_timeout_job (struct ns_thrpool_t *tp, struct timeval *tv, ns_job_type_t job_type, ns_job_func_t func, void *data, struct ns_job_t **job)
 
PRStatus ns_add_io_timeout_job (struct ns_thrpool_t *tp, PRFileDesc *fd, struct timeval *tv, ns_job_type_t job_type, ns_job_func_t func, void *data, struct ns_job_t **job)
 
PRStatus ns_add_signal_job (ns_thrpool_t *tp, PRInt32 signum, ns_job_type_t job_type, ns_job_func_t func, void *data, struct ns_job_t **job)
 
PRStatus ns_add_job (ns_thrpool_t *tp, ns_job_type_t job_type, ns_job_func_t func, void *data, struct ns_job_t **job)
 
PRFileDesc * ns_job_get_fd (struct ns_job_t *job)
 
void * ns_job_get_data (struct ns_job_t *job)
 
PRStatus ns_job_set_data (struct ns_job_t *job, void *data)
 
ns_job_type_t ns_job_get_type (struct ns_job_t *job)
 
ns_thrpool_tns_job_get_tp (struct ns_job_t *job)
 
ns_job_type_t ns_job_get_output_type (struct ns_job_t *job)
 
PRStatus ns_job_set_done_cb (struct ns_job_t *job, ns_job_func_t func)
 
struct ns_thrpool_tns_thrpool_new (struct ns_thrpool_config *config)
 
void ns_thrpool_destroy (struct ns_thrpool_t *tp)
 
void ns_thrpool_shutdown (struct ns_thrpool_t *tp)
 
PRInt32 ns_thrpool_is_shutdown (struct ns_thrpool_t *tp)
 
PRStatus ns_thrpool_wait (struct ns_thrpool_t *tp)
 
PRStatus ns_job_rearm (struct ns_job_t *job)
 

Detailed Description

Nunc Stans public API.

This is the public API for Nunc Stans

Macro Definition Documentation

§ NS_JOB_ACCEPT

#define NS_JOB_ACCEPT   0x1

Flag for accept() jobs - new connection listeners

Use this flag when creating jobs that listen for and accept new connections. This is typically used in conjunction with the NS_JOB_PERSIST flag so that the job does not have to be rearmed every time it is called.

struct ns_job_t *listenerjob;
PRFileDesc *listenfd = PR_OpenTCPSocket(...);
PR_Bind(listenfd, ...);
PR_Listen(listenfd, ...);
listenerctx = new_listenerctx(...); // the application context object
accept_new_connection, listenerctx, &listenerjob);

You will probably want to keep track of listenerjob and use it with ns_job_done() at application shutdown time to avoid leaking resources.

See also
ns_add_io_job, ns_add_io_timeout_job, NS_JOB_IS_ACCEPT, ns_job_get_type, ns_job_get_output_type

§ NS_JOB_CONNECT

#define NS_JOB_CONNECT   0x2

Flag for jobs that will use connect()

When creating an I/O job, set this flag in the job_type to be notified when the file descriptor is available for outgoing connections. In the job callback, use ns_job_get_output_type() and NS_JOB_IS_CONNECT to see if the callback was called due to connect available if the callback is used with more than one of the job flags.

See also
ns_add_io_job, ns_add_io_timeout_job, ns_job_get_type, ns_job_get_output_type, NS_JOB_IS_CONNECT

§ NS_JOB_IS_ACCEPT

#define NS_JOB_IS_ACCEPT (   eee)    ((eee)&NS_JOB_ACCEPT)

§ NS_JOB_IS_CONNECT

#define NS_JOB_IS_CONNECT (   eee)    ((eee)&NS_JOB_CONNECT)

§ NS_JOB_IS_IO

#define NS_JOB_IS_IO (   eee)    (NS_JOB_IS_ACCEPT(eee)||NS_JOB_IS_READ(eee)||NS_JOB_IS_CONNECT(eee)||NS_JOB_IS_WRITE(eee))

Used to test an ns_job_type_t value to see if it is any sort of I/O job

See also
NS_JOB_IS_ACCEPT, NS_JOB_IS_READ, NS_JOB_IS_CONNECT, NS_JOB_IS_WRITE, ns_job_get_type, ns_job_get_output_type

§ NS_JOB_IS_PERSIST

#define NS_JOB_IS_PERSIST (   eee)    ((eee)&NS_JOB_PERSIST)

§ NS_JOB_IS_PRESERVE_FD

#define NS_JOB_IS_PRESERVE_FD (   eee)    ((eee)&NS_JOB_PRESERVE_FD)

§ NS_JOB_IS_READ

#define NS_JOB_IS_READ (   eee)    ((eee)&NS_JOB_READ)

§ NS_JOB_IS_SIGNAL

#define NS_JOB_IS_SIGNAL (   eee)    ((eee)&NS_JOB_SIGNAL)

§ NS_JOB_IS_THREAD

#define NS_JOB_IS_THREAD (   eee)    ((eee)&NS_JOB_THREAD)

§ NS_JOB_IS_TIMER

#define NS_JOB_IS_TIMER (   eee)    ((eee)&NS_JOB_TIMER)

§ NS_JOB_IS_WRITE

#define NS_JOB_IS_WRITE (   eee)    ((eee)&NS_JOB_WRITE)

§ NS_JOB_NONE

#define NS_JOB_NONE   0x0

Flag for jobs that are not associated with an event.

Use this flag when creating a job that you want to be run but not associated with an event. Usually used in conjunction with ns_add_job() and NS_JOB_THREAD to execute a function using the thread pool.

See also
ns_add_job, NS_JOB_THREAD

§ NS_JOB_PERSIST

#define NS_JOB_PERSIST   0x40

Flag to make jobs persistent

By default, when an event (I/O, timer, signal) is triggered and the job callback is called, the event is removed from the event framework, and the application will no longer receive callbacks for events. The application is then responsible for calling ns_job_rearm to "re-arm" the job to respond to the event again. Adding the job with the NS_JOB_PERSIST flag added to the job_type means the job will not have to be rearmed. This is usually used in conjunction with NS_JOB_ACCEPT for accept jobs. Use ns_job_get_type() or ns_job_get_output_type() with NS_JOB_IS_PERSIST to test if the job is persistent.

Note
Be very careful when using this flag in conjunction with NS_JOB_THREAD. For example, for a NS_JOB_ACCEPT job, once you call accept(), the socket may be immediately available for another accept, and your callback could be called again immediately in another thread. Same for the other types of I/O jobs. In that case, your job callback function must be thread safe - global resources must be protected with a mutex, the function must be reentrant, etc.
See also
NS_JOB_ACCEPT, NS_JOB_THREAD, NS_JOB_IS_PERSIST, ns_job_get_type, ns_job_get_output_type

§ NS_JOB_PRESERVE_FD

#define NS_JOB_PRESERVE_FD   0x100

Flag to tell ns_job_done() not to close the job fd

I/O jobs will have a file descriptor (fd). If the job->fd lifecycle is managed by the application, this flag tells ns_job_done() not to close the fd.

See also
ns_add_io_job, ns_add_io_timeout_job, ns_job_get_type, ns_job_get_output_type, NS_JOB_IS_PRESERVE_FD

§ NS_JOB_READ

#define NS_JOB_READ   0x4

Flag for I/O read jobs

When creating an I/O job, set this flag in the job_type to be notified when the file descriptor is available for reading. In the job callback, use ns_job_get_output_type() and NS_JOB_IS_READ to see if the callback was called due to read available if the callback is used with more than one of the job flags.

See also
ns_add_io_job, ns_add_io_timeout_job, ns_job_get_type, ns_job_get_output_type, NS_JOB_IS_READ

§ NS_JOB_SET_READ

#define NS_JOB_SET_READ (   eee)    ((eee) |= NS_JOB_READ)

Used to set an ns_job_type_t value to have NS_JOB_READ

§ NS_JOB_SET_THREAD

#define NS_JOB_SET_THREAD (   eee)    ((eee) |= NS_JOB_THREAD)

Used to set an ns_job_type_t value to have NS_JOB_THREAD

§ NS_JOB_SET_WRITE

#define NS_JOB_SET_WRITE (   eee)    ((eee) |= NS_JOB_WRITE)

Used to set an ns_job_type_t value to have NS_JOB_WRITE

§ NS_JOB_SIGNAL

#define NS_JOB_SIGNAL   0x20

Flag for signal jobs

When creating a signal job, set this flag in the job_type to be notified when the process receives the given signal. In the job callback, use ns_job_get_output_type() and NS_JOB_IS_SIGNAL to see if the callback was called due to receiving the signal if the callback is used with more than one of the job flags.

See also
ns_add_signal_job, ns_job_get_type, ns_job_get_output_type, NS_JOB_IS_SIGNAL

§ NS_JOB_THREAD

#define NS_JOB_THREAD   0x80

Flag to make jobs run in a thread pool thread

This flag allows you to specify if you want a job to run threaded or not. If the job is threaded, the job callback is executed by a thread in the thread pool, and the job callback function must be thread safe and reentrant. If the job is not threaded, the job runs in the same thread as the event loop thread.

Note
When NS_JOB_THREAD is not used, the job callback will be run in the event loop thread, and will block all events from being processed. Care must be taken to ensure that the job callback does not block.

Use ns_job_get_type() or ns_job_get_output_type() with NS_JOB_IS_THREAD to test if the job is threaded.

See also
NS_JOB_IS_THREAD, ns_job_get_type, ns_job_get_output_type

§ NS_JOB_TIMER

#define NS_JOB_TIMER   0x10

Flag for timer jobs

When creating a timeout or I/O timeout job, set this flag in the job_type to be notified when the time given by the timeval argument has elapsed. In the job callback, use ns_job_get_output_type() and NS_JOB_IS_TIMER to see if the callback was called due to elapsed time if the callback is used with more than one of the job flags.

See also
ns_add_timeout_job, ns_add_io_timeout_job, ns_job_get_type, ns_job_get_output_type, NS_JOB_IS_TIMER

§ NS_JOB_UNSET_READ

#define NS_JOB_UNSET_READ (   eee)    ((eee) &= ~NS_JOB_READ)

Remove NS_JOB_READ from an ns_job_type_t value

§ NS_JOB_UNSET_THREAD

#define NS_JOB_UNSET_THREAD (   eee)    ((eee) &= ~NS_JOB_THREAD)

Remove NS_JOB_THREAD from an ns_job_type_t value

§ NS_JOB_UNSET_WRITE

#define NS_JOB_UNSET_WRITE (   eee)    ((eee) &= ~NS_JOB_WRITE)

Remove NS_JOB_WRITE from an ns_job_type_t value

§ NS_JOB_WRITE

#define NS_JOB_WRITE   0x8

Flag for I/O write jobs

When creating an I/O job, set this flag in the job_type to be notified when the file descriptor is available for writing. In the job callback, use ns_job_get_output_type() and NS_JOB_IS_WRITE to see if the callback was called due to write available if the callback is used with more than one of the job flags.

See also
ns_add_io_job, ns_add_io_timeout_job, ns_job_get_type, ns_job_get_output_type, NS_JOB_IS_WRITE

Typedef Documentation

§ ns_job_func_t

typedef void(* ns_job_func_t) (struct ns_job_t *)

The job callback function type

Job callback functions must have a function signature of ns_job_func_t.

See also
ns_add_io_job, ns_add_io_timeout_job, ns_add_timeout_job, ns_add_signal_job, ns_add_job

§ ns_job_type_t

typedef unsigned short ns_job_type_t

Bitflag type for job types

This is the job_type bitfield argument used when adding jobs, and the return value of the functions ns_job_get_type() and ns_job_get_output_type(). The value is one or more of the NS_JOB_* macros OR'd together.

When used with ns_job_get_type() or ns_job_get_output_type() to see what type of job it is, use the return value with one of the NS_JOB_IS_* macros:

// handle timeout
}
See also
ns_add_io_job, ns_add_io_timeout_job, ns_add_job, ns_add_signal_job, ns_add_timeout_job, ns_job_get_type, ns_job_get_output_type

§ ns_thrpool_t

typedef struct ns_thrpool_t ns_thrpool_t

This is the thread pool typedef

The actual thread pool is opaque to applications.

See also
ns_thrpool_new, ns_thrpool_wait, ns_thrpool_destroy, ns_job_get_tp

Function Documentation

§ ns_add_io_job()

PRStatus ns_add_io_job ( struct ns_thrpool_t tp,
PRFileDesc *  fd,
ns_job_type_t  job_type,
ns_job_func_t  func,
void *  data,
struct ns_job_t **  job 
)

Adds an I/O job to the thread pool

Specify the type of I/O job using the job_type bitfield. You can specify more than one type of I/O job. Use ns_job_get_output_type(job) to determine which event triggered the I/O.

ns_add_io_job(tp, fd, NS_JOB_READ|NS_JOB_WRITE, my_io_callback, ...);
...
void my_io_callback(struct ns_job_t *job)
{
// handle reading from fd
} else {
// handle writing to fd
}
}

The callback will need to rearm the job or add another job if it wants to be notified of more events, or use NS_JOB_PERSIST. If you want an I/O job that will timeout if I/O is not detected within a certain period of time, use ns_add_io_timeout_job().

Parameters
tpThe thread pool you want to add an I/O job to.
fdThe file descriptor to use for I/O.
job_typeA set of flags that indicates the job type.
funcThe callback function to call when processing the job.
dataArbitrary data that will be available to the job callback function.
[out]jobThe address of a job pointer that will be filled in once the job is allocated. NULL can be passed if a pointer to the job is not needed.
Return values
PR_SUCCESSJob was successfully added.
PR_FAILUREFailed to add job.
Warning
The thread pool will not allow a job to be added when it has been signaled to shutdown. It will return PR_FAILURE in that case.
See also
ns_job_t, ns_job_get_data, NS_JOB_READ, NS_JOB_WRITE, NS_JOB_ACCEPT, NS_JOB_CONNECT, NS_JOB_IS_IO, ns_job_done

§ ns_add_io_timeout_job()

PRStatus ns_add_io_timeout_job ( struct ns_thrpool_t tp,
PRFileDesc *  fd,
struct timeval *  tv,
ns_job_type_t  job_type,
ns_job_func_t  func,
void *  data,
struct ns_job_t **  job 
)

Adds an I/O job to the thread pool's work queue with a timeout.

The callback func function should test the type of event that triggered the callback using ns_job_get_output_type(job) to get the ns_job_type_t, then use NS_JOB_IS_TIMER(output_type) to see if this callback was triggered by a timer event. This is useful if you want to perform some sort of I/O, but you require that I/O must happen in a certain amount of time.

ns_add_io_timeout_job(tp, fd, &tv, NS_JOB_READ|NS_JOB_TIMER, my_iot_callback, ...);
...
void my_iot_callback(struct ns_job_t *job)
{
// handle timeout condition
} else {
// handle read from fd
}
}
Note
This is like adding an I/O job, with an optional timeout. This is not like adding a timeout job with an additional I/O event component. This depends on the underlying event framework having the ability to have a timed I/O job. For example, libevent I/O events can have a timeout.
Parameters
tpThe thread pool whose work queue you want to add an I/O job to.
fdThe file descriptor to use for I/O.
tvThe timer that needs to expire before triggering the callback function.
job_typeA set of flags that indicates the job type.
funcThe callback function for a worker thread to call when processing the job.
dataArbitrary data that will be available to the job callback function.
[out]jobThe address of a job pointer that will be filled in once the job is allocated. NULL can be passed if a pointer to the job is not needed.
Return values
PR_SUCCESSJob was successfully added.
PR_FAILUREFailed to add job.
Warning
The thread pool will not allow a job to be added when it has been signaled to shutdown. It will return PR_FAILURE in that case.
See also
ns_job_t, ns_job_get_data, NS_JOB_READ, NS_JOB_WRITE, NS_JOB_ACCEPT, NS_JOB_CONNECT, NS_JOB_IS_IO, ns_job_done, NS_JOB_TIMER, NS_JOB_IS_TIMER

§ ns_add_job()

PRStatus ns_add_job ( ns_thrpool_t tp,
ns_job_type_t  job_type,
ns_job_func_t  func,
void *  data,
struct ns_job_t **  job 
)

Add a non-event related job to the thread pool

A non-event related job is a job that is executed immediately that is not contingent on an event or signal. This is typically used when the application wants to do some processing in parallel using a thread from the thread pool.

ns_add_job(tp, NS_JOB_NONE|NS_JOB_THREAD, my_callback, ...);
...
void my_callback(struct ns_job_t *job)
{
// now in a separate thread
}
Parameters
tpThe thread pool you want to add the job to.
job_typeA set of flags that indicates the job type (usually just NS_JOB_NONE|NS_JOB_THREAD)
funcThe callback function to call when processing the job.
dataArbitrary data that will be available to the job callback function.
[out]jobThe address of a job pointer that will be filled in once the job is allocated. NULL can be passed if a pointer to the job is not needed.
Return values
PR_SUCCESSJob was successfully added.
PR_FAILUREFailed to add job.
Warning
The thread pool will not allow a job to be added when it has been signaled to shutdown. It will return PR_FAILURE in that case.
See also
ns_job_t, ns_job_get_data, NS_JOB_NONE, NS_JOB_THREAD

§ ns_add_signal_job()

PRStatus ns_add_signal_job ( ns_thrpool_t tp,
PRInt32  signum,
ns_job_type_t  job_type,
ns_job_func_t  func,
void *  data,
struct ns_job_t **  job 
)

Adds a signal job to the thread pool

The func function will be called when the signal is received by the process.

Parameters
tpThe thread pool you want to add a signal job to.
signumThe signal number that you want to trigger the callback function.
job_typeA set of flags that indicates the job type.
funcThe callback function to call when processing the job.
dataArbitrary data that will be available to the job callback function.
[out]jobThe address of a job pointer that will be filled in once the job is allocated. NULL can be passed if a pointer to the job is not needed.
Return values
PR_SUCCESSJob was successfully added.
PR_FAILUREFailed to add job.
Warning
The thread pool will not allow a job to be added when it has been signaled to shutdown. It will return PR_FAILURE in that case.
See also
ns_job_t, ns_job_get_data, NS_JOB_SIGNAL, NS_JOB_IS_SIGNAL

§ ns_add_timeout_job()

PRStatus ns_add_timeout_job ( struct ns_thrpool_t tp,
struct timeval *  tv,
ns_job_type_t  job_type,
ns_job_func_t  func,
void *  data,
struct ns_job_t **  job 
)

Adds a timeout job to the thread pool

The func function will be called when the timer expires.

Parameters
tpThe thread pool you want to add a timeout job to.
tvThe timer that needs to expire before triggering the callback function.
job_typeA set of flags that indicates the job type - NS_JOB_TIMER + other flags
funcThe callback function to call when processing the job.
dataArbitrary data that will be available to the job callback function.
[out]jobThe address of a job pointer that will be filled in once the job is allocated. NULL can be passed if a pointer to the job is not needed.
Return values
PR_SUCCESSJob was successfully added.
PR_FAILUREFailed to add job.
Warning
The thread pool will not allow a job to be added when it has been signaled to shutdown. It will return PR_FAILURE in that case.
See also
ns_job_t, ns_job_get_data, NS_JOB_TIMER, NS_JOB_IS_TIMER, ns_job_done

§ ns_create_job()

PRStatus ns_create_job ( struct ns_thrpool_t tp,
ns_job_type_t  job_type,
ns_job_func_t  func,
struct ns_job_t **  job 
)

Create a new job which is not yet armed.

Specify the type of job using the job_type bitfield. You can specify more than one type of job.

The callback will need to rearm the job or add another job if it wants to be notified of more events.

This job is not armed at creation unlike other ns_add_*_job. This means that after the job is created, you can use ns_job_set_*, and when ready, arm the job.

struct ns_job_t *job;
ns_create_job(tp, NS_JOB_READ, my_callback, &job);
ns_job_set_data(job, data);
// You may not alter job once it is armed.
Parameters
tpThe thread pool you want to add an I/O job to.
job_typeA set of flags that indicates the job type.
funcThe callback function to call when processing the job.
[out]jobThe address of a job pointer that will be filled in once the job is allocated.
Return values
PR_SUCCESSJob was successfully added.
PR_FAILUREFailed to add job.
Warning
The thread pool will not allow a job to be added when it has been signaled to shutdown. It will return PR_FAILURE in that case.
See also
ns_job_t, ns_job_get_data, NS_JOB_READ, NS_JOB_WRITE, NS_JOB_ACCEPT, NS_JOB_CONNECT, NS_JOB_IS_IO, ns_job_done

§ ns_job_done()

PRStatus ns_job_done ( struct ns_job_t job)

The application is finished with this job

The application uses this function to tell nunc-stans that it is finished using this job. Once the application calls this function, it may no longer refer to job - it should be considered as an allocated pointer that the free() function has been called with. An application will typically call ns_job_done() at the end of a job callback function for non-persistent jobs (not using NS_JOB_PERSIST), or at application shutdown time for persistent jobs (using NS_JOB_PERSIST). For an I/O job, ns_job_done will close() the file descriptor associated with the job unless the NS_JOB_PRESERVE_FD is specified when the job is added.

void read_callback(struct ns_job_t *job)
{
appctx_t *appctx = (appctx_t *)ns_job_get_data(job);
...
// ok to use appctx here, but not job
// app must free or ensure appctx is not leaked
return;
}
Parameters
jobthe job to clean up
Return values
PR_SUCCESSJob was successfully queued for removal.
PR_FAILUREFailed to mark job for removal. Likely the job is ARMED! We cannot remove jobs that are armed due to the race conditions it can cause.
See also
ns_job_t, ns_job_get_data, NS_JOB_PERSIST, NS_JOB_PRESERVE_FD

§ ns_job_get_data()

void* ns_job_get_data ( struct ns_job_t job)

Allows the callback to access the private data field in the job.

This is the data field passed in when the job is added. This data is private to the application - nunc-stans does not touch it in any way. The application is responsible for managing the lifecycle of this data.

void my_job_callback(struct ns_job_t *job)
{
myappctx_t *myappctx = (myappctx_t *)ns_job_get_data(job);
...
}
Parameters
jobThe job to get the data for.
Returns
The private data associated with the job.
See also
ns_job_t

§ ns_job_get_fd()

PRFileDesc* ns_job_get_fd ( struct ns_job_t job)

Allows the callback to access the file descriptor for an I/O job

void my_io_job_callback(struct ns_job_t *job)
{
PRFileDesc *fd = ns_job_get_fd(job);
rc = PR_Read(fd, ...);
...
}

If the job is not an I/O job, the function will return NULL.

Parameters
jobThe job to get the fd for.
Return values
fdThe file descriptor associated with the I/O job.
NULLThe job is not an I/O job
See also
ns_job_t, ns_add_io_job, ns_add_io_timeout_job

§ ns_job_get_output_type()

ns_job_type_t ns_job_get_output_type ( struct ns_job_t job)

Allows the callback to know which event triggered the callback. Can only be called from within the callback itself.

The callback func may need to know which event triggered the callback. This function will allow access to the type of event that triggered the callback. For example, when using ns_add_io_timeout_job(), the callback can be called either because of an I/O event or a timer event. Use NS_JOB_IS_TIMER to tell if the event is a timer event, like this:

... handle timeout ...
} else {
... handle I/O ...
}
Parameters
jobThe job to get the output type for.
Returns
The ns_job_type_t corresponding to the event that triggered the callback
See also
ns_job_t, NS_JOB_IS_TIMER, NS_JOB_IS_READ, NS_JOB_IS_WRITE, NS_JOB_IS_IO, ns_add_io_timeout_job

§ ns_job_get_tp()

ns_thrpool_t* ns_job_get_tp ( struct ns_job_t job)

Allows the callback to access the thread pool that the job is associated with.

Useful for adding jobs from within job callbacks.

void my_job_callback(struct ns_job_t *job)
{
// do some work
// need to listen for some events
ns_add_io_job(ns_job_get_tp(job), fd, ...);
// finished with job
return;
}
Parameters
jobThe job to get the thread pool for.
Returns
The thread pool associated with the job.
See also
ns_job_t, ns_add_io_job

§ ns_job_get_type()

ns_job_type_t ns_job_get_type ( struct ns_job_t job)

Allows the callback to access the job type flags.

Usually used in conjunction with one of the NS_JOB_IS_* macros.

void my_job_callback(struct ns_job_t *job)
{
...
}
}
Parameters
jobThe job to get the type for.
Returns
The ns_job_type_t flags for the job
See also
ns_job_t, NS_JOB_IS_READ, NS_JOB_IS_WRITE, NS_JOB_IS_IO, NS_JOB_IS_TIMER

§ ns_job_rearm()

PRStatus ns_job_rearm ( struct ns_job_t job)

Convenience function to re-arm the same job

This is used for non-persistent (not using NS_JOB_PERSIST) jobs. For example, if you have an I/O reading job, and the job needs to read more data, the job callback can just call ns_job_rearm(), and the job callback will be called again when read is ready on the job fd. Once this function is called, the job callback may be called immediately if the job uses NS_JOB_THREAD. Do not refer to job after calling ns_job_rearm().

Note
Do not call ns_job_done() with a job if using ns_job_rearm() with the job
Parameters
jobThe job to re-arm
See also
ns_job_t, ns_job_done, NS_JOB_PERSIST, NS_JOB_THREAD

§ ns_job_set_data()

PRStatus ns_job_set_data ( struct ns_job_t job,
void *  data 
)

Allows the caller to set private data into the job Care should be taken to make sure that the previous contents are freed, or that the data is freed after use. Leaks will be annoying to track down with this!

This sets the data field. This data is private to the application - nunc-stans will not touch it in any way.

void my_job_callback(struct ns_job_t *job)
{
myappctx_t *myappctx = malloc(sizeof(struct appctx));
...
// You must check and *free* the data if required.
// Else you may introduce a memory leak!
void *data = ns_job_get_data(job);
if (data != NULL) {
myapp_use_data(data);
...
}
free(data);
if (ns_job_set_data(job, (void *)myappctx) == PR_SUCCESS) {
//handle the error, you probably have a bug ....
}
}
Parameters
jobThe job to set the data for
dataThe void * pointer to the data to set
Returns
if the set data succeeded
See also
ns_job_t

§ ns_job_set_done_cb()

PRStatus ns_job_set_done_cb ( struct ns_job_t job,
ns_job_func_t  func 
)

Allows setting the job done callback.

The job done callback will be triggered when ns_job_done is called on the job. This allows jobs to have private data fields cleaned and freed correctly

ns_create_job(tp, NS_JOB_READ, my_callback, &job);
if (ns_job_set_done_cb(job, my_done_callback) != PR_SUCCESS) {
// you must handle this error!!!! the cb did not set!
}
...
void my_done_callback(struct ns_job_t job) {
free(ns_job_get_data(job));
}
Returns
status if the set succeeded. Always check this!
Parameters
jobThe job to set the callback for.
funcThe callback function, to be called when ns_job_done is triggered.
See also
ns_job_t, ns_job_done

§ ns_thrpool_config_init()

void ns_thrpool_config_init ( struct ns_thrpool_config tp_config)

Initialize a thrpool config struct

The config struct must be allocated/freed by the caller. A stack variable is typically used.

struct ns_thrpool_config nsconfig;
nsconfig.max_threads = 16;
nsconfig.malloc_fct = mymalloc;
...
rc = ns_thrpool_new(&nsconfig);
See also
ns_thrpool_config, ns_thrpool_new
Parameters
tp_config- thread pool config struct

§ ns_thrpool_destroy()

void ns_thrpool_destroy ( struct ns_thrpool_t tp)

Frees a thread pool from memory

This will free a thread pool and it's internal resources from memory. You should be sure that the thread pool has been shutdown before destroying it by calling ns_thrpool_wait(), then call ns_job_done() to finish any long-lived jobs. After calling ns_thrpool_destroy(), do not use tp.

Parameters
tpThe thread pool to destroy.
See also
ns_thrpool_config, ns_thrpool_config_init, ns_thrpool_new, ns_thrpool_wait, ns_thrpool_shutdown

§ ns_thrpool_is_shutdown()

PRInt32 ns_thrpool_is_shutdown ( struct ns_thrpool_t tp)

Checks if a thread pool is shutting down

This can be called by worker threads so they know when the thread pool has been requested to shut down.

Return values
0if the thread pool is not shutting down.
1if the thread pool is shutting down.
See also
ns_thrpool_shutdown

§ ns_thrpool_new()

struct ns_thrpool_t* ns_thrpool_new ( struct ns_thrpool_config config)

Creates a new thread pool

Must be called with a struct ns_thrpool_config that has been initialized by ns_thrpool_config_init(). Typically, once the thread pool has been created, one or more listener jobs or other long lived jobs will be added, and the application will just call ns_thrpool_wait(). The application should add at least one job that will listen for shutdown events, signals, etc. which will call ns_thrpool_shutdown(). After ns_thrpool_wait() returns, the application should use ns_job_done() to finish any long-lived jobs, then call ns_thrpool_destroy().

Parameters
configA pointer to a struct ns_thrpool_config
Returns
A pointer to the newly created thread pool.
See also
ns_thrpool_config, ns_thrpool_config_init, ns_thrpool_wait, ns_thrpool_shutdown, ns_thrpool_destroy

§ ns_thrpool_shutdown()

void ns_thrpool_shutdown ( struct ns_thrpool_t tp)

Tells a thread pool to shutdown its threads

The application will usually call ns_thrpool_shutdown() from an event callback that is listening for shutdown events e.g. a signal job that is listening for SIGINT or SIGTERM events.

tp = ns_thrpool_new(...);
ns_add_signal_job(tp, SIGTERM, handle_shutdown_signal, NS_JOB_SIGNAL|NS_JOB_THREAD, ...);
void handle_shutdown_signal(job)
{
// set application shutdown flag
return;
}

Use NS_JOB_SIGNAL|NS_JOB_THREAD so that the job will run in a worker thread, not in the event loop thread.

Note
The application must call ns_thrpool_shutdown() or ns_thrpool_wait() will never return.
Parameters
tpThe thread pool to shutdown.
Warning
This must only be called from a job that runs in a worker thread. Calling this function from the event thread can cause a deadlock.
See also
ns_thrpool_config, ns_thrpool_config_init, ns_thrpool_new, ns_thrpool_wait, ns_thrpool_destroy, ns_add_signal_job, NS_JOB_THREAD

§ ns_thrpool_wait()

PRStatus ns_thrpool_wait ( struct ns_thrpool_t tp)

Waits for all threads in the pool to exit

This call will block the caller until all threads in the thread pool have exited. A program will typically create the thread pool by calling ns_thrpool_new(), then it will call ns_thrpool_wait() to wait until the thread pool is shutdown (which is likely initiated by a signal handler). Once this function successfully returns, the thread pool can be safely destroyed by calling ns_thrpool_destroy().

Note
The application must call ns_thrpool_shutdown() or ns_thrpool_wait() will never return.
Parameters
tpThe thread pool to wait for.
Return values
PR_SUCCESSThe thread pool threads completed successfully
PR_FAILUREFailure waiting for the thread pool threads to terminate
See also
ns_thrpool_config, ns_thrpool_config_init, ns_thrpool_new, ns_thrpool_destroy, ns_thrpool_shutdown