pthreadpool: add pthreadpool_restart_check[_monitor_{fd,drain}]()
[samba.git] / lib / pthreadpool / pthreadpool.h
1 /*
2  * Unix SMB/CIFS implementation.
3  * threadpool implementation based on pthreads
4  * Copyright (C) Volker Lendecke 2009,2011
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #ifndef __PTHREADPOOL_H__
21 #define __PTHREADPOOL_H__
22
23 struct pthreadpool;
24
25 /**
26  * @defgroup pthreadpool The pthreadpool API
27  *
28  * This API provides a way to run threadsafe functions in a helper
29  * thread. It is initially intended to run getaddrinfo asynchronously.
30  */
31
32
33 /**
34  * @brief Create a pthreadpool
35  *
36  * A struct pthreadpool is the basis for for running threads in the
37  * background.
38  *
39  * @param[in]   max_threads     Maximum parallelism in this pool
40  * @param[out]  presult         Pointer to the threadpool returned
41  * @return                      success: 0, failure: errno
42  *
43  * max_threads=0 means unlimited parallelism. The caller has to take
44  * care to not overload the system.
45  */
46 int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult,
47                      int (*signal_fn)(int jobid,
48                                       void (*job_fn)(void *private_data),
49                                       void *job_fn_private_data,
50                                       void *private_data),
51                      void *signal_fn_private_data);
52
53 /**
54  * @brief Get the max threads value of pthreadpool
55  *
56  * @note This can be 0 for strict sync processing.
57  *
58  * @param[in]   pool            The pool
59  * @return                      number of possible threads
60  */
61 size_t pthreadpool_max_threads(struct pthreadpool *pool);
62
63 /**
64  * @brief The number of queued jobs of pthreadpool
65  *
66  * This is the number of jobs added by pthreadpool_add_job(),
67  * which are not yet processed by a thread.
68  *
69  * @param[in]   pool            The pool
70  * @return                      The number of jobs
71  */
72 size_t pthreadpool_queued_jobs(struct pthreadpool *pool);
73
74 /**
75  * @brief Check for per thread current working directory support of pthreadpool
76  *
77  * Since Linux kernel 2.6.16, unshare(CLONE_FS) is supported,
78  * which provides a per thread current working directory
79  * and allows [f]chdir() within the worker threads.
80  *
81  * Note that this doesn't work on some contraint container setups,
82  * the complete unshare() syscall might be rejected.
83  * pthreadpool_per_thread_cwd() returns what is available
84  * at runtime, so the callers should really check this!
85  *
86  * @param[in]   pool            The pool to run the job on
87  * @return                      supported: true, otherwise: false
88  */
89 bool pthreadpool_per_thread_cwd(struct pthreadpool *pool);
90
91 /**
92  * @brief Stop a pthreadpool
93  *
94  * Stop a pthreadpool. If jobs are submitted, but not yet active in
95  * a thread, they won't get executed. If a job has already been
96  * submitted to a thread, the job function will continue running, and
97  * the signal function might still be called.
98  *
99  * This allows a multi step shutdown using pthreadpool_stop(),
100  * pthreadpool_cancel_job() and pthreadpool_destroy().
101  *
102  * @param[in]   pool            The pool to stop
103  * @return                      success: 0, failure: errno
104  *
105  * @see pthreadpool_cancel_job()
106  * @see pthreadpool_destroy()
107  */
108 int pthreadpool_stop(struct pthreadpool *pool);
109
110 /**
111  * @brief Destroy a pthreadpool
112  *
113  * This basically implies pthreadpool_stop() if the pool
114  * isn't already stopped.
115  *
116  * Destroy a pthreadpool. If jobs are submitted, but not yet active in
117  * a thread, they won't get executed. If a job has already been
118  * submitted to a thread, the job function will continue running, and
119  * the signal function might still be called. The caller of
120  * pthreadpool_init must make sure the required resources are still
121  * around when the pool is destroyed with pending jobs.  The last
122  * thread to exit will finally free() the pool memory.
123  *
124  * @param[in]   pool            The pool to destroy
125  * @return                      success: 0, failure: errno
126  *
127  * @see pthreadpool_stop()
128  */
129 int pthreadpool_destroy(struct pthreadpool *pool);
130
131 /**
132  * @brief Add a job to a pthreadpool
133  *
134  * This adds a job to a pthreadpool. The job can be identified by
135  * job_id. This integer will be passed to signal_fn() when the
136  * job is completed.
137  *
138  * @param[in]   pool            The pool to run the job on
139  * @param[in]   job_id          A custom identifier
140  * @param[in]   fn              The function to run asynchronously
141  * @param[in]   private_data    Pointer passed to fn
142  * @return                      success: 0, failure: errno
143  */
144 int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
145                         void (*fn)(void *private_data), void *private_data);
146
147 /**
148  * @brief Check if the pthreadpool needs a restart.
149  *
150  * This checks if there are enough threads to run the already
151  * queued jobs. This should be called only the callers signal_fn
152  * (passed to pthreadpool_init()) returned an error, so
153  * that the job's worker thread exited.
154  *
155  * Typically this is called once the file destriptor
156  * returned by pthreadpool_restart_check_monitor_fd()
157  * became readable and pthreadpool_restart_check_monitor_drain()
158  * returned success.
159  *
160  * This function tries to restart the missing threads.
161  *
162  * @param[in]   pool            The pool to run the job on
163  * @return                      success: 0, failure: errno
164  *
165  * @see pthreadpool_restart_check_monitor_fd
166  * @see pthreadpool_restart_check_monitor_drain
167  */
168 int pthreadpool_restart_check(struct pthreadpool *pool);
169
170 /**
171  * @brief Return a file destriptor that monitors the pool.
172  *
173  * If the file destrictor becomes readable,
174  * the event handler should call pthreadpool_restart_check_monitor_drain().
175  *
176  * pthreadpool_restart_check() should also be called once the
177  * state is drained.
178  *
179  * This function returns a fresh fd using dup() each time.
180  *
181  * If the pool doesn't require restarts, this function
182  * returns -1 and sets errno = ENOSYS. The caller
183  * may ignore that situation.
184  *
185  * @param[in]   pool            The pool to run the job on
186  * @return                      success: 0, failure: -1 (set errno)
187  *
188  * @see pthreadpool_restart_check_monitor_fd
189  * @see pthreadpool_restart_check_monitor_drain
190  */
191 int pthreadpool_restart_check_monitor_fd(struct pthreadpool *pool);
192
193 /**
194  * @brief Drain the monitor file destriptor of the pool.
195  *
196  * If the file destrictor returned by pthreadpool_restart_check_monitor_fd()
197  * becomes readable, pthreadpool_restart_check_monitor_drain() should be
198  * called before pthreadpool_restart_check().
199  *
200  * If this function returns an error the caller should close
201  * the file destriptor it got from pthreadpool_restart_check_monitor_fd().
202  *
203  * @param[in]   pool            The pool to run the job on
204  * @return                      success: 0, failure: errno
205  *
206  * @see pthreadpool_restart_check_monitor_fd
207  * @see pthreadpool_restart_check
208  */
209 int pthreadpool_restart_check_monitor_drain(struct pthreadpool *pool);
210
211 /**
212  * @brief Try to cancel a job in a pthreadpool
213  *
214  * This tries to cancel a job in a pthreadpool. The same
215  * arguments, which were given to pthreadpool_add_job()
216  * needs to be passed.
217  *
218  * The combination of id, fn, private_data might not be unique.
219  * So the function tries to cancel as much matching jobs as possible.
220  * Note once a job is scheduled in a thread it's to late to
221  * cancel it.
222  *
223  * Canceled jobs that weren't started yet won't be reported via a
224  * pool's signal_fn.
225  *
226  * @param[in]   pool            The pool to run the job on
227  * @param[in]   job_id          A custom identifier
228  * @param[in]   fn              The function to run asynchronously
229  * @param[in]   private_data    Pointer passed to fn
230  * @return                      The number of canceled jobs
231  *
232  * @see pthreadpool_add_job()
233  * @see pthreadpool_stop()
234  * @see pthreadpool_destroy()
235  */
236 size_t pthreadpool_cancel_job(struct pthreadpool *pool, int job_id,
237                               void (*fn)(void *private_data), void *private_data);
238
239 #endif