Nunc Stans public API. More...
#include "nspr.h"
Go to the source code of this file.
Data Structures | |
struct | ns_thrpool_config |
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_t * | ns_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_t * | ns_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) |
Nunc Stans public API.
This is the public API for Nunc Stans
#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.
You will probably want to keep track of listenerjob and use it with ns_job_done() at application shutdown time to avoid leaking resources.
#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.
#define NS_JOB_IS_ACCEPT | ( | eee | ) | ((eee)&NS_JOB_ACCEPT) |
Used to test an ns_job_type_t value for NS_JOB_ACCEPT
#define NS_JOB_IS_CONNECT | ( | eee | ) | ((eee)&NS_JOB_CONNECT) |
Used to test an ns_job_type_t value for NS_JOB_CONNECT
#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
#define NS_JOB_IS_PERSIST | ( | eee | ) | ((eee)&NS_JOB_PERSIST) |
Used to test an ns_job_type_t value for NS_JOB_PERSIST
#define NS_JOB_IS_PRESERVE_FD | ( | eee | ) | ((eee)&NS_JOB_PRESERVE_FD) |
Used to test an ns_job_type_t value for NS_JOB_PRESERVE_FD
#define NS_JOB_IS_READ | ( | eee | ) | ((eee)&NS_JOB_READ) |
Used to test an ns_job_type_t value for NS_JOB_READ
#define NS_JOB_IS_SIGNAL | ( | eee | ) | ((eee)&NS_JOB_SIGNAL) |
Used to test an ns_job_type_t value for NS_JOB_SIGNAL
#define NS_JOB_IS_THREAD | ( | eee | ) | ((eee)&NS_JOB_THREAD) |
Used to test an ns_job_type_t value for NS_JOB_THREAD
#define NS_JOB_IS_TIMER | ( | eee | ) | ((eee)&NS_JOB_TIMER) |
Used to test an ns_job_type_t value for NS_JOB_TIMER
#define NS_JOB_IS_WRITE | ( | eee | ) | ((eee)&NS_JOB_WRITE) |
Used to test an ns_job_type_t value for NS_JOB_WRITE
#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.
#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.
#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.
#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.
#define NS_JOB_SET_READ | ( | eee | ) | ((eee) |= NS_JOB_READ) |
Used to set an ns_job_type_t value to have NS_JOB_READ
#define NS_JOB_SET_THREAD | ( | eee | ) | ((eee) |= NS_JOB_THREAD) |
Used to set an ns_job_type_t value to have NS_JOB_THREAD
#define NS_JOB_SET_WRITE | ( | eee | ) | ((eee) |= NS_JOB_WRITE) |
Used to set an ns_job_type_t value to have NS_JOB_WRITE
#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.
#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.
Use ns_job_get_type() or ns_job_get_output_type() with NS_JOB_IS_THREAD to test if the job is threaded.
#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.
#define NS_JOB_UNSET_READ | ( | eee | ) | ((eee) &= ~NS_JOB_READ) |
Remove NS_JOB_READ from an ns_job_type_t value
#define NS_JOB_UNSET_THREAD | ( | eee | ) | ((eee) &= ~NS_JOB_THREAD) |
Remove NS_JOB_THREAD from an ns_job_type_t value
#define NS_JOB_UNSET_WRITE | ( | eee | ) | ((eee) &= ~NS_JOB_WRITE) |
Remove NS_JOB_WRITE from an ns_job_type_t value
#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.
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.
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:
typedef struct ns_thrpool_t ns_thrpool_t |
This is the thread pool typedef
The actual thread pool is opaque to applications.
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.
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().
tp | The thread pool you want to add an I/O job to. | |
fd | The file descriptor to use for I/O. | |
job_type | A set of flags that indicates the job type. | |
func | The callback function to call when processing the job. | |
data | Arbitrary data that will be available to the job callback function. | |
[out] | job | The 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. |
PR_SUCCESS | Job was successfully added. |
PR_FAILURE | Failed to add 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.
tp | The thread pool whose work queue you want to add an I/O job to. | |
fd | The file descriptor to use for I/O. | |
tv | The timer that needs to expire before triggering the callback function. | |
job_type | A set of flags that indicates the job type. | |
func | The callback function for a worker thread to call when processing the job. | |
data | Arbitrary data that will be available to the job callback function. | |
[out] | job | The 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. |
PR_SUCCESS | Job was successfully added. |
PR_FAILURE | Failed to 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.
tp | The thread pool you want to add the job to. | |
job_type | A set of flags that indicates the job type (usually just NS_JOB_NONE|NS_JOB_THREAD) | |
func | The callback function to call when processing the job. | |
data | Arbitrary data that will be available to the job callback function. | |
[out] | job | The 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. |
PR_SUCCESS | Job was successfully added. |
PR_FAILURE | Failed to add 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.
tp | The thread pool you want to add a signal job to. | |
signum | The signal number that you want to trigger the callback function. | |
job_type | A set of flags that indicates the job type. | |
func | The callback function to call when processing the job. | |
data | Arbitrary data that will be available to the job callback function. | |
[out] | job | The 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. |
PR_SUCCESS | Job was successfully added. |
PR_FAILURE | Failed to add 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.
tp | The thread pool you want to add a timeout job to. | |
tv | The timer that needs to expire before triggering the callback function. | |
job_type | A set of flags that indicates the job type - NS_JOB_TIMER + other flags | |
func | The callback function to call when processing the job. | |
data | Arbitrary data that will be available to the job callback function. | |
[out] | job | The 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. |
PR_SUCCESS | Job was successfully added. |
PR_FAILURE | Failed to add 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.
tp | The thread pool you want to add an I/O job to. | |
job_type | A set of flags that indicates the job type. | |
func | The callback function to call when processing the job. | |
[out] | job | The address of a job pointer that will be filled in once the job is allocated. |
PR_SUCCESS | Job was successfully added. |
PR_FAILURE | Failed to add job. |
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.
job | the job to clean up |
PR_SUCCESS | Job was successfully queued for removal. |
PR_FAILURE | Failed 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. |
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.
job | The job to get the data for. |
PRFileDesc* ns_job_get_fd | ( | struct ns_job_t * | job | ) |
Allows the callback to access the file descriptor for an I/O job
If the job is not an I/O job, the function will return NULL.
job | The job to get the fd for. |
fd | The file descriptor associated with the I/O job. |
NULL | The job is not an I/O job |
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:
job | The job to get the output type for. |
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.
job | The job to get the thread pool for. |
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.
job | The job to get the type for. |
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().
job | The job to re-arm |
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.
job | The job to set the data for |
data | The void * pointer to the data to set |
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
job | The job to set the callback for. |
func | The callback function, to be called when ns_job_done is triggered. |
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.
tp_config | - thread pool config struct |
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.
tp | The thread pool to destroy. |
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.
0 | if the thread pool is not shutting down. |
1 | if the thread pool is shutting down. |
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().
config | A pointer to a struct ns_thrpool_config |
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.
Use NS_JOB_SIGNAL|NS_JOB_THREAD so that the job will run in a worker thread, not in the event loop thread.
tp | The thread pool to shutdown. |
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().
tp | The thread pool to wait for. |
PR_SUCCESS | The thread pool threads completed successfully |
PR_FAILURE | Failure waiting for the thread pool threads to terminate |