1 /*************************************************************************
2  *                                                                       *
3  * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
4  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
5  *                                                                       *
6  * Builtin ODE threading implementation header.                          *
7  * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved.          *
8  * e-mail: odar@eleks.com (change all "a" to "e")                        *
9  *                                                                       *
10  * This library is free software; you can redistribute it and/or         *
11  * modify it under the terms of EITHER:                                  *
12  *   (1) The GNU Lesser General Public License as published by the Free  *
13  *       Software Foundation; either version 2.1 of the License, or (at  *
14  *       your option) any later version. The text of the GNU Lesser      *
15  *       General Public License is included with this library in the     *
16  *       file LICENSE.TXT.                                               *
17  *   (2) The BSD-style license that is included with this library in     *
18  *       the file LICENSE-BSD.TXT.                                       *
19  *                                                                       *
20  * This library is distributed in the hope that it will be useful,       *
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
23  * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
24  *                                                                       *
25  *************************************************************************/
26 
27 /*
28  *  A threading implementation built into ODE for those who does not care to
29  *  or can't implement an own one.
30  */
31 
32 #ifndef _ODE_THREADING_IMPL_H_
33 #define _ODE_THREADING_IMPL_H_
34 
35 
36 #include <ode/odeconfig.h>
37 #include <ode/threading.h>
38 
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 
45 struct dxThreadingThreadPool;
46 typedef struct dxThreadingThreadPool *dThreadingThreadPoolID;
47 
48 
49 /**
50  * @brief Allocates built-in multi-threaded threading implementation object.
51  *
52  * A multi-threaded implementation is a type of implementation that has to be
53  * served with a thread pool. The thread pool can be either the built-in ODE object
54  * or set of external threads that dedicate themselves to this purpose and stay
55  * in ODE until implementation releases them.
56  *
57  * @returns ID of object allocated or NULL on failure
58  *
59  * @ingroup threading
60  * @see dThreadingThreadPoolServeMultiThreadedImplementation
61  * @see dExternalThreadingServeMultiThreadedImplementation
62  * @see dThreadingFreeImplementation
63  */
64 ODE_API dThreadingImplementationID dThreadingAllocateMultiThreadedImplementation();
65 
66 /**
67  * @brief Retrieves the functions record of a built-in threading implementation.
68  *
69  * The implementation can be the one allocated by ODE (from @c dThreadingAllocateMultiThreadedImplementation).
70  * Do not use this function with self-made custom implementations -
71  * they should be bundled with their own set of functions.
72  *
73  * @param impl Threading implementation ID
74  * @returns Pointer to associated functions structure
75  *
76  * @ingroup threading
77  * @see dThreadingAllocateMultiThreadedImplementation
78  */
79 ODE_API const dThreadingFunctionsInfo *dThreadingImplementationGetFunctions(dThreadingImplementationID impl);
80 
81 /**
82  * @brief Requests a built-in implementation to release threads serving it.
83  *
84  * The function unblocks threads employed in implementation serving and lets them
85  * return to from where they originate. It's the responsibility of external code
86  * to make sure all the calls to ODE that might be dependent on given threading
87  * implementation object had already returned before this call is made. If threading
88  * implementation is still processing some posted calls while this function is
89  * invoked the behavior is implementation dependent.
90  *
91  * This call is to be used to request the threads to be released before waiting
92  * for them in host pool or before waiting for them to exit. Implementation object
93  * must not be destroyed before it is known that all the serving threads have already
94  * returned from it. If implementation needs to be reused after this function is called
95  * and all the threads have exited from it a call to @c dThreadingImplementationCleanupForRestart
96  * must be made to restore internal state of the object.
97  *
98  * If this function is called for self-threaded built-in threading implementation
99  * the call has no effect.
100  *
101  * @param impl Threading implementation ID
102  *
103  * @ingroup threading
104  * @see dThreadingAllocateMultiThreadedImplementation
105  * @see dThreadingImplementationCleanupForRestart
106  */
107 ODE_API void dThreadingImplementationShutdownProcessing(dThreadingImplementationID impl);
108 
109 /**
110  * @brief Restores built-in implementation's state to let it be reused after shutdown.
111  *
112  * If a multi-threaded built-in implementation needs to be reused after a call
113  * to @c dThreadingImplementationShutdownProcessing this call is to be made to
114  * restore object's internal state. After that the implementation can be served again.
115  *
116  * If this function is called for self-threaded built-in threading implementation
117  * the call has no effect.
118  *
119  * @param impl Threading implementation ID
120  *
121  * @ingroup threading
122  * @see dThreadingAllocateMultiThreadedImplementation
123  * @see dThreadingImplementationShutdownProcessing
124  */
125 ODE_API void dThreadingImplementationCleanupForRestart(dThreadingImplementationID impl);
126 
127 /**
128  * @brief Deletes an instance of built-in threading implementation.
129  *
130  * @warning A care must be taken to make sure the implementation is unassigned
131  * from all the objects it was assigned to and that there are no more threads
132  * serving it before attempting to call this function.
133  *
134  * @param impl Threading implementation ID
135  *
136  * @ingroup threading
137  * @see dThreadingAllocateMultiThreadedImplementation
138  */
139 ODE_API void dThreadingFreeImplementation(dThreadingImplementationID impl);
140 
141 
142 typedef void (dThreadReadyToServeCallback)(void *callback_context);
143 
144 /**
145  * @brief An entry point for external threads that would like to serve a built-in
146  * threading implementation object.
147  *
148  * A thread that calls this function remains blocked in ODE and serves implementation
149  * object @p impl until being released with @c dThreadingImplementationShutdownProcessing call.
150  * This function can be used to provide external threads instead of ODE's built-in
151  * thread pools.
152  *
153  * The optional callback @readiness_callback is called after the thread has reached
154  * and has registered within the implementation. The implementation should not
155  * be used until all dedicated threads register within it as otherwise it will not
156  * have accurate view of the execution resources available.
157  *
158  * @param impl Threading implementation ID
159  * @param readiness_callback Optional readiness callback to be called after thread enters the implementation
160  * @param callback_context A value to be passed as parameter to readiness callback
161  *
162  * @ingroup threading
163  * @see dThreadingAllocateMultiThreadedImplementation
164  * @see dThreadingImplementationShutdownProcessing
165  */
166 ODE_API void dExternalThreadingServeMultiThreadedImplementation(dThreadingImplementationID impl,
167   dThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/);
168 
169 
170 /**
171  * @brief Creates an instance of built-in thread pool object that can be used to serve
172  * multi-threaded threading implementations.
173  *
174  * The threads allocated inherit priority of caller thread. Their affinity is not
175  * explicitly adjusted and gets the value the system assigns by default. Threads
176  * have their stack memory fully committed immediately on start. On POSIX platforms
177  * threads are started with all the possible signals blocked. Threads execute
178  * calls to @c dAllocateODEDataForThread with @p ode_data_allocate_flags
179  * on initialization.
180  *
181  * On POSIX platforms this function must be called with signals masked
182  * or other measures must be taken to prevent reception of signals by calling thread
183  * for the duration of the call.
184  *
185  * @param thread_count Number of threads to start in pool
186  * @param stack_size Size of stack to be used for every thread or 0 for system default value
187  * @param ode_data_allocate_flags Flags to be passed to @c dAllocateODEDataForThread on behalf of each thread
188  * @returns ID of object allocated or NULL on failure
189  *
190  * @ingroup threading
191  * @see dThreadingAllocateMultiThreadedImplementation
192  * @see dThreadingImplementationShutdownProcessing
193  * @see dThreadingFreeThreadPool
194  */
195 ODE_API dThreadingThreadPoolID dThreadingAllocateThreadPool(unsigned thread_count,
196   size_t stack_size, unsigned int ode_data_allocate_flags, void *reserved/*=NULL*/);
197 
198 /**
199  * @brief Commands an instance of built-in thread pool to serve a built-in multi-threaded
200  * threading implementation.
201  *
202  * A pool can only serve one threading implementation at a time.
203  * Call @c dThreadingImplementationShutdownProcessing to release pool threads
204  * from implementation serving and make them idle. Pool threads must be released
205  * from any implementations before pool is attempted to be deleted.
206  *
207  * This function waits for threads to register within implementation before returning.
208  * So, after the function call exits the implementation can be used immediately.
209  *
210  * @param pool Thread pool ID to serve the implementation
211  * @param impl Implementation ID of implementation to be served
212  *
213  * @ingroup threading
214  * @see dThreadingAllocateThreadPool
215  * @see dThreadingAllocateMultiThreadedImplementation
216  * @see dThreadingImplementationShutdownProcessing
217  */
218 ODE_API void dThreadingThreadPoolServeMultiThreadedImplementation(dThreadingThreadPoolID pool, dThreadingImplementationID impl);
219 
220 /**
221  * @brief Waits until all pool threads are released from threading implementation
222  * they might be serving.
223  *
224  * The function can be used after a call to @c dThreadingImplementationShutdownProcessing
225  * to make sure all the threads have already been released by threading implementation
226  * and it can be deleted or it can be cleaned up for restart and served by another pool
227  * or this pool's threads can be used to serve another threading implementation.
228  *
229  * Note that is it not necessary to call this function before pool destruction
230  * since @c dThreadingFreeThreadPool performs similar wait operation implicitly on its own.
231  *
232  * It is OK to call this function even if pool was not serving any threading implementation
233  * in which case the call exits immediately with minimal delay.
234  *
235  * @param pool Thread pool ID to wait for
236  *
237  * @ingroup threading
238  * @see dThreadingAllocateThreadPool
239  * @see dThreadingImplementationShutdownProcessing
240  * @see dThreadingFreeThreadPool
241  */
242 ODE_API void dThreadingThreadPoolWaitIdleState(dThreadingThreadPoolID pool);
243 
244 /**
245  * @brief Deletes a built-in thread pool instance.
246  *
247  * The pool threads must be released from any implementations they might be serving
248  * before this function is called. Otherwise the call is going to block
249  * and wait until pool's threads return.
250  *
251  * @param pool Thread pool ID to delete
252  *
253  * @ingroup threading
254  * @see dThreadingAllocateThreadPool
255  * @see dThreadingImplementationShutdownProcessing
256  */
257 ODE_API void dThreadingFreeThreadPool(dThreadingThreadPoolID pool);
258 
259 
260 #ifdef __cplusplus
261 }
262 #endif
263 
264 #endif /* #ifndef _ODE_THREADING_IMPL_H_ */
265