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