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
|
/**************************************************************************\
*
* This file is part of the Coin 3D visualization library.
* Copyright (C) by Kongsberg Oil & Gas Technologies.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* ("GPL") version 2 as published by the Free Software Foundation.
* See the file LICENSE.GPL at the root directory of this source
* distribution for additional information about the GNU GPL.
*
* For using Coin with software that can not be combined with the GNU
* GPL, and for taking advantage of the additional benefits of our
* support services, please contact Kongsberg Oil & Gas Technologies
* about acquiring a Coin Professional Edition License.
*
* See http://www.coin3d.org/ for more information.
*
* Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
* http://www.sim.no/ sales@sim.no coin-support@coin3d.org
*
\**************************************************************************/
#include <Inventor/C/threads/thread.h>
#include <stdlib.h>
#include <assert.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <Inventor/C/errors/debugerror.h>
#include "threads/threadp.h"
#include "threads/mutexp.h"
#include "threads/recmutexp.h"
#include "threads/syncp.h"
#include "tidbitsp.h"
/* ********************************************************************** */
/*
FIXME:
- copy struct malloc/free/init/clean setup scheme from cc_string
- use static table of cc_thread structures?
- use cc_storage to reference self-structure for cc_thread_get_self()?
*/
/* ********************************************************************** */
#ifdef USE_PTHREAD
#include "threads/thread_pthread.icc"
#endif /* USE_PTHREAD */
#ifdef USE_W32THREAD
#include "threads/thread_win32.icc"
#endif /* USE_W32THREAD */
/*
*/
cc_thread *
cc_thread_construct(cc_thread_f * func, void * closure)
{
cc_thread * thread;
int ok;
thread = (cc_thread*) malloc(sizeof(cc_thread));
assert(thread != NULL);
thread->func = func;
thread->closure = closure;
ok = internal_init(thread);
if (ok) return thread;
assert(0 && "unable to create thread");
free(thread);
return NULL;
}
/* ********************************************************************** */
/*
*/
void
cc_thread_destruct(cc_thread * thread)
{
int ok;
assert(thread != NULL);
ok = internal_clean(thread);
assert(ok == CC_OK);
free(thread);
}
/* ********************************************************************** */
/*
*/
int
cc_thread_join(cc_thread * thread,
void ** retvalptr)
{
int ok;
assert(thread != NULL);
ok = internal_join(thread, retvalptr);
assert(ok == CC_OK);
return ok;
}
/* ********************************************************************** */
void
cc_sleep(float seconds)
{
#ifndef _WIN32
/* FIXME: 20011107, thammer: create a configure macro to detect
* which sleep function is available */
sleep(floor(seconds));
#else
Sleep((int)(seconds*1000.0));
#endif
};
#ifdef USE_PTHREAD
unsigned long
cc_thread_id(void)
{
return (unsigned long) pthread_self();
}
#endif /* USE_PTHREAD */
#ifdef USE_W32THREAD
static DWORD win32_threadid_idx;
unsigned long
cc_thread_id(void)
{
static unsigned long currentidx = 1;
LPVOID val = TlsGetValue(win32_threadid_idx);
if (val == 0) { /* not set yet */
cc_mutex_global_lock();
val = (LPVOID) currentidx++;
cc_mutex_global_unlock();
if (!TlsSetValue(win32_threadid_idx, (LPVOID)val)) {
assert(0 && "unexpected failure");
}
}
return (unsigned long) val;
}
static void
win32_threadid_idx_cleanup(void)
{
TlsFree(win32_threadid_idx);
}
#endif /* USE_WIN32THREAD */
void
cc_thread_init(void)
{
cc_mutex_init();
cc_sync_init();
#ifdef USE_W32THREAD
/* needed to quickly generate a thread-id for each thread */
win32_threadid_idx = TlsAlloc();
assert(win32_threadid_idx != TLS_OUT_OF_INDEXES);
/* clean-up priority for the thread sub-system in Coin is set so it
is done very late at exit */
/* FIXME: not sure if this really needs the "- 2", but I added it
to keep the same order wrt the other thread-related clean-up
functions, since before I changed hard-coded numbers for
enumerated values for coin_atexit() invocations. 20060301 mortene. */
coin_atexit(win32_threadid_idx_cleanup, CC_ATEXIT_THREADING_SUBSYSTEM_VERYLOWPRIORITY);
#endif /* USE_WIN32THREAD */
cc_recmutex_init();
}
/* ********************************************************************** */
/* maybe use static table of thread structures, reference counted, to be
able to implement something like this, if needed */
/* cc_thread * cc_thread_get_self(void); */
/* ********************************************************************** */
/*
* We don't really want to expose internal id types, which would mean we
* must include threads-implementation-specific headers in the header files.
* It's therefore better to implement the missing/needed functionality for
* the cc_thread type, so id peeking won't be necessary.
*/
/* <id> cc_thread_get_id(cc_thread * thread); */
/* <id> cc_thread_get_current_id(void); */
/* ********************************************************************** */
/*!
\page multithreading_support Multithreading Support in Coin
The support in Coin for using multiple threads in application
programs and the Coin library itself, consists of two main features:
<ul>
<li>
Coin provides platform-independent thread-handling abstraction
classes. These are classes that the application programmer can
freely use in her application code to start new threads, control
their execution, work with mutexes and do other tasks related to
handling multiple threads.
The classes in question are SbThread, SbMutex, SbStorage, SbBarrier,
SbCondVar, SbFifo, SbThreadAutoLock, SbRWMutex, and
SbTypedStorage. See their respective documentation for the detailed
information.
The classes fully hides the system-specific implementation, which is
either done on top of native Win32 (if on Microsoft Windows), or
over POSIX threads (on UNIX and UNIX-like systems).
</li>
<li>
The other aspect of our multi-threading support is that Coin can be
specially configured so that rendering traversals of the scene graph
are done in a thread-safe manner. This means e.g. that it is
possible to have Coin render the scene in parallel on multiple CPUs
for multiple rendering pipes, to better take advantage of such
high-end systems (like CAVE environments, for instance).
Thread-safe render traversals are \e off by default, because there
is a small overhead involved which would make rendering (very)
slightly slower on single-threaded invocations.
To get a Coin library built with thread-safe rendering, one must
actively re-configure Coin and build a special, local version. For
configure-based builds (UNIX and UNIX-like systems, or with Cygwin
on Microsoft Windows) this is done with the option
"--enable-threadsafe" to Autoconf configure. For how to change the
configuration and re-build with Visual Studio, get in touch with us
at "coin-support@coin3d.org".
</li>
</ul>
There are some restrictions and other issues which it is important
to be aware of:
<ul>
<li> We do not yet provide any support for binding the
multi-threaded rendering support into the SoQt / SoWin / etc GUI
bindings, and neither do we provide bindings against any specific
library that handles multi-pipe rendering. This means the
application programmer will have to possess some expertise, and put
in some effort, to be able to utilize multi-pipe rendering with
Coin. </li>
<li> Rendering traversals is currently the only operation which we
publicly support to be thread-safe. There are other aspects of Coin
that we know are thread-safe, like most other action traversals
beside just rendering, but we make no guarantees in this
regard. </li>
<li> Be careful about using a separate thread for changing Coin
structures versus what is used for the application's GUI event
thread.
We are aware of at least issues with Qt (and thereby SoQt), where
you should not modify the scene graph in any way in a thread
separate from the main Qt thread. This because it will trigger
operations where Qt is not thread-safe. </li>
</ul>
\since Coin 2.0
*/
/* ********************************************************************** */
/*!
\class SbThread Inventor/threads/SbThread.h
\brief A class for managing threads.
\ingroup threads
This class provides a portable framework around the tasks of
instantiating, starting, stopping and joining threads.
It wraps the underlying native thread-handling toolkit in a
transparent manner, to make multiplatform threads programming
straightforward for the application programmer.
*/
/*!
\fn static SbThread * SbThread::create(void *(*func)(void *), void * closure)
This function creates a new thread, or returns NULL on failure.
*/
/*!
\fn static void SbThread::destroy(SbThread * thread)
This function destroys a thread.
*/
/*!
\fn static int SbThread::join(SbThread * thread, void ** retval)
This function waits on the death of the given thread, returning the thread's
return value at the location pointed to by \c retval.
*/
/*!
\fn int SbThread::join(void ** retval)
This function waits on the death of the given thread, returning the thread's
return value at the location pointed to by \c retval.
*/
/*!
\fn SbThread::SbThread(cc_thread * thread)
Protected constructor handling the internal thread ADT.
\sa SbThread::create
*/
/*!
\fn SbThread::~SbThread(void)
Destructor.
\sa SbThread::destroy
*/
/* ********************************************************************** */
|