World of Might and Magic
0.2.0
Open reimplementation of Might and Magic 6 7 8 game engine
|
Классы | |
struct | SDL_atomic_t |
A type representing an atomic integer value. It is a struct so people don't accidentally use numeric operations on it. Подробнее... | |
SDL AtomicLock | |
The atomic locks are efficient spinlocks using CPU instructions, but are vulnerable to starvation and can spin forever if a thread holding a lock has been terminated. For this reason you should minimize the code executed inside an atomic lock and never do expensive things like API or system calls while holding them. The atomic locks are not safe to lock recursively. Porting Note: The spin lock functions and type are required and can not be emulated because they are used in the atomic emulation code. | |
typedef int | SDL_SpinLock |
typedef void(* | SDL_KernelMemoryBarrierFunc) () |
DECLSPEC SDL_bool SDLCALL | SDL_AtomicTryLock (SDL_SpinLock *lock) |
Try to lock a spin lock by setting it to a non-zero value. Подробнее... | |
DECLSPEC void SDLCALL | SDL_AtomicLock (SDL_SpinLock *lock) |
Lock a spin lock by setting it to a non-zero value. Подробнее... | |
DECLSPEC void SDLCALL | SDL_AtomicUnlock (SDL_SpinLock *lock) |
Unlock a spin lock by setting it to 0. Always returns immediately. Подробнее... | |
void | _ReadWriteBarrier (void) |
_inline void | SDL_CompilerBarrier (void) |
DECLSPEC void SDLCALL | SDL_MemoryBarrierReleaseFunction (void) |
DECLSPEC void SDLCALL | SDL_MemoryBarrierAcquireFunction (void) |
DECLSPEC SDL_bool SDLCALL | SDL_AtomicCAS (SDL_atomic_t *a, int oldval, int newval) |
Set an atomic variable to a new value if it is currently an old value. Подробнее... | |
DECLSPEC int SDLCALL | SDL_AtomicSet (SDL_atomic_t *a, int v) |
Set an atomic variable to a value. Подробнее... | |
DECLSPEC int SDLCALL | SDL_AtomicGet (SDL_atomic_t *a) |
Get the value of an atomic variable. Подробнее... | |
DECLSPEC int SDLCALL | SDL_AtomicAdd (SDL_atomic_t *a, int v) |
Add to an atomic variable. Подробнее... | |
DECLSPEC SDL_bool SDLCALL | SDL_AtomicCASPtr (void **a, void *oldval, void *newval) |
Set a pointer to a new value if it is currently an old value. Подробнее... | |
DECLSPEC void *SDLCALL | SDL_AtomicSetPtr (void **a, void *v) |
Set a pointer to a value atomically. Подробнее... | |
DECLSPEC void *SDLCALL | SDL_AtomicGetPtr (void **a) |
Get the value of a pointer atomically. Подробнее... | |
Atomic operations.
IMPORTANT: If you are not an expert in concurrent lockless programming, you should only be using the atomic lock and reference counting functions in this file. In all other cases you should be protecting your data structures with full mutexes.
The list of "safe" functions to use are: SDL_AtomicLock() SDL_AtomicUnlock() SDL_AtomicIncRef() SDL_AtomicDecRef()
Seriously, here be dragons! ^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can find out a little more about lockless programming and the subtle issues that can arise here: http://msdn.microsoft.com/en-us/library/ee418650%28v=vs.85%29.aspx
There's also lots of good information here: http://www.1024cores.net/home/lock-free-algorithms http://preshing.com/
These operations may or may not actually be implemented using processor specific atomic operations. When possible they are implemented as true processor specific atomic operations. When that is not possible the are implemented using locks that do use the available atomic operations.
All of the atomic operations that modify memory are full memory barriers.
См. определение в файле SDL_atomic.h
typedef int SDL_SpinLock |
См. определение в файле SDL_atomic.h строка 89
typedef void(* SDL_KernelMemoryBarrierFunc) () |
См. определение в файле SDL_atomic.h строка 172
DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock | ( | SDL_SpinLock * | lock | ) |
Try to lock a spin lock by setting it to a non-zero value.
lock | Points to the lock. |
DECLSPEC void SDLCALL SDL_AtomicLock | ( | SDL_SpinLock * | lock | ) |
Lock a spin lock by setting it to a non-zero value.
lock | Points to the lock. |
DECLSPEC void SDLCALL SDL_AtomicUnlock | ( | SDL_SpinLock * | lock | ) |
Unlock a spin lock by setting it to 0. Always returns immediately.
lock | Points to the lock. |
The compiler barrier prevents the compiler from reordering reads and writes to globally visible variables across the call.
Memory barriers are designed to prevent reads and writes from being reordered by the compiler and being seen out of order on multi-core CPUs.
A typical pattern would be for thread A to write some data and a flag, and for thread B to read the flag and get the data. In this case you would insert a release barrier between writing the data and the flag, guaranteeing that the data write completes no later than the flag is written, and you would insert an acquire barrier between reading the flag and reading the data, to ensure that all the reads associated with the flag have completed.
In this pattern you should always see a release barrier paired with an acquire barrier and you should gate the data reads/writes with a single flag variable.
For more information on these semantics, take a look at the blog post: http://preshing.com/20120913/acquire-and-release-semantics
DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS | ( | SDL_atomic_t * | a, |
int | oldval, | ||
int | newval | ||
) |
Set an atomic variable to a new value if it is currently an old value.
DECLSPEC int SDLCALL SDL_AtomicSet | ( | SDL_atomic_t * | a, |
int | v | ||
) |
Set an atomic variable to a value.
DECLSPEC int SDLCALL SDL_AtomicGet | ( | SDL_atomic_t * | a | ) |
Get the value of an atomic variable.
DECLSPEC int SDLCALL SDL_AtomicAdd | ( | SDL_atomic_t * | a, |
int | v | ||
) |
Add to an atomic variable.
Set a pointer to a new value if it is currently an old value.
Set a pointer to a value atomically.