Ptex
PtexPlatform.h
Go to the documentation of this file.
1 #ifndef PtexPlatform_h
2 #define PtexPlatform_h
3 #define PtexPlatform_h
4 /*
5 PTEX SOFTWARE
6 Copyright 2014 Disney Enterprises, Inc. All rights reserved
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are
10 met:
11 
12  * Redistributions of source code must retain the above copyright
13  notice, this list of conditions and the following disclaimer.
14 
15  * Redistributions in binary form must reproduce the above copyright
16  notice, this list of conditions and the following disclaimer in
17  the documentation and/or other materials provided with the
18  distribution.
19 
20  * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
21  Studios" or the names of its contributors may NOT be used to
22  endorse or promote products derived from this software without
23  specific prior written permission from Walt Disney Pictures.
24 
25 Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
26 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
27 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
28 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
29 IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
30 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37 */
38 
43 #include "PtexInt.h"
44 
45 // platform-specific includes
46 #if defined(_WIN32) || defined(_WINDOWS) || defined(_MSC_VER)
47 #ifndef WINDOWS
48 #define WINDOWS
49 #endif
50 #define _CRT_NONSTDC_NO_DEPRECATE 1
51 #define _CRT_SECURE_NO_DEPRECATE 1
52 #define NOMINMAX 1
53 
54 // windows - defined for both Win32 and Win64
55 #include <Windows.h>
56 #include <malloc.h>
57 #include <io.h>
58 #include <tchar.h>
59 #include <process.h>
60 
61 #else
62 
63 // linux/unix/posix
64 #include <stdlib.h>
65 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
66 #include <alloca.h>
67 #endif
68 #include <string.h>
69 #include <pthread.h>
70 
71 #ifdef __APPLE__
72 #include <os/lock.h>
73 #include <sys/types.h>
74 #endif
75 #endif
76 
77 // general includes
78 #include <stdio.h>
79 #include <math.h>
80 #include <assert.h>
81 
82 // missing functions on Windows
83 #ifdef WINDOWS
84 typedef __int64 FilePos;
85 #define fseeko _fseeki64
86 #define ftello _ftelli64
87 
88 #else
89 typedef off_t FilePos;
90 #endif
91 
92 #include "PtexVersion.h"
93 
95 
96 /*
97  * Mutex
98  */
99 
100 #ifdef WINDOWS
101 
102 class Mutex {
103 public:
104  Mutex() { _mutex = CreateMutex(NULL, FALSE, NULL); }
105  ~Mutex() { CloseHandle(_mutex); }
106  void lock() { WaitForSingleObject(_mutex, INFINITE); }
107  bool trylock() { return WAIT_TIMEOUT != WaitForSingleObject(_mutex,0);}
108  void unlock() { ReleaseMutex(_mutex); }
109 private:
110  HANDLE _mutex;
111 };
112 
113 class SpinLock {
114 public:
115  SpinLock() { InitializeCriticalSection(&_spinlock); }
116  ~SpinLock() { DeleteCriticalSection(&_spinlock); }
117  void lock() { EnterCriticalSection(&_spinlock); }
118  bool trylock() { return TryEnterCriticalSection(&_spinlock); }
119  void unlock() { LeaveCriticalSection(&_spinlock); }
120 private:
121  CRITICAL_SECTION _spinlock;
122 };
123 
124 #else
125 // assume linux/unix/posix
126 
127 class Mutex {
128 public:
129  Mutex() { pthread_mutex_init(&_mutex, 0); }
130  ~Mutex() { pthread_mutex_destroy(&_mutex); }
131  void lock() { pthread_mutex_lock(&_mutex); }
132  bool trylock() { return 0 == pthread_mutex_trylock(&_mutex); }
133  void unlock() { pthread_mutex_unlock(&_mutex); }
134 private:
135  pthread_mutex_t _mutex;
136 };
137 
138 #ifdef __APPLE__
139 class SpinLock {
140 public:
141  SpinLock() { _spinlock = OS_UNFAIR_LOCK_INIT; }
142  ~SpinLock() { }
143  void lock() { os_unfair_lock_lock(&_spinlock); }
144  bool trylock() { return os_unfair_lock_trylock(&_spinlock); }
145  void unlock() { os_unfair_lock_unlock(&_spinlock); }
146 private:
147  os_unfair_lock _spinlock;
148 };
149 #else
150 class SpinLock {
151 public:
152  SpinLock() { pthread_spin_init(&_spinlock, PTHREAD_PROCESS_PRIVATE); }
153  ~SpinLock() { pthread_spin_destroy(&_spinlock); }
154  void lock() { pthread_spin_lock(&_spinlock); }
155  bool trylock() { return 0 == pthread_spin_trylock(&_spinlock); }
156  void unlock() { pthread_spin_unlock(&_spinlock); }
157 private:
158  pthread_spinlock_t _spinlock;
159 };
160 #endif // __APPLE__
161 #endif
162 
163 /*
164  * Atomics
165  */
166 
167 #ifdef WINDOWS
168  #define ATOMIC_ALIGNED __declspec(align(8))
169  #define ATOMIC_ADD32(x,y) (InterlockedExchangeAdd((volatile long*)(x),(long)(y)) + (y))
170  #define ATOMIC_ADD64(x,y) (InterlockedExchangeAdd64((volatile long long*)(x),(long long)(y)) + (y))
171  #define ATOMIC_SUB32(x,y) (InterlockedExchangeAdd((volatile long*)(x),-((long)(y))) - (y))
172  #define ATOMIC_SUB64(x,y) (InterlockedExchangeAdd64((volatile long long*)(x),-((long long)(y))) - (y))
173  #define MEM_FENCE() MemoryBarrier()
174  #define BOOL_CMPXCH32(x,y,z) (InterlockedCompareExchange((volatile long*)(x),(long)(z),(long)(y)) == (y))
175  #define BOOL_CMPXCH64(x,y,z) (InterlockedCompareExchange64((volatile long long*)(x),(long long)(z),(long long)(y)) == (y))
176  #ifdef NDEBUG
177  #define PTEX_INLINE __forceinline
178  #else
179  #define PTEX_INLINE inline
180  #endif
181 #else
182  #define ATOMIC_ALIGNED __attribute__((aligned(8)))
183  #define ATOMIC_ADD32(x,y) __sync_add_and_fetch(x,y)
184  #define ATOMIC_ADD64(x,y) __sync_add_and_fetch(x,y)
185  #define ATOMIC_SUB32(x,y) __sync_sub_and_fetch(x,y)
186  #define ATOMIC_SUB64(x,y) __sync_sub_and_fetch(x,y)
187  #define MEM_FENCE() __sync_synchronize()
188  #define BOOL_CMPXCH32(x,y,z) __sync_bool_compare_and_swap((x),(y),(z))
189  #define BOOL_CMPXCH64(x,y,z) __sync_bool_compare_and_swap((x),(y),(z))
190 
191  #ifdef NDEBUG
192  #define PTEX_INLINE inline __attribute__((always_inline))
193  #else
194  #define PTEX_INLINE inline
195  #endif
196 #endif
197 
198 template <typename T>
199 PTEX_INLINE T AtomicAdd(volatile T* target, T value)
200 {
201  switch(sizeof(T)){
202  case 4:
203  return (T)ATOMIC_ADD32(target, value);
204  break;
205  case 8:
206  return (T)ATOMIC_ADD64(target, value);
207  break;
208  default:
209  assert(0=="Can only use 32 or 64 bit atomics");
210  return *(T*)NULL;
211  }
212 }
213 
214 template <typename T>
215 PTEX_INLINE T AtomicIncrement(volatile T* target)
216 {
217  return AtomicAdd(target, (T)1);
218 }
219 
220 template <typename T>
221 PTEX_INLINE T AtomicSubtract(volatile T* target, T value)
222 {
223  switch(sizeof(T)){
224  case 4:
225  return (T)ATOMIC_SUB32(target, value);
226  break;
227  case 8:
228  return (T)ATOMIC_SUB64(target, value);
229  break;
230  default:
231  assert(0=="Can only use 32 or 64 bit atomics");
232  return *(T*)NULL;
233  }
234 }
235 
236 template <typename T>
237 PTEX_INLINE T AtomicDecrement(volatile T* target)
238 {
239  return AtomicSubtract(target, (T)1);
240 }
241 
242 // GCC is pretty forgiving, but ICC only allows int, long and long long
243 // so use partial specialization over structs (C(98)) to get certain compilers
244 // to do the specialization to sizeof(T) before doing typechecking and
245 // throwing errors for no good reason.
246 template <typename T, size_t n>
248 
249 template <typename T>
250 struct AtomicCompareAndSwapImpl<T, sizeof(uint32_t)> {
251  PTEX_INLINE bool operator()(T volatile* target, T oldvalue, T newvalue){
252  return BOOL_CMPXCH32((volatile uint32_t*)target,
253  (uint32_t)oldvalue,
254  (uint32_t)newvalue);
255  }
256 };
257 
258 template <typename T>
259 struct AtomicCompareAndSwapImpl<T, sizeof(uint64_t)> {
260  PTEX_INLINE bool operator()(T volatile* target, T oldvalue, T newvalue){
261  return BOOL_CMPXCH64((volatile uint64_t*)target,
262  (uint64_t)oldvalue,
263  (uint64_t)newvalue);
264  }
265 };
266 
267 template <typename T>
268 PTEX_INLINE bool AtomicCompareAndSwap(T volatile* target, T oldvalue, T newvalue)
269 {
270  return AtomicCompareAndSwapImpl<T, sizeof(T)>()(target, oldvalue, newvalue);
271 }
272 
273 template <typename T>
274 PTEX_INLINE void AtomicStore(T volatile* target, T value)
275 {
276  MEM_FENCE();
277  *target = value;
278 }
279 
281 {
282  MEM_FENCE();
283 }
284 
285 
286 #ifndef CACHE_LINE_SIZE
287 #define CACHE_LINE_SIZE 64
288 #endif
289 
290 #define CACHE_LINE_PAD(var,type) char var##_pad[CACHE_LINE_SIZE - sizeof(type)]
291 #define CACHE_LINE_PAD_INIT(var) memset(&var##_pad[0], 0, sizeof(var##_pad))
292 
294 
295 #endif // PtexPlatform_h
Portable fixed-width integer types.
#define ATOMIC_ADD32(x, y)
Definition: PtexPlatform.h:183
#define ATOMIC_SUB64(x, y)
Definition: PtexPlatform.h:186
off_t FilePos
Definition: PtexPlatform.h:89
#define PTEX_INLINE
Definition: PtexPlatform.h:192
PTEX_INLINE T AtomicAdd(volatile T *target, T value)
Definition: PtexPlatform.h:199
#define BOOL_CMPXCH32(x, y, z)
Definition: PtexPlatform.h:188
#define ATOMIC_SUB32(x, y)
Definition: PtexPlatform.h:185
PTEX_INLINE T AtomicDecrement(volatile T *target)
Definition: PtexPlatform.h:237
#define ATOMIC_ADD64(x, y)
Definition: PtexPlatform.h:184
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition: PtexPlatform.h:274
#define MEM_FENCE()
Definition: PtexPlatform.h:187
PTEX_INLINE T AtomicIncrement(volatile T *target)
Definition: PtexPlatform.h:215
PTEX_INLINE void PtexMemoryFence()
Definition: PtexPlatform.h:280
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:268
#define BOOL_CMPXCH64(x, y, z)
Definition: PtexPlatform.h:189
PTEX_INLINE T AtomicSubtract(volatile T *target, T value)
Definition: PtexPlatform.h:221
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
bool trylock()
Definition: PtexPlatform.h:132
void unlock()
Definition: PtexPlatform.h:133
pthread_mutex_t _mutex
Definition: PtexPlatform.h:135
void lock()
Definition: PtexPlatform.h:131
void unlock()
Definition: PtexPlatform.h:156
void lock()
Definition: PtexPlatform.h:154
pthread_spinlock_t _spinlock
Definition: PtexPlatform.h:158
bool trylock()
Definition: PtexPlatform.h:155
Doxygen version sizeof(uint32_t)>... Generating docs for compound AtomicCompareAndSwapImpl< T
PTEX_INLINE bool operator()(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:251
PTEX_INLINE bool operator()(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:260