EPICS Base  7.0.6.1
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
epicsThreadPool.h
1 /*************************************************************************\
2 * Copyright (c) 2014 Brookhaven Science Associates, as Operator of
3 * Brookhaven National Laboratory.
4 * SPDX-License-Identifier: EPICS
5 * EPICS BASE is distributed subject to a Software License Agreement found
6 * in file LICENSE that is included with this distribution.
7 \*************************************************************************/
8 /* General purpose worker thread pool manager
10  */
11 #ifndef EPICSTHREADPOOL_H
12 #define EPICSTHREADPOOL_H
13 
14 #include <stdlib.h>
15 #include <stdio.h>
16 
17 #include "libComAPI.h"
18 #include "errMdef.h"
19 
20 #define S_pool_jobBusy (M_pool| 1) /*Job already queued or running*/
21 #define S_pool_jobIdle (M_pool| 2) /*Job was not queued or running*/
22 #define S_pool_noPool (M_pool| 3) /*Job not associated with a pool*/
23 #define S_pool_paused (M_pool| 4) /*Pool not currently accepting jobs*/
24 #define S_pool_noThreads (M_pool| 5) /*Can't create worker thread*/
25 #define S_pool_timeout (M_pool| 6) /*Pool still busy after timeout*/
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 typedef struct {
32  unsigned int initialThreads;
33  unsigned int maxThreads;
34  unsigned int workerStack;
35  unsigned int workerPriority;
37 
38 typedef struct epicsThreadPool epicsThreadPool;
39 
40 /* Job function call modes */
41 typedef enum {
42  /* Normal run of job */
43  epicsJobModeRun,
44 
45  /* Thread pool is being destroyed.
46  * A chance to cleanup the job immediately with epicsJobDestroy().
47  * If ignored, the job is orphaned (dissociated from the thread pool)
48  * and epicsJobDestroy() must be called later.
49  */
50  epicsJobModeCleanup
51 } epicsJobMode;
52 
53 typedef void (*epicsJobFunction)(void* arg, epicsJobMode mode);
54 
55 typedef struct epicsJob epicsJob;
56 
57 /* Pool operations */
58 
59 /* Initialize a pool config with default values.
60  * This much be done to preserve future compatibility
61  * when new options are added.
62  */
63 LIBCOM_API void epicsThreadPoolConfigDefaults(epicsThreadPoolConfig *);
64 
65 /* fetch or create a thread pool which can be shared with other users.
66  * may return NULL for allocation failures
67  */
68 LIBCOM_API epicsThreadPool* epicsThreadPoolGetShared(epicsThreadPoolConfig *opts);
69 LIBCOM_API void epicsThreadPoolReleaseShared(epicsThreadPool *pool);
70 
71 /* If opts is NULL then defaults are used.
72  * The opts pointer is not stored by this call, and may exist on the stack.
73  */
74 LIBCOM_API epicsThreadPool* epicsThreadPoolCreate(epicsThreadPoolConfig *opts);
75 
76 /* Blocks until all worker threads have stopped.
77  * Any jobs still attached to this pool receive a callback with EPICSJOB_CLEANUP
78  * and are then orphaned.
79  */
80 LIBCOM_API void epicsThreadPoolDestroy(epicsThreadPool *);
81 
82 /* pool control options */
83 typedef enum {
84  epicsThreadPoolQueueAdd, /* val==0 causes epicsJobQueue to fail, 1 is default */
85  epicsThreadPoolQueueRun /* val==0 prevents workers from running jobs, 1 is default */
86 } epicsThreadPoolOption;
87 
88 LIBCOM_API void epicsThreadPoolControl(epicsThreadPool* pool,
89  epicsThreadPoolOption opt,
90  unsigned int val);
91 
92 /* Block until job queue is emptied and no jobs are running.
93  * Useful after calling epicsThreadPoolControl() with option epicsThreadPoolQueueAdd=0
94  *
95  * timeout<0 waits forever, timeout==0 polls, timeout>0 waits at most one timeout period
96  * Returns 0 for success or non-zero on error (timeout is ETIMEOUT)
97  */
98 LIBCOM_API int epicsThreadPoolWait(epicsThreadPool* pool, double timeout);
99 
100 
101 /* Per job operations */
102 
103 /* Special flag for epicsJobCreate().
104  * When passed as the third argument "user"
105  * the argument passed to the job callback
106  * will be the epicsJob*
107  */
108 #define EPICSJOB_SELF epicsJobArgSelfMagic
109 LIBCOM_API extern void* epicsJobArgSelfMagic;
110 
111 /* Creates, but does not add, a new job.
112  * If pool is NULL then the job is not associated with any pool and
113  * epicsJobMove() must be called before epicsJobQueue().
114  * Safe to call from a running job function.
115  * Returns a new job pointer, or NULL on error.
116  */
117 LIBCOM_API epicsJob* epicsJobCreate(epicsThreadPool* pool,
118  epicsJobFunction cb,
119  void* user);
120 
121 /* Cancel and free a job structure. Does not block.
122  * Job may not be immediately free'd.
123  * Safe to call from a running job function.
124  */
125 LIBCOM_API void epicsJobDestroy(epicsJob*);
126 
127 /* Move the job to a different pool.
128  * If pool is NULL then the job will no longer be associated
129  * with any pool.
130  * Not thread safe. Job must not be running or queued.
131  * returns 0 on success, non-zero on error.
132  */
133 LIBCOM_API int epicsJobMove(epicsJob* job, epicsThreadPool* pool);
134 
135 /* Adds the job to the run queue
136  * Safe to call from a running job function.
137  * returns 0 for success, non-zero on error.
138  */
139 LIBCOM_API int epicsJobQueue(epicsJob*);
140 
141 /* Remove a job from the run queue if it is queued.
142  * Safe to call from a running job function.
143  * returns 0 if job was queued and now is not.
144  * 1 if job already ran, is running, or was not queued before,
145  * Other non-zero on error
146  */
147 LIBCOM_API int epicsJobUnqueue(epicsJob*);
148 
149 
150 /* Mostly useful for debugging */
151 
152 LIBCOM_API void epicsThreadPoolReport(epicsThreadPool *pool, FILE *fd);
153 
154 /* Current number of active workers. May be less than the maximum */
155 LIBCOM_API unsigned int epicsThreadPoolNThreads(epicsThreadPool *);
156 
157 #ifdef __cplusplus
158 }
159 #endif
160 
161 #endif // EPICSTHREADPOOL_H