Open Dynamics Engine
threading_base.h
1 /*************************************************************************
2  * *
3  * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4  * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5  * *
6  * Threading base wrapper class header file. *
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  * Threading base class to be used for inheritance by dxWorld, dxSpace and others
29  * to take advantage of threaded execution.
30  */
31 
32 
33 #ifndef _ODE_THREADING_BASE_H_
34 #define _ODE_THREADING_BASE_H_
35 
36 
37 #include <ode/threading.h>
38 
39 
40 struct dxThreadingBase;
41 
43 {
44 public:
45  virtual const dxThreadingFunctionsInfo *RetrieveThreadingDefaultImpl(dThreadingImplementationID &out_default_impl) = 0;
46 };
47 
48 
50 {
51 protected:
53  m_default_impl_provider(NULL),
54  m_functions_info(NULL),
55  m_threading_impl(NULL)
56  {
57  }
58 
59  // This ought to be done via constructor, but passing 'this' in base class initializer emits a warning in MSVC :(
60  void SetThreadingDefaultImplProvider(dxIThreadingDefaultImplProvider *default_impl_provider) { m_default_impl_provider = default_impl_provider; }
61 
62 public:
63  void AssignThreadingImpl(const dxThreadingFunctionsInfo *functions_info, dThreadingImplementationID threading_impl)
64  {
65  dAASSERT((functions_info == NULL) == (threading_impl == NULL));
66 
67  m_functions_info = functions_info;
68  m_threading_impl = threading_impl;
69  }
70 
71 public:
72  dMutexGroupID AllocMutexGroup(dmutexindex_t Mutex_count, const char *const *Mutex_names_ptr/*=NULL*/) const
73  {
74  dThreadingImplementationID impl;
75  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
76  return functions->alloc_mutex_group(impl, Mutex_count, Mutex_names_ptr);
77  }
78 
79  void FreeMutexGroup(dMutexGroupID mutex_group) const
80  {
81  dThreadingImplementationID impl;
82  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
83  functions->free_mutex_group(impl, mutex_group);
84  }
85 
86  void LockMutexGroupMutex(dMutexGroupID mutex_group, dmutexindex_t mutex_index) const
87  {
88  dThreadingImplementationID impl;
89  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
90  functions->lock_group_mutex(impl, mutex_group, mutex_index);
91  }
92 
93 // bool TryLockMutexGroupMutex(dMutexGroupID mutex_group, dmutexindex_t mutex_index) const
94 // {
95 // dThreadingImplementationID impl;
96 // const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
97 // return functions->trylock_group_mutex(impl, mutex_group, mutex_index) != 0;
98 // }
99 
100  void UnlockMutexGroupMutex(dMutexGroupID mutex_group, dmutexindex_t mutex_index) const
101  {
102  dThreadingImplementationID impl;
103  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
104  functions->unlock_group_mutex(impl, mutex_group, mutex_index);
105  }
106 
107  dCallWaitID AllocThreadedCallWait() const
108  {
109  dThreadingImplementationID impl;
110  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
111  return functions->alloc_call_wait(impl);
112  }
113 
114  void ResetThreadedCallWait(dCallWaitID call_wait) const
115  {
116  dThreadingImplementationID impl;
117  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
118  functions->reset_call_wait(impl, call_wait);
119  }
120 
121  void FreeThreadedCallWait(dCallWaitID call_wait) const
122  {
123  dThreadingImplementationID impl;
124  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
125  functions->free_call_wait(impl, call_wait);
126  }
127 
128  void PostThreadedCall(int *out_summary_fault/*=NULL*/,
129  dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/,
130  dCallWaitID call_wait/*=NULL*/,
131  dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index,
132  const char *call_name/*=NULL*/) const
133  {
134  dThreadingImplementationID impl;
135  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
136  functions->post_call(impl, out_summary_fault, out_post_releasee, dependencies_count, dependent_releasee, call_wait, call_func, call_context, instance_index, call_name);
137  }
138 
139  void AlterThreadedCallDependenciesCount(dCallReleaseeID target_releasee,
140  ddependencychange_t dependencies_count_change) const
141  {
142  dThreadingImplementationID impl;
143  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
144  functions->alter_call_dependencies_count(impl, target_releasee, dependencies_count_change);
145  }
146 
147  void WaitThreadedCallExclusively(int *out_wait_status/*=NULL*/,
148  dCallWaitID call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/,
149  const char *wait_name/*=NULL*/) const
150  {
151  dThreadingImplementationID impl;
152  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
153  functions->wait_call(impl, out_wait_status, call_wait, timeout_time_ptr, wait_name);
154  functions->reset_call_wait(impl, call_wait);
155  }
156 
157  void WaitThreadedCallCollectively(int *out_wait_status/*=NULL*/,
158  dCallWaitID call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/,
159  const char *wait_name/*=NULL*/) const
160  {
161  dThreadingImplementationID impl;
162  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
163  functions->wait_call(impl, out_wait_status, call_wait, timeout_time_ptr, wait_name);
164  }
165 
166  unsigned RetrieveThreadingThreadCount() const
167  {
168  dThreadingImplementationID impl;
169  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
170  return functions->retrieve_thread_count(impl);
171  }
172 
173  bool PreallocateResourcesForThreadedCalls(unsigned max_simultaneous_calls_estimate) const
174  {
175  dThreadingImplementationID impl;
176  const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl);
177  return functions->preallocate_resources_for_calls(impl, max_simultaneous_calls_estimate) != 0;
178  }
179 
180 public:
181  void PostThreadedCallsGroup(int *out_summary_fault/*=NULL*/,
182  ddependencycount_t member_count, dCallReleaseeID dependent_releasee/*=NULL*/,
183  dThreadedCallFunction *call_func, void *call_context,
184  const char *call_name/*=NULL*/) const;
185  void PostThreadedCallForUnawareReleasee(int *out_summary_fault/*=NULL*/,
186  dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/,
187  dCallWaitID call_wait/*=NULL*/,
188  dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index,
189  const char *call_name/*=NULL*/) const;
190 
191 protected:
192  const dxThreadingFunctionsInfo *FindThreadingImpl(dThreadingImplementationID &out_impl_found) const;
193 
194 private:
195  const dxThreadingFunctionsInfo *GetFunctionsInfo() const { return m_functions_info; }
196  dThreadingImplementationID GetThreadingImpl() const { return m_threading_impl; }
197 
198 private:
199  dxIThreadingDefaultImplProvider *m_default_impl_provider;
200  const dxThreadingFunctionsInfo *m_functions_info;
201  dThreadingImplementationID m_threading_impl;
202 };
203 
205 {
206 public:
207  dxMutexGroupLockHelper(dxThreadingBase *threading_base, dMutexGroupID mutex_group, dmutexindex_t mutex_index):
208  m_threading_base(threading_base),
209  m_mutex_group(mutex_group),
210  m_mutex_index(mutex_index),
211  m_mutex_locked(true)
212  {
213  threading_base->LockMutexGroupMutex(mutex_group, mutex_index);
214  }
215 
217  {
218  if (m_mutex_locked)
219  {
220  m_threading_base->UnlockMutexGroupMutex(m_mutex_group, m_mutex_index);
221  }
222  }
223 
224  void UnlockMutex()
225  {
226  dIASSERT(m_mutex_locked);
227 
228  m_threading_base->UnlockMutexGroupMutex(m_mutex_group, m_mutex_index);
229  m_mutex_locked = false;
230  }
231 
232  void RelockMutex()
233  {
234  dIASSERT(!m_mutex_locked);
235 
236  m_threading_base->LockMutexGroupMutex(m_mutex_group, m_mutex_index);
237  m_mutex_locked = true;
238  }
239 
240 private:
241  dxThreadingBase *m_threading_base;
242  dMutexGroupID m_mutex_group;
243  dmutexindex_t m_mutex_index;
244  bool m_mutex_locked;
245 };
246 
247 #endif // #ifndef _ODE_THREADING_BASE_H_
Definition: threading_base.h:49
Definition: threading_base.h:204
Definition: threading_base.h:42
Definition: threading.h:154
An interface structure with function pointers to be provided by threading implementation.
Definition: threading.h:370