/usr/include/ode/threading.h is in libode-dev 2:0.13.1+git20150309-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | /*************************************************************************
* *
* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
* All rights reserved. Email: russ@q12.org Web: www.q12.org *
* *
* Threading support header file. *
* Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. *
* e-mail: odar@eleks.com (change all "a" to "e") *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of EITHER: *
* (1) The GNU Lesser General Public License as published by the Free *
* Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. The text of the GNU Lesser *
* General Public License is included with this library in the *
* file LICENSE.TXT. *
* (2) The BSD-style license that is included with this library in *
* the file LICENSE-BSD.TXT. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
* *
*************************************************************************/
/*
* ODE threading support interfaces
*/
#ifndef _ODE_THREADING_H_
#define _ODE_THREADING_H_
#include <ode/odeconfig.h>
// Include <time.h> since time_t is used and it is not available by default in some OSes
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
struct dxThreadingImplementation;
typedef struct dxThreadingImplementation *dThreadingImplementationID;
typedef unsigned dmutexindex_t;
struct dxMutexGroup;
typedef struct dxMutexGroup *dMutexGroupID;
/**
* @brief Allocates a group of muteces.
*
* The Mutex allocated do not need to support recursive locking.
*
* The Mutex names are provided to aid in debugging and thread state tracking.
*
* @param impl Threading implementation ID
* @param Mutex_count Number of Mutex to create
* @Mutex_names_ptr Pointer to optional Mutex names array to be associated with individual Mutex
* @returns MutexGroup ID or NULL if error occurred.
*
* @ingroup threading
* @see dMutexGroupFreeFunction
* @see dMutexGroupMutexLockFunction
* @see dMutexGroupMutexUnlockFunction
*/
typedef dMutexGroupID dMutexGroupAllocFunction (dThreadingImplementationID impl, dmutexindex_t Mutex_count, const char *const *Mutex_names_ptr/*=NULL*/);
/**
* @brief Deletes a group of muteces.
*
* @param impl Threading implementation ID
* @param mutex_group Mutex group to deallocate
*
* @ingroup threading
* @see dMutexGroupAllocFunction
* @see dMutexGroupMutexLockFunction
* @see dMutexGroupMutexUnlockFunction
*/
typedef void dMutexGroupFreeFunction (dThreadingImplementationID impl, dMutexGroupID mutex_group);
/**
* @brief Locks a mutex in a group of muteces.
*
* The function is to block execution until requested mutex can be locked.
*
* Note: Mutex provided may not support recursive locking. Calling this function
* while mutex is already locked by current thread will result in unpredictable behavior.
*
* @param impl Threading implementation ID
* @param mutex_group Mutex group to use for locking
* @param mutex_index The index of mutex to be locked (0..Mutex_count - 1)
*
* @ingroup threading
* @see dMutexGroupAllocFunction
* @see dMutexGroupFreeFunction
* @see dMutexGroupMutexUnlockFunction
*/
typedef void dMutexGroupMutexLockFunction (dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index);
/**
* @brief Attempts to lock a mutex in a group of muteces.
*
* The function is to lock the requested mutex if it is unoccupied or
* immediately return failure if mutex is already locked by other thread.
*
* Note: Mutex provided may not support recursive locking. Calling this function
* while mutex is already locked by current thread will result in unpredictable behavior.
*
* @param impl Threading implementation ID
* @param mutex_group Mutex group to use for locking
* @param mutex_index The index of mutex to be locked (0..Mutex_count - 1)
* @returns 1 for success (mutex is locked) and 0 for failure (mutex is not locked)
*
* @ingroup threading
* @see dMutexGroupAllocFunction
* @see dMutexGroupFreeFunction
* @see dMutexGroupMutexLockFunction
* @see dMutexGroupMutexUnlockFunction
*/
/* typedef int dMutexGroupMutexTryLockFunction (dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index);*/
/**
* @brief Unlocks a mutex in a group of muteces.
*
* The function is to unlock the given mutex provided it had been locked before.
*
* @param impl Threading implementation ID
* @param mutex_group Mutex group to use for unlocking
* @param mutex_index The index of mutex to be unlocked (0..Mutex_count - 1)
*
* @ingroup threading
* @see dMutexGroupAllocFunction
* @see dMutexGroupFreeFunction
* @see dMutexGroupMutexLockFunction
*/
typedef void dMutexGroupMutexUnlockFunction (dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index);
struct dxCallReleasee;
typedef struct dxCallReleasee *dCallReleaseeID;
struct dxCallWait;
typedef struct dxCallWait *dCallWaitID;
typedef size_t ddependencycount_t;
typedef ptrdiff_t ddependencychange_t;
typedef size_t dcallindex_t;
typedef int dThreadedCallFunction(void *call_context, dcallindex_t instance_index,
dCallReleaseeID this_releasee);
typedef struct dxThreadedWaitTime
{
time_t wait_sec;
unsigned long wait_nsec;
} dThreadedWaitTime;
/**
* @brief Allocates a Wait ID that can be used to wait for a call.
*
* @param impl Threading implementation ID
* @returns Wait ID or NULL if error occurred
*
* @ingroup threading
* @see dThreadedCallWaitResetFunction
* @see dThreadedCallWaitFreeFunction
* @see dThreadedCallPostFunction
* @see dThreadedCallWaitFunction
*/
typedef dCallWaitID dThreadedCallWaitAllocFunction(dThreadingImplementationID impl);
/**
* @brief Resets a Wait ID so that it could be used to wait for another call.
*
* @param impl Threading implementation ID
* @param call_wait Wait ID to reset
*
* @ingroup threading
* @see dThreadedCallWaitAllocFunction
* @see dThreadedCallWaitFreeFunction
* @see dThreadedCallPostFunction
* @see dThreadedCallWaitFunction
*/
typedef void dThreadedCallWaitResetFunction(dThreadingImplementationID impl, dCallWaitID call_wait);
/**
* @brief Frees a Wait ID.
*
* @param impl Threading implementation ID
* @param call_wait Wait ID to delete
*
* @ingroup threading
* @see dThreadedCallWaitAllocFunction
* @see dThreadedCallPostFunction
* @see dThreadedCallWaitFunction
*/
typedef void dThreadedCallWaitFreeFunction(dThreadingImplementationID impl, dCallWaitID call_wait);
/**
* @brief Post a function to be called in another thread.
*
* A call is scheduled to be executed asynchronously.
*
* A @a out_summary_fault variable can be provided for call to accumulate any
* possible faults from its execution and execution of any possible sub-calls.
* This variable gets result that @a call_func returns. Also, if dependent calls
* are executed after the call already exits, the variable is also going to be
* updated with results of all those calls before control is released to master.
*
* @a out_post_releasee parameter receives a value of @c dCallReleaseeID that can
* later be used for @a dependent_releasee while scheduling sub-calls to make
* current call depend on them. The value is only returned if @a dependencies_count
* is not zero (i.e. if any dependencies are expected at all). The call is not going
* to start until all its dependencies complete.
*
* In case if number of dependencies is unknown in advance 1 can be passed on call
* scheduling. Then @c dThreadedCallDependenciesCountAlterFunction can be used to
* add one more extra dependencies before scheduling each subcall. And then, after
* all sub-calls had been scheduled, @c dThreadedCallDependenciesCountAlterFunction
* can be used again to subtract initial extra dependency from total number.
* Adding one dependency in advance is necessary to obtain releasee ID and to make
* sure the call will not start and will not terminate before all sub-calls are scheduled.
*
* Extra dependencies can also be added from the call itself after it has already
* been started (with parameter received in @c dThreadedCallFunction).
* In that case those dependencies will start immediately or after call returns
* but the call's master will not be released/notified until all additional
* dependencies complete. This can be used to schedule sub-calls from a call and
* then pass own job to another sub-call dependent on those initial sub-calls.
*
* By using @ call_wait it is possible to assign a Wait ID that can later
* be passed into @c dThreadedCallWaitFunction to wait for call completion.
*
* If @a call_name is available (and it should!) the string must remain valid until
* after call completion. In most cases this should be a static string literal.
*
* Since the function is an analogue of normal method call it is not supposed to fail.
* Any complications with resource allocation on call scheduling should be
* anticipated, avoided and worked around by implementation.
*
* @param impl Threading implementation ID
* @param out_summary_fault Optional pointer to variable to be set to 1 if function
* call (or any sub-call) fails internally, or 0 if all calls return success
* @param out_post_releasee Optional pointer to variable to receive releasee ID
* associated with the call
* @param dependencies_count Number of dependencies that are going to reference
* this call as dependent releasee
* @param dependent_releasee Optional releasee ID to reference with this call
* @param call_wait Optional Wait ID that can later be used to wait for the call
* @param call_func Pointer to function to be called
* @param call_context Context parameter to be passed into the call
* @param instance_index Index parameter to be passed into the call
* @param call_name Optional name to be associated with the call (for debugging and state tracking)
*
* @ingroup threading
* @see dThreadedCallWaitFunction
* @see dThreadedCallDependenciesCountAlterFunction
* @see dThreadingImplResourcesForCallsPreallocateFunction
*/
typedef void dThreadedCallPostFunction(dThreadingImplementationID impl, int *out_summary_fault/*=NULL*/,
dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/,
dCallWaitID call_wait/*=NULL*/,
dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index,
const char *call_name/*=NULL*/);
/**
* @brief Add or remove extra dependencies from call that has been scheduled
* or is in process of execution.
*
* Extra dependencies can be added to a call if exact number of sub-calls is
* not known in advance at the moment the call is scheduled. Also, some dependencies
* can be removed if sub-calls were planned but then dropped.
*
* In case if total dependency count of a call reaches zero by result of invoking
* this function, the call is free to start executing immediately.
*
* After the call execution had been started, any additional dependencies can only
* be added from the call function itself!
*
* @param impl Threading implementation ID
* @param target_releasee ID of releasee to apply dependencies count change to
* @param dependencies_count_change Number of dependencies to add or remove
*
* @ingroup threading
* @see dThreadedCallPostFunction
*/
typedef void dThreadedCallDependenciesCountAlterFunction(dThreadingImplementationID impl, dCallReleaseeID target_releasee,
ddependencychange_t dependencies_count_change);
/**
* @brief Wait for a posted call to complete.
*
* Function blocks until a call identified by @a call_wait completes or
* timeout elapses.
*
* IT IS ILLEGAL TO INVOKE THIS FUNCTION FROM WITHIN A THREADED CALL!
* This is because doing so will block a physical thread and will require
* increasing worker thread count to avoid starvation. Use call dependencies
* if it is necessary make sure sub-calls have been completed instead!
*
* If @a timeout_time_ptr is NULL, the function waits without time limit. If @a timeout_time_ptr
* points to zero value, the function only checks status and does not block.
*
* If @a wait_name is available (and it should!) the string must remain valid for
* the duration of wait. In most cases this should be a static string literal.
*
* Function is not expected to return failures caused by system call faults as
* those are hardly ever possible to be handled in this case anyway. In event of
* system call fault the function is supposed to terminate application.
*
* @param impl Threading implementation ID
* @param out_wait_status Optional pointer to variable to receive 1 if waiting succeeded
* or 0 in case of timeout
* @param call_wait Wait ID that had been passed to scheduling a call that needs to be waited for
* @param timeout_time_ptr Optional pointer to time specification the wait must not
* last longer than (pass NULL for infinite timeout)
* @param wait_name Optional name to be associated with the wait (for debugging and state tracking)
*
* @ingroup threading
* @see dThreadedCallPostFunction
*/
typedef void dThreadedCallWaitFunction(dThreadingImplementationID impl, int *out_wait_status/*=NULL*/,
dCallWaitID call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/,
const char *wait_name/*=NULL*/);
/**
* @brief Retrieve number of active threads that serve the implementation.
*
* @param impl Threading implementation ID
* @returns Number of active threads
*
* @ingroup threading
*/
typedef unsigned dThreadingImplThreadCountRetrieveFunction(dThreadingImplementationID impl);
/**
* @brief Preallocate resources to handle posted calls.
*
* The function is intended to make sure enough resources is preallocated for the
* implementation to be able to handle posted calls. Then @c max_simultaneous_calls_estimate
* is an estimate of how many posted calls can potentially be active or scheduled
* at the same time. The value is usually derived from the way the calls are posted
* in library code and dependencies between them.
*
* @warning While working on an implementation be prepared that the estimate provided
* yet rarely but theoretically can be exceeded due to unpredictability of thread execution.
*
* This function is normally going to be invoked by library each time it is entered
* from outside to do the job but before any threaded calls are going to be posted.
*
* @param impl Threading implementation ID
* @param max_simultaneous_calls_estimate An estimated number of calls that can be posted simultaneously
* @returns 1 or 0 to indicate success or failure
*
* @ingroup threading
* @see dThreadedCallPostFunction
*/
typedef int dThreadingImplResourcesForCallsPreallocateFunction(dThreadingImplementationID impl,
ddependencycount_t max_simultaneous_calls_estimate);
/**
* @brief An interface structure with function pointers to be provided by threading implementation.
*/
typedef struct dxThreadingFunctionsInfo
{
unsigned struct_size;
dMutexGroupAllocFunction *alloc_mutex_group;
dMutexGroupFreeFunction *free_mutex_group;
dMutexGroupMutexLockFunction *lock_group_mutex;
dMutexGroupMutexUnlockFunction *unlock_group_mutex;
dThreadedCallWaitAllocFunction *alloc_call_wait;
dThreadedCallWaitResetFunction *reset_call_wait;
dThreadedCallWaitFreeFunction *free_call_wait;
dThreadedCallPostFunction *post_call;
dThreadedCallDependenciesCountAlterFunction *alter_call_dependencies_count;
dThreadedCallWaitFunction *wait_call;
dThreadingImplThreadCountRetrieveFunction *retrieve_thread_count;
dThreadingImplResourcesForCallsPreallocateFunction *preallocate_resources_for_calls;
/*
* Beware of Jon Watte's anger if you dare to uncomment this!
* May cryptic text below be you a warning!
* Стародавні легенди розказують, що кожного сміливця, хто наважиться порушити табу
* і відкрити заборонений код, спіткає страшне прокляття і він відразу почне робити
* одні лиш помилки.
*
* dMutexGroupMutexTryLockFunction *trylock_group_mutex;
*/
} dThreadingFunctionsInfo;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _ODE_THREADING_H_ */
|