HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_Relacy.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_Relacy.h (UT Library, C++)
7  *
8  * COMMENTS: Wrapper classes for testing with Relacy.
9  *
10  * - Do NOT include this in .h files!
11  * - Only include this in the .C file of your unit tests.
12  * - Include this file *first* in your .C file so that it can
13  * redefine everything. For any conflicting header files,
14  * add them to the PRE_INCLUDES list below.
15  * - For all classes wrapped by this file, use the macro UT_VAR()
16  * to access the variables of these classes.
17  *
18  * For more information on the Relacy Race Detector see
19  * http://www.1024cores.net/home/relacy-race-detector
20  *
21  */
22 
23 #ifndef __UT_RELACY_INCLUDED__
24 #define __UT_RELACY_INCLUDED__
25 
26 #if !defined(UT_DEBUG_RELACY)
27 
28 //
29 // No Relacy
30 //
31 
32 #define UT_VAR(X) (X)
33 #define UT_VAR_T(X) X
34 
35 #define UT_LOG_EVENT(X)
36 
37 #else
38 
39 
40 // PRE_INCLUDES
41 // These headers must be included before we can perform the redefinitions to
42 // avoid compiler errors in the files that include UT_Relacy.h.
43 #include "UT_Assert.h"
44 #include "UT_ConcurrentVector.h"
45 #include "UT_Debug.h"
46 #include "UT_IntArray.h"
47 #include "UT_LockUtil.h"
48 #include "UT_ValArray.h"
49 #include "UT_RecursiveTimedLock.h"
50 #include "UT_Array.h"
51 #include "UT_SmallObject.h"
52 #include "UT_UniquePtr.h"
53 #include "UT_StopWatch.h"
54 #include "UT_String.h"
55 #include "UT_SysClone.h"
56 #include "UT_TaskLock.h"
57 #include "UT_TestManager.h"
58 #include "UT_Thread.h"
59 #include "UT_ThreadSpecificValue.h"
60 #include "UT_ValArray.h"
61 #include <SYS/SYS_AtomicInt.h>
62 #include <SYS/SYS_AtomicPtr.h>
63 #include <SYS/SYS_BoostThread.h>
64 #include <SYS/SYS_Math.h>
65 #include <SYS/SYS_StaticInit.h>
66 #include <SYS/SYS_Types.h>
67 #include <SYS/SYS_TypeTraits.h>
68 #include <limits>
69 #include <errno.h>
70 #include <stdio.h>
71 
72 
73 //
74 // Relacy
75 //
76 
77 #define RL_MSVC_OUTPUT // output debug message to MSVC
78 #define RL_DEBUGBREAK_ON_FAILURE // cause breakpoint on failures
79 
80 #include <relacy/relacy_std.hpp> // include Relacy
81 
82 namespace UT_Relacy
83 {
84 
85 // Import classes that we're using from Relacy into this namespace
86 using rl::debug_info;
87 using rl::debug_info_param;
88 using rl::atomic;
89 using rl::recursive_timed_mutex;
90 
91 //
92 // Wrapper for atomic variables
93 //
94 
95 #define SYS_MEMORY_ORDER_RELAXED (rl::mo_relaxed)
96 //#define SYS_MEMORY_ORDER_CONSUME (rl::mo_consume)
97 #define SYS_MEMORY_ORDER_ACQ_REL (rl::mo_acq_rel)
98 #define SYS_MEMORY_ORDER_ACQUIRE (rl::mo_acquire)
99 #define SYS_MEMORY_ORDER_RELEASE (rl::mo_release)
100 #define SYS_MEMORY_ORDER_SEQ_CST (rl::mo_seq_cst)
101 
102 template<typename T>
103 class SYS_Atomic;
104 
105 template<typename T>
106 class SYS_AtomicProxyConst
107 {
108 public:
109  SYS_AtomicProxyConst(SYS_Atomic<T> const & var, debug_info_param info)
110  : var_(const_cast<SYS_Atomic<T>&>(var))
111  , info_(info)
112  {
113  }
114 
115  T load(rl::memory_order mo = rl::mo_seq_cst) const
116  {
117  return var_.load(mo, info_);
118  }
119 
120  operator T () const
121  {
122  return load();
123  }
124 
125 protected:
126  SYS_Atomic<T>& var_;
127  debug_info info_;
128 
129  SYS_AtomicProxyConst& operator = (SYS_AtomicProxyConst const&);
130 };
131 
132 template<typename T>
133 class SYS_AtomicProxy : public SYS_AtomicProxyConst<T>
134 {
135 public:
136  SYS_AtomicProxy(SYS_Atomic<T> & var, debug_info_param info)
137  : SYS_AtomicProxyConst<T>(var, info)
138  {
139  }
140 
141  void store(T value, rl::memory_order mo = rl::mo_seq_cst)
142  {
143  this->var_.store(value, mo, this->info_);
144  }
145  T add(T value)
146  {
147  return this->var_.add(value, this->info_);
148  }
149  T exchange(T xchg)
150  {
151  return this->var_.exchange(xchg, this->info_);
152  }
153 };
154 
155 template <typename T>
156 class SYS_Atomic : private rl::generic_atomic<T, true>
157 {
158  typedef rl::generic_atomic<T, true> SUPER;
159 
160 public:
161  SYS_Atomic()
162  {
163  }
164 
165  SYS_Atomic(T value)
166  {
167  SUPER::store(value, rl::mo_relaxed, $);
168  }
169 
170  void store(T val, rl::memory_order mo, rl::debug_info_param info)
171  {
172  SUPER::store(val, mo, info);
173  }
174  T load(rl::memory_order mo, rl::debug_info_param info) const
175  {
176  return SUPER::load(mo, info);
177  }
178  T add(T val, rl::debug_info_param info)
179  {
180  return SUPER::fetch_add(val, rl::mo_seq_cst, info) + val;
181  }
182  T exchange(T val, rl::debug_info_param info)
183  {
184  return SUPER::exchange(val, rl::mo_seq_cst, info);
185  }
186 
187  SYS_AtomicProxyConst<T> operator () (debug_info_param info) const
188  {
189  return SYS_AtomicProxyConst<T>(*this, info);
190  }
191 
192  SYS_AtomicProxy<T> operator () (debug_info_param info)
193  {
194  return SYS_AtomicProxy<T>(*this, info);
195  }
196 
197  friend class SYS_AtomicProxy<T>;
198  friend class SYS_AtomicProxyConst<T>;
199 
200  RL_NOCOPY(SYS_Atomic);
201 };
202 
203 typedef SYS_Atomic<int32> SYS_AtomicInt32; // From SYS_AtomicInt.h
204 
205 template <typename T>
206 class SYS_AtomicPtr : public SYS_Atomic<T *> // From SYS_AtomicPtr.h
207 {
208 public:
209 
210  SYS_AtomicPtr(T *ptr = NULL)
211  : SYS_Atomic(ptr)
212  {
213  }
214 
215 };
216 
217 inline int
218 SYSgetSTID()
219 {
220  return rl::ctx().current_thread()
221  + UT_Thread::UT_FIRST_SEQUENTIAL_THREAD_INDEX;
222 }
223 
224 class UT_RelacyObject
225 {
226 public:
227  virtual ~UT_RelacyObject() { }
228  virtual void construct(int num_threads) = 0;
229  virtual void destruct() = 0;
230 };
231 
232 class UT_RelacyManager
233 {
234 public:
235  UT_RelacyManager()
236  : myNumThreads(0)
237  {
238  }
239 
240  void subscribe(UT_RelacyObject &obj)
241  {
242  mySubscribers.append(&obj);
243  if (myNumThreads > 0)
244  obj.construct(myNumThreads);
245  }
246  void unsubscribe(UT_RelacyObject &obj)
247  {
248  if (myNumThreads > 0)
249  obj.destruct();
250  mySubscribers.findAndRemove(&obj);
251  }
252 
253  void construct(int num_threads)
254  {
255  myNumThreads = num_threads;
256  for (int i = 0; i < mySubscribers.entries(); i++)
257  mySubscribers(i)->construct(num_threads);
258  }
259 
260  void destruct()
261  {
262  for (int i = 0; i < mySubscribers.entries(); i++)
263  mySubscribers(i)->destruct();
264  myNumThreads = 0;
265  }
266 
267 private:
268  UT_ValArray<UT_RelacyObject *> mySubscribers;
269  int myNumThreads;
270 };
271 static UT_RelacyManager theRelacyManager;
272 
273 template <typename T>
274 class UT_ThreadSpecificValue : public UT_RelacyObject
275 {
276 public:
278  : myValues(NULL)
279  , myNumThreads(0)
280  {
281  theRelacyManager.subscribe(*this);
282  }
284  {
285  theRelacyManager.unsubscribe(*this);
286  }
287 
288  virtual void construct(int num_threads)
289  {
290  myValues = new T[num_threads];
291  myNumThreads = num_threads;
292 
293  // If T is an object, the default constructor will have been
294  // called. Otherwise, initialize the memory to 0.
295  if (std::numeric_limits<T>::is_specialized
297  {
298  memset(static_cast<void *>(myValues), 0, myNumThreads*sizeof(T));
299  }
300  }
301  virtual void destruct()
302  {
303  delete [] myValues;
304  myValues = NULL;
305  myNumThreads = 0;
306  }
307 
308  T &getValueForThread(int thread_index)
309  {
310  thread_index -= UT_Thread::UT_FIRST_SEQUENTIAL_THREAD_INDEX;
311  UT_ASSERT(thread_index >= 0 && thread_index < myNumThreads);
312  return myValues[thread_index];
313  }
314 
315  const T &getValueForThread(int thread_index) const
316  {
317  thread_index -= UT_Thread::UT_FIRST_SEQUENTIAL_THREAD_INDEX;
318  UT_ASSERT(thread_index >= 0 && thread_index < myNumThreads);
319  return myValues[thread_index];
320  }
321 
322  int maxThreadsSeen() const
323  {
324  return myNumThreads;
325  }
326 
327  class const_iterator
328  {
329  public:
330  const_iterator()
331  : myVal(0)
332  , myI(0)
333  , myEnd(0)
334  {
335  }
336  const_iterator(const const_iterator &copy)
337  : myVal(copy.myVal)
338  , myI(copy.myI)
339  , myEnd(copy.myEnd)
340  {
341  }
342  const_iterator &operator=(const const_iterator &copy)
343  {
344  if (this != &copy)
345  {
346  myVal = copy.myVal;
347  myI = copy.myI;
348  myEnd = copy.myEnd;
349  }
350  return *this;
351  }
352 
353  const T &get() const
354  {
355  return myVal->getValueForThread(myI);
356  }
357 
358  int thread() const
359  {
360  return myI;
361  }
362 
363  const_iterator &operator++()
364  {
365  if (myI < myEnd)
366  ++myI;
367  return *this;
368  }
369 
370  bool operator==(const const_iterator &right)
371  {
372  return (myVal == right.myVal
373  && myI == right.myI
374  && myEnd == right.myEnd);
375  }
376  bool operator!=(const const_iterator &right)
377  {
378  return !(*this == right);
379  }
380 
381  protected:
382  const_iterator(UT_ThreadSpecificValue<T> *value, int start)
383  : myVal(value)
384  , myI(start)
385  , myEnd(UT_Thread::UT_FIRST_SEQUENTIAL_THREAD_INDEX
386  + value->maxThreadsSeen())
387  {
388  }
389 
391  int myI;
392  int myEnd;
393  template <typename TY> friend class UT_ThreadSpecificValue;
394  };
395 
396  /// iterator
397  ///
398  /// @note The iterator iterates over ALL possible thread values, thus
399  /// you must be aware that the get() method will return the default value
400  /// for cases where this variable was never used in a thread.
401  class iterator : public const_iterator
402  {
403  public:
404  iterator()
405  : const_iterator()
406  {
407  }
408  iterator(const iterator &copy)
409  : const_iterator(copy)
410  {
411  }
412  iterator &operator=(const iterator &copy)
413  {
414  this->const_iterator::operator=(copy);
415  return *this;
416  }
417 
418 
419  T &get()
420  {
421  return const_iterator::myVal->getValueForThread(
422  const_iterator::myI);
423  }
424 
425  iterator &operator++()
426  {
427  if (const_iterator::myI < const_iterator::myEnd)
428  ++const_iterator::myI;
429  return *this;
430  }
431 
432  bool operator==(const iterator &right)
433  {
434  return (const_iterator::myVal == right.myVal
435  && const_iterator::myI == right.myI
436  && const_iterator::myEnd == right.myEnd);
437  }
438  bool operator!=(const iterator &right)
439  {
440  return !(*this == right);
441  }
442 
443  private:
444  iterator(UT_ThreadSpecificValue<T> *value, int start)
445  : const_iterator(value, start)
446  {
447  }
448  template <typename TY> friend class UT_ThreadSpecificValue;
449  };
450 
451  /// begin() const iterator
452  const_iterator begin() const
453  { return const_iterator(this,
454  UT_Thread::UT_FIRST_SEQUENTIAL_THREAD_INDEX); }
455  /// end() const iterator
456  const_iterator end() const
457  { return const_iterator(this,
458  UT_Thread::UT_FIRST_SEQUENTIAL_THREAD_INDEX + maxThreadsSeen()); }
459 
460  /// begin() iterator
461  iterator begin()
462  { return iterator(this, UT_Thread::UT_FIRST_SEQUENTIAL_THREAD_INDEX); }
463  /// end() iterator
464  iterator end()
465  { return iterator(this,
466  UT_Thread::UT_FIRST_SEQUENTIAL_THREAD_INDEX + maxThreadsSeen()); }
467 
468 private:
469  T * myValues;
470  int myNumThreads;
471 };
472 
473 class UT_RecursiveTimedLockProxy
474 {
475 public:
476  UT_RecursiveTimedLockProxy(
477  recursive_timed_mutex &mutex,
478  debug_info_param info
479  )
480  : mutex_(mutex)
481  , info_(info)
482  {
483  }
484 
485  bool timedLock(int ms) { return mutex_.timed_lock(ms, info_); }
486  bool tryLock() { return mutex_.try_lock(info_); }
487  void lock() { mutex_.lock(info_); }
488  void unlock() { mutex_.unlock(info_); }
489 
490 private:
491  recursive_timed_mutex & mutex_;
492  debug_info info_;
493 };
494 
496 {
497 public:
499  {
500  }
501 
502  UT_RecursiveTimedLockProxy operator()(debug_info_param info)
503  {
504  return UT_RecursiveTimedLockProxy(mutex_, info);
505  }
506 
507 private:
508  recursive_timed_mutex mutex_;
509 
510  RL_NOCOPY(UT_RecursiveTimedLock);
511 };
512 
513 } // namespace UT_Relacy
514 
515 //
516 // Defines to swap in use of the wrappers
517 //
518 #define SYSgetSTID UT_Relacy::SYSgetSTID
519 #define UT_RecursiveTimedLock UT_Relacy::UT_RecursiveTimedLock
520 #define UT_ThreadSpecificValue UT_Relacy::UT_ThreadSpecificValue
521 #define SYS_AtomicInt32 UT_Relacy::SYS_AtomicInt32
522 #define SYS_AtomicPtr UT_Relacy::SYS_AtomicPtr
523 
524 // Substitute UT_ASSERT() with RL_ASSERT()
525 #ifdef UT_ASSERT
526  #undef UT_ASSERT
527 #endif
528 #define UT_ASSERT RL_ASSERT
529 
530 // Relacy specific macros
531 #define UT_LOG_EVENT(X) if (rl::ctx().collecting_history()) { RL_LOG(X); }
532 #define UT_VAR(X) VAR((X))
533 #define UT_VAR_T(X) VAR_T(X)
534 
535 #endif // UT_DEBUG_RELACY
536 
537 
538 //////////////////////////////////////////////////////////////////////////////
539 //
540 // UT_RelacyTest
541 //
542 
543 #ifdef UT_DEBUG_RELACY
544 
545 template <typename DERIVED_T, int THREAD_COUNT>
546 class UT_RelacyTest : public rl::test_suite<DERIVED_T, THREAD_COUNT>
547 {
548 public:
549  static bool simulate(int ITER_COUNT_RELACTY)
550  {
551  rl::test_params params;
552 
553  params.iteration_count = ITER_COUNT_RELACY;
554  params.search_type = rl::random_scheduler_type;
555  params.execution_depth_limit = 4000;
556  //
557  //params.iteration_count = 1;
558  //params.search_type = rl::fair_context_bound_scheduler_type;
559  //
560  //params.iteration_count = 1;
561  //params.search_type = rl::fair_full_search_scheduler_type;
562 
563  return rl::simulate<DERIVED_T>(params);
564  }
565 
566 protected:
567  void construct()
568  {
569  UT_Relacy::theRelacyManager.construct(THREAD_COUNT);
570  }
571  void destruct()
572  {
573  UT_Relacy::theRelacyManager.destruct();
574  }
575 
576  void fail()
577  {
578  UT_ASSERT(!"Test failed");
579  }
580 
581  // In Relacy, random timer's are already occurring so just skip
582  // this step algother.
583  void setSeed(unsigned int /*seed*/)
584  {
585  }
586  void sleepRandom(unsigned int /*max_millisec*/)
587  {
588  }
589 
590  int getMaxThreadId(int num_threads) const
591  {
592  return num_threads - 1;
593  }
594 
595 private:
596 };
597 
598 #else
599 
600 #include "UT_Assert.h"
601 #include "UT_ValArray.h"
602 #include "UT_Thread.h"
603 #include "UT_StopWatch.h"
604 #include "UT_String.h"
605 #include "UT_SysClone.h"
606 #include "UT_UniquePtr.h"
607 #include <SYS/SYS_Math.h>
608 #include <typeinfo>
609 
610 namespace UT_Relacy
611 {
612 
614 {
615 public:
617  : mySize(0)
618  {
619  }
621  {
622  for (int i = 0; i < myThreads.entries(); i++)
623  delete myThreads(i);
624  }
625 
626  void resize(int count)
627  {
628  mySize = count;
629 
630  // always grow array to maximum requested count
631  for (int i = myThreads.entries(); i < count; i++)
632  {
634  thr->startThread(0,0);
635  myThreads.append(thr);
636  }
637  UT_ASSERT(count <= myThreads.entries());
638  }
639 
641  {
642  UT_ASSERT(i >= 0 && i < mySize);
643  return myThreads(i);
644  }
645 
646  void waitThreads()
647  {
648  for (int i = 0; i < mySize; i++)
649  myThreads(i)->waitForState(UT_Thread::ThreadIdle);
650  }
651 
652  static ThreadPool *get(int count)
653  {
654  ThreadPool *&pool = getPoolPtr();
655 
656  if (!pool)
657  pool = new ThreadPool;
658 
659  pool->resize(count);
660  return pool;
661  }
662 
663  static void destroy()
664  {
665  ThreadPool *&pool = getPoolPtr();
666  delete pool;
667  pool = NULL;
668  }
669 
670 private:
671  static ThreadPool *&getPoolPtr()
672  {
673  static ThreadPool *thePool = NULL;
674  return thePool;
675  }
676 
677  UT_ValArray<UT_Thread *> myThreads;
678  int mySize;
679 };
680 
681 template <typename T>
683 {
685  int myIndex;
686 
687  static void *func(void *data)
688  {
689  ThreadData<T> * me = (ThreadData<T> *)data;
690  int i = me->myIndex;
691 
692  me->myTest->mySeqThreadIndex[i] = SYSgetSTID();
693  me->myTest->thread(i);
694  return NULL;
695  }
696 };
697 
698 } // namespace UT_Relacy
699 
700 template <typename DERIVED_T, int THREAD_COUNT>
702 {
703 public:
705 
706 
707  static bool simulate(int ITER_COUNT, bool verbose)
708  {
710  pool = UT_Relacy::ThreadPool::get(THREAD_COUNT);
711  bool passed = true;
713  UT_String num;
714 
715  if (verbose)
716  ts = UTmakeUnique<UT_Timer>(typeid(DERIVED_T).name());
717 
718  for (int iter = 0; iter < ITER_COUNT; iter++)
719  {
720  DERIVED_T test;
722 
723  for (int i = 0; i < THREAD_COUNT; i++)
724  {
725  data[i].myTest = &test;
726  data[i].myIndex = i;
727  }
728 
729  test.myOk = true;
730  test.before();
731 
732  for (int i = 0; i < THREAD_COUNT; i++)
733  {
734  UT_Thread * thr = pool->getThread(i);
735 
737  &data[i]))
738  {
739  UT_ASSERT(!"Failed to start thread");
740  passed = false;
741  break;
742  }
743  }
744  pool->waitThreads();
745 
746  test.after();
747  if (!test.myOk)
748  passed = false;
749  }
750 
751  num.itoa(ITER_COUNT);
752  if (ts)
753  ts->timeStamp("iterations", num);
754  return passed;
755  }
756 
757 protected:
758  void construct()
759  {
760  mySeed = (int32)(((size_t)this) & 0xFFFFFFFF);
761  }
762  void destruct()
763  {
764  }
765 
766  void fail()
767  {
768  UT_ASSERT(!"Test failed");
769  myOk = false;
770  }
771 
772  void sleepRandom(unsigned int max_millisec)
773  {
774  UTnap((unsigned)(SYSrandom(mySeed)*max_millisec));
775  }
776 
777  int getMaxThreadId(int num_threads) const
778  {
779  int max_id = 0;
780  int max_value = mySeqThreadIndex[max_id];
781 
782  for (int i = 1; i < num_threads; i++)
783  {
784  if (mySeqThreadIndex[i] > max_value)
785  {
786  max_value = mySeqThreadIndex[i];
787  max_id = i;
788  }
789  }
790 
791  return max_id;
792  }
793 
794 private:
795  uint mySeed;
796  int mySeqThreadIndex[THREAD_COUNT];
797  bool myOk;
798 
799  template <typename T> friend struct UT_Relacy::ThreadData;
800 };
801 
802 #endif // UT_DEBUG_RELACY
803 
804 
805 #endif // __UT_RELACY_INCLUDED__
constexpr auto max_value() -> T
Definition: format.h:484
cvex test(vector P=0;int unbound=3;export float s=0;export vector Cf=0;)
Definition: test.vfl:11
int int32
Definition: SYS_Types.h:39
void fail()
Definition: UT_Relacy.h:766
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
UT_Thread * getThread(int i)
Definition: UT_Relacy.h:640
GLuint start
Definition: glcorearb.h:475
GLsizei const GLfloat * value
Definition: glcorearb.h:824
GLdouble right
Definition: glad.h:2817
void sleepRandom(unsigned int max_millisec)
Definition: UT_Relacy.h:772
SYS_AtomicInt< int32 > SYS_AtomicInt32
Definition: SYS_AtomicInt.h:96
GLenum const GLfloat * params
Definition: glcorearb.h:105
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
Lock adapter for std mutexes.
static ThreadPool * get(int count)
Definition: UT_Relacy.h:652
GLuint GLuint end
Definition: glcorearb.h:475
int getMaxThreadId(int num_threads) const
Definition: UT_Relacy.h:777
static bool simulate(int ITER_COUNT, bool verbose)
Definition: UT_Relacy.h:707
virtual bool startThread(UTthreadFunc func, void *data, int stacksize)=0
void resize(int count)
Definition: UT_Relacy.h:626
GLuint const GLchar * name
Definition: glcorearb.h:786
static void destroy()
Definition: UT_Relacy.h:663
UT_RelacyTest< DERIVED_T, THREAD_COUNT > TestThread
Definition: UT_Relacy.h:704
static int itoa(char *str, int64 i)
exint append()
Definition: UT_Array.h:142
exint entries() const
Alias of size(). size() is preferred.
Definition: UT_Array.h:655
static UT_Thread * allocThread(SpinMode spin_mode)
**Note that the tasks the is the thread number *for the or if it s being executed by a non pool thread(this *can happen in cases where the whole pool is occupied and the calling *thread contributes to running the work load).**Thread pool.Have fun
SYS_API int SYSgetSTID()
void destruct()
Definition: UT_Relacy.h:762
LeafData & operator=(const LeafData &)=delete
VULKAN_HPP_CONSTEXPR_14 VULKAN_HPP_INLINE T exchange(T &obj, U &&newValue)
Definition: vulkan_raii.hpp:25
auto ptr(T p) -> const void *
Definition: format.h:4331
GLuint GLfloat * val
Definition: glcorearb.h:1608
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
ImageBuf OIIO_API add(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
bool operator!=(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:165
void construct()
Definition: UT_Relacy.h:758
unsigned int uint
Definition: SYS_Types.h:45
static void * func(void *data)
Definition: UT_Relacy.h:687
GLint GLsizei count
Definition: glcorearb.h:405
Definition: format.h:1821
UT_StdLockable< std::recursive_timed_mutex > UT_RecursiveTimedLock
**Note that the tasks the is the thread number *for the pool
Definition: thread.h:646
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:566