Detailed Description
Pool of handles to allow safe access to multiple threads.
Introduction
A Pool structure defines a pool of handles to a resource, and allows a safe way to access them in a multi-threaded environment.
Creation
The fiftyoneDegreesPoolInit method is used to initialise a pointer to a fiftyoneDegreesPool. A concurrency value is provided to indicate the maximum number of threads that will be in operation. If this value is lower than the actual number of threads the stack can be exhausted and a null pointer is returned instead of a valid item. The concurrency value must always be the same or greater than the number of threads. When compiled in single threaded operation a pool is not strictly required and the implementation maintains a simple stack for consistency of interface and to minimise divergent code.
Get & Release
Handles are retrieved from the pool via the fiftyoneDegreesPoolItemGet method. The handle MUST be returned with the fiftyoneDegreesPoolItemRelease method when it is finished with. The handle will always be open and ready for read only operation. If too many threads are accessing the pool simultaneously, meaning a handle cannot be secured, then a NULL pointer is returned.
Free
The items are closed when the pool is released via the fiftyoneDegreesPoolFree method. Any memory allocated by the implementation for the stack is freed.
Usage Example
Design
To improve performance in multi-threaded operation a non locking stack is used where a Compare and Swap (CAS) atomic operation is used to pop and push handles on and off the stack. The design was adapted from the following article (http://nullprogram.com/blog/2014/09/02/) which explains some of the challenges involved including the ABA problem (https://en.wikipedia.org/wiki/ABA_problem). It is for this reason the head structure is implemented as a union between the values and the exchange integer. Pointers are not used as the address space for the stack is continuous and always very small compared to the total addressable memory space.
Collaboration diagram for Pool:
Structs | |
| struct | fiftyoneDegreesPoolItem |
| Pool item node in the stack of items. More... | |
| union | fiftyoneDegreesPoolHead |
| The head of the stack used for pop and push operations. More... | |
| struct | fiftyoneDegreesPool |
| Pool of resources stored as items in a stack. More... | |
Typedefs | |
| typedef void *(* | fiftyoneDegreesPoolResourceCreate) (fiftyoneDegreesPool *pool, void *state, fiftyoneDegreesException *exception) |
| Used to create a new resource for use in the pool. | |
| typedef size_t(* | fiftyoneDegreesPoolResourceSize) (void *state) |
| Used to determine the additional size beyond the pointer used for each resource added to the pool. | |
| typedef void(* | fiftyoneDegreesPoolResourceFree) (fiftyoneDegreesPool *pool, void *resource) |
| Frees a resource previously created with fiftyoneDegreesPoolResourceCreate. | |
Functions | |
| fiftyoneDegreesPool * | fiftyoneDegreesPoolInit (fiftyoneDegreesPool *pool, uint16_t concurrency, void *state, fiftyoneDegreesPoolResourceCreate resourceCreate, fiftyoneDegreesPoolResourceFree resourceFree, fiftyoneDegreesException *exception) |
| Initialises a pool data structure to support the number of concurrent requests that can be made to the pool for resources that can be reused. | |
| fiftyoneDegreesPoolItem * | fiftyoneDegreesPoolItemGet (fiftyoneDegreesPool *pool, fiftyoneDegreesException *exception) |
| Gets the next free item from the pool for exclusive use by the caller. | |
| void | fiftyoneDegreesPoolItemRelease (fiftyoneDegreesPoolItem *item) |
| Releases the item back to the pool it belongs ready to be reused by another operation. | |
| void | fiftyoneDegreesPoolFree (fiftyoneDegreesPool *pool) |
| Releases the items used by the pool freeing the resources used by each item by calling the resourceFree method provided when the pool was created. | |
| void | fiftyoneDegreesPoolReset (fiftyoneDegreesPool *pool) |
| Resets the pool without releasing any resources. | |
Typedef Documentation
◆ fiftyoneDegreesPoolResourceCreate
| typedef void *(* fiftyoneDegreesPoolResourceCreate) (fiftyoneDegreesPool *pool, void *state, fiftyoneDegreesException *exception) |
Used to create a new resource for use in the pool.
- Parameters
-
pool to create the resource for state pointer to data used by the method exception pointer to an exception data structure to be used if an exception occurs. See exceptions.h
- Returns
- pointer to the new resource
◆ fiftyoneDegreesPoolResourceFree
| typedef void(* fiftyoneDegreesPoolResourceFree) (fiftyoneDegreesPool *pool, void *resource) |
Frees a resource previously created with fiftyoneDegreesPoolResourceCreate.
- Parameters
-
pool containing the resource resource to free
◆ fiftyoneDegreesPoolResourceSize
| typedef size_t(* fiftyoneDegreesPoolResourceSize) (void *state) |
Used to determine the additional size beyond the pointer used for each resource added to the pool.
- Parameters
-
state pointer to a state containing the resource and any additional data needed for the calculation
- Returns
- addition size to allocate per resource
Function Documentation
◆ fiftyoneDegreesPoolFree()
| void fiftyoneDegreesPoolFree | ( | fiftyoneDegreesPool * | pool | ) |
Releases the items used by the pool freeing the resources used by each item by calling the resourceFree method provided when the pool was created.
- Parameters
-
pool to be freed
◆ fiftyoneDegreesPoolInit()
| fiftyoneDegreesPool * fiftyoneDegreesPoolInit | ( | fiftyoneDegreesPool * | pool, |
| uint16_t | concurrency, | ||
| void * | state, | ||
| fiftyoneDegreesPoolResourceCreate | resourceCreate, | ||
| fiftyoneDegreesPoolResourceFree | resourceFree, | ||
| fiftyoneDegreesException * | exception ) |
Initialises a pool data structure to support the number of concurrent requests that can be made to the pool for resources that can be reused.
The resourceCreate method is used to create a new resource for use in the pool which will be freed during when the release method is called on the pool using the resourceFree method.
- Parameters
-
pool data structure to be initialised. concurrency the number of resources the pool should contain. state passed to the create resource method. resourceCreate method used to create the resource to be added to items in the pool. resourceFree method used to free a resource from the pool when the pool is freed. exception pointer to an exception data structure to be used if an exception occurs. See exceptions.h.
- Returns
- a pointer to the pool if successful, otherwise NULL.
◆ fiftyoneDegreesPoolItemGet()
| fiftyoneDegreesPoolItem * fiftyoneDegreesPoolItemGet | ( | fiftyoneDegreesPool * | pool, |
| fiftyoneDegreesException * | exception ) |
Gets the next free item from the pool for exclusive use by the caller.
Every item returned must be released when the caller has finished with it using the fiftyoneDegreesPoolItemRelease method.
- Parameters
-
pool to return items from. exception pointer to an exception data structure to be used if an exception occurs. See exceptions.h.
- Returns
- the next free item, or NULL if no items are available.
◆ fiftyoneDegreesPoolItemRelease()
| void fiftyoneDegreesPoolItemRelease | ( | fiftyoneDegreesPoolItem * | item | ) |
Releases the item back to the pool it belongs ready to be reused by another operation.
- Parameters
-
item to be released back to the pool
◆ fiftyoneDegreesPoolReset()
| void fiftyoneDegreesPoolReset | ( | fiftyoneDegreesPool * | pool | ) |
Resets the pool without releasing any resources.
- Parameters
-
pool to be reset
