include/SDL_atomic.h
author Sam Lantinga <slouken@libsdl.org>
Sat, 15 Jan 2011 12:41:59 -0800
changeset 5003 3a95a2b93eb3
parent 4474 119023057881
child 5004 0c72ae7b7cb2
permissions -rw-r--r--
Updated the atomic API for better use cases
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21  */
    22 
    23 /**
    24  * \file SDL_atomic.h
    25  * 
    26  * Atomic operations.
    27  * 
    28  * IMPORTANT:
    29  * If you are not an expert in concurrent lockless programming, you should
    30  * only be using the atomic lock and reference counting functions in this
    31  * file.  In all other cases you should be protecting your data structures
    32  * with full mutexes.
    33  * 
    34  * The list of "safe" functions to use are:
    35  *  SDL_AtomicLock()
    36  *  SDL_AtomicUnlock()
    37  *  SDL_AtomicIncRef()
    38  *  SDL_AtomicDecRef()
    39  * 
    40  * Seriously, here be dragons!
    41  *
    42  * These operations may, or may not, actually be implemented using
    43  * processor specific atomic operations. When possible they are
    44  * implemented as true processor specific atomic operations. When that
    45  * is not possible the are implemented using locks that *do* use the
    46  * available atomic operations.
    47  *
    48  * All of the atomic operations that modify memory are full memory barriers.
    49  */
    50 
    51 #ifndef _SDL_atomic_h_
    52 #define _SDL_atomic_h_
    53 
    54 #include "SDL_stdinc.h"
    55 #include "SDL_platform.h"
    56 
    57 #include "begin_code.h"
    58 
    59 /* Set up for C function definitions, even when using C++ */
    60 #ifdef __cplusplus
    61 /* *INDENT-OFF* */
    62 extern "C" {
    63 /* *INDENT-ON* */
    64 #endif
    65 
    66 /**
    67  * \name SDL AtomicLock
    68  * 
    69  * The atomic locks are efficient spinlocks using CPU instructions,
    70  * but are vulnerable to starvation and can spin forever if a thread
    71  * holding a lock has been terminated.  For this reason you should
    72  * minimize the code executed inside an atomic lock and never do
    73  * expensive things like API or system calls while holding them.
    74  *
    75  * The atomic locks are not safe to lock recursively.
    76  *
    77  * Porting Note:
    78  * The spin lock functions and type are required and can not be
    79  * emulated because they are used in the atomic emulation code.
    80  */
    81 /*@{*/
    82 
    83 typedef int SDL_SpinLock;
    84 
    85 /**
    86  * \brief Try to lock a spin lock by setting it to a non-zero value.
    87  * 
    88  * \param lock Points to the lock.
    89  *
    90  * \return SDL_TRUE if the lock succeeded, SDL_FALSE if the lock is already held.
    91  */
    92 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock);
    93 
    94 /**
    95  * \brief Lock a spin lock by setting it to a non-zero value.
    96  * 
    97  * \param lock Points to the lock.
    98  */
    99 extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock);
   100 
   101 /**
   102  * \brief Unlock a spin lock by setting it to 0. Always returns immediately
   103  *
   104  * \param lock Points to the lock.
   105  */
   106 extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock);
   107 
   108 /*@}*//*SDL AtomicLock*/
   109 
   110 /* Platform specific optimized versions of the atomic functions */
   111 /* None yet... */
   112 
   113 /**
   114  * \brief A type representing an atomic integer value.  It is a struct
   115  *        so people don't accidentally use numeric operations on it.
   116  */
   117 #ifndef SDL_atomic_t_defined
   118 typedef struct { int value; } SDL_atomic_t;
   119 #endif
   120 
   121 /**
   122  * \brief Set an atomic variable to a value.
   123  *
   124  * \return The previous value of the atomic variable.
   125  */
   126 #ifndef SDL_AtomicSet
   127 extern DECLSPEC int SDLCALL SDL_AtomicSet(SDL_atomic_t *a, int value);
   128 #endif
   129 
   130 /**
   131  * \brief Get the value of an atomic variable
   132  */
   133 #ifndef SDL_AtomicGet
   134 extern DECLSPEC int SDLCALL SDL_AtomicGet(SDL_atomic_t *a);
   135 #endif
   136 
   137 /**
   138  * \brief  Add to an atomic variable.
   139  *
   140  * \return The previous value of the atomic variable.
   141  */
   142 #ifndef SDL_AtomicAdd
   143 extern DECLSPEC int SDLCALL SDL_AtomicAdd(SDL_atomic_t *a, int value);
   144 #endif
   145 
   146 /**
   147  * \brief Increment an atomic variable used as a reference count.
   148  */
   149 #ifndef SDL_AtomicIncRef
   150 extern DECLSPEC void SDLCALL SDL_AtomicIncRef(SDL_atomic_t *a);
   151 #endif
   152 
   153 /**
   154  * \brief Decrement an atomic variable used as a reference count.
   155  *
   156  * \return SDL_TRUE if the variable has reached zero after decrementing,
   157  *         SDL_FALSE otherwise
   158  */
   159 #ifndef SDL_AtomicDecRef
   160 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicDecRef(SDL_atomic_t *a);
   161 #endif
   162 
   163 /**
   164  * \brief Set an atomic variable to a new value if it is currently an old value.
   165  *
   166  * \return The previous value of the atomic variable
   167  *
   168  * \note If you don't know what this function is for, you shouldn't use it!
   169 */
   170 #ifndef SDL_AtomicCAS
   171 extern DECLSPEC int SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval);
   172 #endif
   173 
   174 /**
   175  * \brief Set a pointer to a value atomically.
   176  */
   177 #ifndef SDL_AtomicSetPtr
   178 extern DECLSPEC void SDLCALL SDL_AtomicSetPtr(void** a, void* value);
   179 #endif
   180 
   181 /**
   182  * \brief Get the value of a pointer atomically.
   183  */
   184 #ifndef SDL_AtomicGetPtr
   185 extern DECLSPEC void* SDLCALL SDL_AtomicGetPtr(void** a);
   186 #endif
   187 
   188 /**
   189  * \brief Set a pointer to a new value if it is currently an old value.
   190  *
   191  * \return The previous value of the pointer
   192  *
   193  * \note If you don't know what this function is for, you shouldn't use it!
   194 */
   195 #ifndef SDL_AtomicCASPtr
   196 extern DECLSPEC void* SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval);
   197 #endif
   198 
   199 /* Ends C function definitions when using C++ */
   200 #ifdef __cplusplus
   201 /* *INDENT-OFF* */
   202 }
   203 /* *INDENT-ON* */
   204 #endif
   205 
   206 #include "close_code.h"
   207 
   208 #endif /* _SDL_atomic_h_ */
   209 
   210 /* vi: set ts=4 sw=4 expandtab: */