pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plank_AtomicInline_Win_X86_32.h
00001 /*
00002  -------------------------------------------------------------------------------
00003  This file is part of the Plink, Plonk, Plank libraries
00004   by Martin Robinson
00005  
00006  http://code.google.com/p/pl-nk/
00007  
00008  Copyright University of the West of England, Bristol 2011-14
00009  All rights reserved.
00010  
00011  Redistribution and use in source and binary forms, with or without
00012  modification, are permitted provided that the following conditions are met:
00013  
00014  * Redistributions of source code must retain the above copyright
00015    notice, this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright
00017    notice, this list of conditions and the following disclaimer in the
00018    documentation and/or other materials provided with the distribution.
00019  * Neither the name of University of the West of England, Bristol nor 
00020    the names of its contributors may be used to endorse or promote products
00021    derived from this software without specific prior written permission.
00022  
00023  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00026  DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 
00027  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00028  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
00029  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00030  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00031  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
00032  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00033  
00034  This software makes use of third party libraries. For more information see:
00035  doc/license.txt included in the distribution.
00036  -------------------------------------------------------------------------------
00037  */
00038 
00039 // help prevent accidental inclusion other than via the intended header
00040 #if PLANK_INLINING_FUNCTIONS
00041 
00042 #define PLANK_ATOMIC_XBITS          32
00043 #define PLANK_ATOMIC_XREFCOUNTBITS  16
00044 #define PLANK_ATOMIC_XWEAKCOUNTBITS 16
00045 #define PLANK_ATOMIC_XREFCOUNTMAX   0x0000FFFFUL
00046 #define PLANK_ATOMIC_XREFCOUNTMASK  PLANK_ATOMIC_XREFCOUNTMAX
00047 #define PLANK_ATOMIC_XWEAKCOUNTMAX  0x0000FFFFUL
00048 #define PLANK_ATOMIC_XWEAKCOUNTMASK 0xFFFF0000UL
00049 #define PLANK_ATOMIC_XMAX           0xFFFFFFFFUL
00050 #define PLANK_ATOMIC_PMASK          0xFFFFFFFFUL
00051 
00052 #if !DOXYGEN
00053 typedef struct PlankAtomicI
00054 {
00055     volatile PlankI value;
00056 } PlankAtomicI PLANK_ALIGN(4);
00057 
00058 typedef struct PlankAtomicL
00059 {
00060     volatile PlankL value;
00061 } PlankAtomicL PLANK_ALIGN(4);
00062 
00063 typedef struct PlankAtomicLL
00064 {
00065     volatile PlankLL value;
00066 } PlankAtomicLL PLANK_ALIGN(8);
00067 
00068 typedef struct PlankAtomicF
00069 {
00070     volatile PlankF value;
00071 } PlankAtomicF PLANK_ALIGN(4);
00072 
00073 typedef struct PlankAtomicD
00074 {
00075     volatile PlankD value;
00076 } PlankAtomicD PLANK_ALIGN(8);
00077 
00078 typedef struct PlankAtomicP
00079 {
00080     volatile PlankP ptr;
00081 } PlankAtomicP PLANK_ALIGN(4);
00082 
00083 typedef struct PlankAtomicPX
00084 {
00085     volatile PlankP ptr;
00086     volatile PlankUL extra;
00087 } PlankAtomicPX PLANK_ALIGN(8);
00088 #endif
00089 
00090 static inline void pl_AtomicMemoryBarrier()
00091 {
00092         _ReadWriteBarrier();
00093 }
00094 
00095 #pragma warning(disable:4035)
00096 static inline PlankULL pl_InterlockedCompareExchange64 (volatile PlankULL *value, 
00097                                                         PlankULL newValue, 
00098                                                         PlankULL oldValue) 
00099 {
00100     //value returned in eax::edx
00101     __asm {
00102         lea esi,oldValue;
00103         lea edi,newValue;
00104         
00105         mov eax,[esi];
00106         mov edx,4[esi];
00107         mov ebx,[edi];
00108         mov ecx,4[edi];
00109         mov esi,value;
00110         lock CMPXCHG8B [esi];                   
00111     }
00112 }
00113 #pragma warning(default:4035)
00114 
00115 //------------------------------------------------------------------------------
00116 static inline PlankResult pl_AtomicI_Init (PlankAtomicIRef p)
00117 {
00118     if (p == PLANK_NULL)
00119         return PlankResult_MemoryError;
00120     
00121     pl_MemoryZero (p, sizeof (PlankAtomicI));
00122     
00123     return PlankResult_OK;
00124 }
00125 
00126 static inline PlankResult pl_AtomicI_DeInit (PlankAtomicIRef p)
00127 {
00128     if (p == PLANK_NULL)
00129         return PlankResult_MemoryError;
00130     return PlankResult_OK;
00131 }
00132 
00133 static inline PlankI pl_AtomicI_Get (PlankAtomicIRef p)
00134 {
00135     return p->value; // should be aligned anyway and volatile so OK // pl_AtomicI_Add (p, 0);
00136 }
00137 
00138 static inline PlankI pl_AtomicI_GetUnchecked (PlankAtomicIRef p)
00139 {
00140     return p->value;
00141 }
00142 
00143 static inline PlankI pl_AtomicI_Swap (PlankAtomicIRef p, PlankI newValue)
00144 {
00145     PlankI oldValue;
00146     PlankB success;
00147     
00148     do {
00149         oldValue = *(PlankI*)p;
00150         success = pl_AtomicI_CompareAndSwap (p, oldValue, newValue);
00151     } while (!success);
00152     
00153     return oldValue;
00154 }
00155 
00156 static inline void pl_AtomicI_SwapOther (PlankAtomicIRef p1, PlankAtomicIRef p2)
00157 {
00158     PlankI value1, value2;
00159     PlankB success;
00160     
00161     do {
00162         value1 = *(PlankI*)p1;
00163         value2 = *(PlankI*)p2;
00164         success = pl_AtomicI_CompareAndSwap (p1, value1, value2);
00165     } while (!success);
00166     
00167     *(PlankI*)p2 = value1;
00168 }
00169 
00170 static inline void pl_AtomicI_Set (PlankAtomicIRef p, PlankI newValue)
00171 {
00172     pl_AtomicI_Swap (p, newValue);
00173 }
00174 
00175 static inline PlankI pl_AtomicI_Add (PlankAtomicIRef p, PlankI operand)
00176 {
00177     return operand + _InterlockedExchangeAdd ((volatile long*)p, operand);
00178 }
00179 
00180 static inline PlankB  pl_AtomicI_CompareAndSwap (PlankAtomicIRef p, PlankI oldValue, PlankI newValue)
00181 {    
00182     return oldValue == _InterlockedCompareExchange ((volatile long*)p, 
00183                                                     *(long*)&newValue, 
00184                                                     *(long*)&oldValue);
00185 }
00186 
00187 static inline PlankI pl_AtomicI_Subtract (PlankAtomicIRef p, PlankI operand)
00188 {
00189     return pl_AtomicI_Add (p, -operand);
00190 }
00191 
00192 static inline PlankI pl_AtomicI_Increment (PlankAtomicIRef p)
00193 {
00194     return pl_AtomicI_Add (p, 1);
00195 }
00196 
00197 static inline PlankI pl_AtomicI_Decrement (PlankAtomicIRef p)
00198 {
00199     return pl_AtomicI_Add (p, -1);
00200 }
00201 
00202 //------------------------------------------------------------------------------
00203 static inline PlankResult pl_AtomicL_Init (PlankAtomicLRef p)
00204 {
00205     if (p == PLANK_NULL)
00206         return PlankResult_MemoryError;
00207     
00208     pl_MemoryZero (p, sizeof (PlankAtomicL));
00209     
00210     return PlankResult_OK;
00211 }
00212 
00213 static inline PlankResult pl_AtomicL_DeInit (PlankAtomicLRef p)
00214 {
00215     if (p == PLANK_NULL)
00216         return PlankResult_MemoryError;
00217     return PlankResult_OK;
00218 }
00219 
00220 static inline PlankL pl_AtomicL_Get (PlankAtomicLRef p)
00221 {
00222     return p->value; // should be aligned anyway and volatile so OK // pl_AtomicL_Add (p, (PlankL)0);
00223 }
00224 
00225 static inline PlankL pl_AtomicL_GetUnchecked (PlankAtomicLRef p)
00226 {
00227     return p->value;
00228 }
00229 
00230 static inline PlankL pl_AtomicL_Swap (PlankAtomicLRef p, PlankL newValue)
00231 {
00232     PlankL oldValue;
00233     PlankB success;
00234     
00235     do {
00236         oldValue = *(PlankL*)p;
00237         success = pl_AtomicL_CompareAndSwap (p, oldValue, newValue);
00238     } while (!success);
00239     
00240     return oldValue;
00241 }
00242 
00243 static inline void pl_AtomicL_SwapOther (PlankAtomicLRef p1, PlankAtomicLRef p2)
00244 {
00245     PlankL value1, value2;
00246     PlankB success;
00247     
00248     do {
00249         value1 = *(PlankL*)p1;
00250         value2 = *(PlankL*)p2;
00251         success = pl_AtomicL_CompareAndSwap (p1, value1, value2);
00252     } while (!success);
00253     
00254     *(PlankL*)p2 = value1;
00255 }
00256 
00257 static inline void pl_AtomicL_Set (PlankAtomicLRef p, PlankL newValue)
00258 {
00259     pl_AtomicL_Swap (p, newValue);
00260 }
00261 
00262 static inline PlankL pl_AtomicL_Add (PlankAtomicLRef p, PlankL operand)
00263 {
00264     return operand + _InterlockedExchangeAdd ((volatile long*)p, operand);
00265 }
00266 
00267 static inline PlankB  pl_AtomicL_CompareAndSwap (PlankAtomicLRef p, PlankL oldValue, PlankL newValue)
00268 {    
00269     return oldValue == _InterlockedCompareExchange ((volatile long*)p, newValue, oldValue);
00270 }
00271 
00272 static inline PlankL pl_AtomicL_Subtract (PlankAtomicLRef p, PlankL operand)
00273 {
00274     return pl_AtomicL_Add (p, -operand);
00275 }
00276 
00277 static inline PlankL pl_AtomicL_Increment (PlankAtomicLRef p)
00278 {
00279     return pl_AtomicL_Add (p, (PlankL)1);
00280 }
00281 
00282 static inline PlankL pl_AtomicL_Decrement (PlankAtomicLRef p)
00283 {
00284     return pl_AtomicL_Add (p, (PlankL)(-1));
00285 }
00286 
00287 //------------------------------------------------------------------------------
00288 
00289 static inline PlankResult pl_AtomicLL_Init (PlankAtomicLLRef p)
00290 {
00291     PlankResult result = PlankResult_OK;
00292     
00293     if (p == PLANK_NULL)
00294     {
00295         result = PlankResult_MemoryError;
00296         goto exit;
00297     }
00298     
00299     p->value = 0;
00300     
00301 exit:
00302     return result;
00303 }
00304 
00305 static inline PlankResult pl_AtomicLL_DeInit (PlankAtomicLLRef p)
00306 {
00307     PlankResult result = PlankResult_OK;
00308     
00309     if (p == PLANK_NULL)
00310     {
00311         result = PlankResult_MemoryError;
00312         goto exit;
00313     }
00314         
00315 exit:
00316     return result;
00317 }
00318 
00319 static inline PlankLL pl_AtomicLL_Get (PlankAtomicLLRef p)
00320 {
00321     return pl_AtomicLL_Add (p, (PlankLL)0);
00322 }
00323 
00324 static inline PlankLL pl_AtomicLL_GetUnchecked (PlankAtomicLLRef p)
00325 {
00326     return p->value;
00327 }
00328 
00329 static inline PlankLL pl_AtomicLL_Swap (PlankAtomicLLRef p, PlankLL newValue)
00330 {
00331     PlankLL oldValue;
00332     PlankB success;
00333     
00334     do {
00335         oldValue = *(PlankLL*)p;
00336         success = pl_AtomicLL_CompareAndSwap (p, oldValue, newValue);
00337     } while (!success);
00338     
00339     return oldValue;
00340 }
00341 
00342 static inline void pl_AtomicLL_SwapOther (PlankAtomicLLRef p1, PlankAtomicLLRef p2)
00343 {
00344     PlankLL value1, value2;
00345     PlankB success;
00346     
00347     do {
00348         value1 = *(PlankLL*)p1;
00349         value2 = *(PlankLL*)p2;
00350         success = pl_AtomicLL_CompareAndSwap (p1, value1, value2);
00351     } while (!success);
00352     
00353     *(PlankLL*)p2 = value1;
00354 }
00355 
00356 static inline void pl_AtomicLL_Set (PlankAtomicLLRef p, PlankLL newValue)
00357 {
00358     pl_AtomicLL_Swap (p, newValue);
00359 }
00360 
00361 static inline PlankLL pl_AtomicLL_Add (PlankAtomicLLRef p, PlankLL operand)
00362 {
00363     PlankLL oldValue, newValue;
00364     PlankB success;
00365     
00366     do {
00367         oldValue = *(PlankLL*)p;
00368         newValue = oldValue + operand;
00369         success = pl_AtomicLL_CompareAndSwap (p, oldValue, newValue);
00370     } while (!success);
00371     
00372     return newValue;    
00373 }
00374 
00375 static inline PlankB pl_AtomicLL_CompareAndSwap (PlankAtomicLLRef p, PlankLL oldValue, PlankLL newValue)
00376 {    
00377     return oldValue == (PlankLL)pl_InterlockedCompareExchange64 ((volatile PlankULL*)p,
00378                                                                                                                      *(PlankULL*)&newValue, 
00379                                                                                                                                  *(PlankULL*)&oldValue);
00380 }
00381 
00382 static inline PlankLL pl_AtomicLL_Subtract (PlankAtomicLLRef p, PlankLL operand)
00383 {
00384     return pl_AtomicLL_Add (p, -operand);
00385 }
00386 
00387 static inline PlankLL pl_AtomicLL_Increment (PlankAtomicLLRef p)
00388 {
00389     return pl_AtomicLL_Add (p, (PlankLL)1);
00390 }
00391 
00392 static inline PlankLL pl_AtomicLL_Decrement (PlankAtomicLLRef p)
00393 {
00394     return pl_AtomicLL_Add (p, (PlankLL)(-1));
00395 }
00396 
00397 //------------------------------------------------------------------------------
00398 
00399 static inline PlankResult pl_AtomicF_Init (PlankAtomicFRef p)
00400 {
00401     if (p == PLANK_NULL)
00402         return PlankResult_MemoryError;
00403     
00404     pl_MemoryZero (p, sizeof (PlankAtomicF));
00405     
00406     return PlankResult_OK;
00407 }
00408 
00409 static inline PlankResult pl_AtomicF_DeInit (PlankAtomicFRef p)
00410 {
00411     if (p == PLANK_NULL)
00412         return PlankResult_MemoryError;
00413     return PlankResult_OK;
00414 }
00415 
00416 static inline PlankF pl_AtomicF_Get (PlankAtomicFRef p)
00417 {    
00418     return p->value; // should be aligned anyway and volatile so OK
00419 }
00420 
00421 static inline PlankF pl_AtomicF_GetUnchecked (PlankAtomicFRef p)
00422 {
00423     return  p->value;
00424 }
00425 
00426 static inline PlankF pl_AtomicF_Swap (PlankAtomicFRef p, PlankF newValue)
00427 {
00428     PlankF oldValue;
00429     PlankB success;
00430     
00431     do
00432     {
00433         oldValue = *(PlankF*)p;
00434         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00435     } while (!success);
00436     
00437     return oldValue;
00438 }
00439 
00440 static inline void pl_AtomicF_SwapOther (PlankAtomicFRef p1, PlankAtomicFRef p2)
00441 {
00442     PlankF value1, value2;
00443     PlankB success;
00444     
00445     do {
00446         value1 = *(PlankF*)p1;
00447         value2 = *(PlankF*)p2;
00448         success = pl_AtomicF_CompareAndSwap (p1, value1, value2);
00449     } while (!success);
00450     
00451     *(PlankF*)p2 = value1;
00452 }
00453 
00454 static inline void pl_AtomicF_Set (PlankAtomicFRef p, PlankF newValue)
00455 {
00456     pl_AtomicF_Swap (p, newValue);
00457 }
00458 
00459 static inline PlankF pl_AtomicF_Add (PlankAtomicFRef p, PlankF operand)
00460 {
00461     PlankF newValue, oldValue;
00462     PlankB success;
00463     
00464     do {
00465         oldValue = *(PlankF*)p;
00466         newValue = oldValue + operand;
00467         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00468     } while (!success);
00469     
00470     return newValue;
00471 }
00472 
00473 static inline PlankB pl_AtomicF_CompareAndSwap (PlankAtomicFRef p, PlankF oldValue, PlankF newValue)
00474 {   
00475         long oldLong = *(long*)&oldValue;
00476     return oldLong == _InterlockedCompareExchange ((volatile long*)p,
00477                                                    *(long*)&newValue, 
00478                                                    oldLong);
00479 }
00480 
00481 static inline PlankF pl_AtomicF_Subtract (PlankAtomicFRef p, PlankF operand)
00482 {
00483     return pl_AtomicF_Add (p, -operand);
00484 }
00485 
00486 static inline PlankF pl_AtomicF_Increment (PlankAtomicFRef p)
00487 {
00488     return pl_AtomicF_Add (p, 1.f);
00489 }
00490 
00491 static inline PlankF pl_AtomicF_Decrement (PlankAtomicFRef p)
00492 {
00493     return pl_AtomicF_Add (p, -1.f);
00494 }
00495 
00496 //------------------------------------------------------------------------------
00497 
00498 static inline PlankResult pl_AtomicD_Init (PlankAtomicDRef p)
00499 {
00500     PlankResult result = PlankResult_OK;
00501     
00502     if (p == PLANK_NULL)
00503     {
00504         result = PlankResult_MemoryError;
00505         goto exit;
00506     }
00507     
00508     p->value = 0.0;
00509     
00510 exit:
00511     return result;
00512 }
00513 
00514 static inline PlankResult pl_AtomicD_DeInit (PlankAtomicDRef p)
00515 {
00516     PlankResult result = PlankResult_OK;
00517     
00518     if (p == PLANK_NULL)
00519     {
00520         result = PlankResult_MemoryError;
00521         goto exit;
00522     }
00523     
00524 exit:
00525     return result;
00526 }
00527 
00528 static inline PlankD pl_AtomicD_Get (PlankAtomicDRef p)
00529 {
00530     PlankLL bits = pl_AtomicLL_Add ((PlankAtomicLLRef)p, (PlankLL)0); // use the LL version
00531     return *(PlankD*)&bits;
00532 }
00533 
00534 static inline PlankD pl_AtomicD_GetUnchecked (PlankAtomicDRef p)
00535 {
00536     return p->value;
00537 }
00538 
00539 static inline PlankD pl_AtomicD_Swap (PlankAtomicDRef p, PlankD newValue)
00540 {
00541     PlankD oldValue;
00542     PlankB success;
00543     
00544     do {
00545         oldValue = *(PlankD*)p;
00546         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00547     } while (!success);
00548     
00549     return oldValue;
00550 }
00551 
00552 static inline void pl_AtomicD_SwapOther (PlankAtomicDRef p1, PlankAtomicDRef p2)
00553 {
00554     PlankD value1, value2;
00555     PlankB success;
00556     
00557     do {
00558         value1 = *(PlankD*)p1;
00559         value2 = *(PlankD*)p2;
00560         success = pl_AtomicD_CompareAndSwap (p1, value1, value2);
00561     } while (!success);
00562     
00563     *(PlankD*)p2 = value1;
00564 }
00565 
00566 static inline void pl_AtomicD_Set (PlankAtomicDRef p, PlankD newValue)
00567 {
00568     pl_AtomicD_Swap (p, newValue);
00569 }
00570 
00571 static inline PlankD pl_AtomicD_Add (PlankAtomicDRef p, PlankD operand)
00572 {
00573     PlankD newValue, oldValue;
00574     PlankB success;
00575     
00576     do {
00577         oldValue = *(PlankD*)p;
00578         newValue = oldValue + operand;
00579         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00580     } while (!success);
00581     
00582     return newValue;
00583 }
00584 
00585 inline PlankB pl_AtomicD_CompareAndSwap (PlankAtomicDRef p, PlankD oldValue, PlankD newValue)
00586 {   
00587     PlankULL oldBits = *(PlankULL*)&oldValue;
00588     return oldBits == pl_InterlockedCompareExchange64 ((volatile PlankULL*)p,
00589                                                        *(PlankULL*)&newValue, 
00590                                                        oldBits);
00591 }
00592 
00593 static inline PlankD pl_AtomicD_Subtract (PlankAtomicDRef p, PlankD operand)
00594 {
00595     return pl_AtomicD_Add (p, -operand);
00596 }
00597 
00598 static inline PlankD pl_AtomicD_Increment (PlankAtomicDRef p)
00599 {
00600     return pl_AtomicD_Add (p, 1.0);
00601 }
00602 
00603 static inline PlankD pl_AtomicD_Decrement (PlankAtomicDRef p)
00604 {
00605     return pl_AtomicD_Add (p, -1.0);
00606 }
00607 
00608 //------------------------------------------------------------------------------
00609 
00610 static inline PlankResult pl_AtomicP_Init (PlankAtomicPRef p)
00611 {
00612     if (p == PLANK_NULL)
00613         return PlankResult_MemoryError;
00614     
00615     pl_MemoryZero (p, sizeof (PlankAtomicP));
00616     
00617     return PlankResult_OK;
00618 }
00619 
00620 static inline PlankResult pl_AtomicP_DeInit (PlankAtomicPRef p)
00621 {
00622     if (p == PLANK_NULL)
00623         return PlankResult_MemoryError;
00624     return PlankResult_OK;
00625 }
00626 
00627 static inline PlankP pl_AtomicP_Get (PlankAtomicPRef p)
00628 {
00629     return p->ptr; // should be aligned anyway and volatile so OK // pl_AtomicP_Add (p, (PlankL)0);
00630 }
00631 
00632 static inline PlankP pl_AtomicP_GetUnchecked (PlankAtomicPRef p)
00633 {
00634     return p->ptr;
00635 }
00636 
00637 static inline PlankP pl_AtomicP_Swap (PlankAtomicPRef p, PlankP newPtr)
00638 {
00639     PlankP oldPtr;
00640     PlankB success;
00641     
00642     do {
00643         oldPtr = *(PlankP*)p;
00644         success = pl_AtomicP_CompareAndSwap (p, oldPtr, newPtr);
00645     } while (!success);
00646     
00647     return oldPtr;    
00648 }
00649 
00650 static inline void pl_AtomicP_SwapOther (PlankAtomicPRef p1, PlankAtomicPRef p2)
00651 {
00652     PlankP value1, value2;
00653     PlankB success;
00654     
00655     do {
00656         value1 = *(PlankP*)p1;
00657         value2 = *(PlankP*)p2;
00658         success = pl_AtomicP_CompareAndSwap (p1, value1, value2);
00659     } while (!success);
00660     
00661     *(PlankP*)p2 = value1;
00662 }
00663 
00664 static inline void pl_AtomicP_Set (PlankAtomicPRef p, PlankP newPtr)
00665 {
00666     pl_AtomicP_Swap (p, newPtr);
00667 }
00668 
00669 static inline PlankP pl_AtomicP_Add (PlankAtomicPRef p, PlankL operand)
00670 {
00671     return (PlankP)(_InterlockedExchangeAdd ((volatile long*)&p, operand) + operand);
00672 }
00673 
00674 static inline PlankB pl_AtomicP_CompareAndSwap (PlankAtomicPRef p, PlankP oldValue, PlankP newValue)
00675 {    
00676         long oldLong = *(long*)&oldValue;
00677     return oldLong == _InterlockedCompareExchange ((volatile long*)p, 
00678                                                    *(long*)&newValue, 
00679                                                    oldLong);
00680 }
00681 
00682 static inline PlankP pl_AtomicP_Subtract (PlankAtomicPRef p, PlankL operand)
00683 {
00684     return pl_AtomicP_Add (p, -operand);
00685 }
00686 
00687 static inline PlankP pl_AtomicP_Increment (PlankAtomicPRef p)
00688 {
00689     return pl_AtomicP_Add (p, (PlankL)1);
00690 }
00691 
00692 static inline PlankP pl_AtomicP_Decrement (PlankAtomicPRef p)
00693 {
00694     return pl_AtomicP_Add (p, (PlankL)(-1));
00695 }
00696 
00697 //------------------------------------------------------------------------------
00698 
00699 static inline PlankAtomicPXRef pl_AtomicPX_CreateAndInit()
00700 {
00701     PlankAtomicPXRef p = pl_AtomicPX_Create();
00702     if (p != PLANK_NULL) pl_AtomicPX_Init (p);
00703     return p;
00704 }
00705 
00706 static inline PlankAtomicPXRef pl_AtomicPX_Create()
00707 {
00708     PlankMemoryRef m;
00709     PlankAtomicPXRef p;
00710     
00711     m = pl_MemoryGlobal();
00712     p = (PlankAtomicPXRef)pl_Memory_AllocateBytes (m, sizeof (PlankAtomicPX));
00713     
00714     if (p != PLANK_NULL)
00715         pl_MemoryZero (p, sizeof (PlankAtomicPX));
00716     
00717     return p;
00718 }
00719 
00720 static inline PlankResult pl_AtomicPX_Init (PlankAtomicPXRef p)
00721 {
00722     PlankResult result = PlankResult_OK;
00723     
00724     if (p == PLANK_NULL)
00725     {
00726         result = PlankResult_MemoryError;
00727         goto exit;
00728     }
00729 
00730     pl_MemoryZero (p, sizeof (PlankAtomicPX));
00731     
00732 exit:
00733     return result;
00734 }
00735 
00736 static inline PlankResult pl_AtomicPX_DeInit (PlankAtomicPXRef p)
00737 {
00738     PlankResult result = PlankResult_OK;
00739     
00740     if (p == PLANK_NULL)
00741     {
00742         result = PlankResult_MemoryError;
00743         goto exit;
00744     }
00745         
00746 exit:
00747     return result;
00748 }
00749 
00750 static inline PlankResult pl_AtomicPX_Destroy (PlankAtomicPXRef p)
00751 {
00752     PlankResult result;
00753     PlankMemoryRef m;
00754     
00755     result = PlankResult_OK;
00756     m = pl_MemoryGlobal();
00757     
00758     if ((result = pl_AtomicPX_DeInit (p)) != PlankResult_OK)
00759         goto exit;
00760     
00761     result = pl_Memory_Free (m, p);
00762     
00763 exit:
00764     return result;
00765 }
00766 
00767 static inline PlankP pl_AtomicPX_Get (PlankAtomicPXRef p)
00768 {
00769     return p->ptr; // should be aligned anyway and volatile so OK // pl_AtomicP_Get ((PlankAtomicPRef)p);
00770 }
00771 
00772 static inline PlankP pl_AtomicPX_GetUnchecked (PlankAtomicPXRef p)
00773 {
00774     return p->ptr;
00775 }
00776 
00777 static inline PlankUL pl_AtomicPX_GetExtra (PlankAtomicPXRef p)
00778 {
00779     return p->extra; // should be aligned anyway and volatile so OK // pl_AtomicL_Get ((PlankAtomicLRef)&(p->extra));
00780 }
00781 
00782 static inline PlankUL pl_AtomicPX_GetExtraUnchecked (PlankAtomicPXRef p)
00783 {
00784     return p->extra;
00785 }
00786 
00787 static inline PlankP pl_AtomicPX_SwapAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra, PlankUL* oldExtraPtr)
00788 {
00789     PlankP oldPtr;
00790     PlankUL oldExtra;
00791     PlankB success;
00792     
00793     do {
00794         oldPtr = p->ptr;
00795         oldExtra = p->extra;
00796         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, newExtra);
00797     } while (!success);
00798     
00799     if (oldExtraPtr != PLANK_NULL)
00800         *oldExtraPtr = oldExtra;
00801     
00802     return oldPtr;
00803 }
00804 
00805 static inline PlankP pl_AtomicPX_Swap (PlankAtomicPXRef p, PlankP newPtr)
00806 {
00807     PlankP oldPtr;
00808     PlankUL oldExtra;
00809     PlankB success;
00810     
00811     do {
00812         oldPtr = p->ptr;
00813         oldExtra = p->extra;
00814         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00815     } while (!success);
00816     
00817     return oldPtr;
00818 }
00819 
00820 static inline void pl_AtomicPX_SwapOther (PlankAtomicPXRef p1, PlankAtomicPXRef p2)
00821 {
00822     PlankAtomicPX tmp1, tmp2;
00823     PlankB success;
00824     
00825     do {
00826         tmp1 = *p1;
00827         tmp2 = *p2;
00828         success = pl_AtomicPX_CompareAndSwap (p1, tmp1.ptr, tmp1.extra, tmp2.ptr, tmp1.extra + 1);
00829     } while (!success);
00830     
00831     pl_AtomicPX_Set (p2, tmp1.ptr);
00832 }
00833 
00834 static inline void pl_AtomicPX_SetAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00835 {
00836     pl_AtomicPX_SwapAll (p, newPtr, newExtra, (PlankUL*)PLANK_NULL);
00837 }
00838 
00839 static inline void pl_AtomicPX_Set (PlankAtomicPXRef p, PlankP newPtr)
00840 {
00841     PlankP oldPtr;
00842     PlankUL oldExtra;
00843     PlankB success;
00844     
00845     do {
00846         oldPtr = p->ptr;
00847         oldExtra = p->extra;
00848         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00849     } while (!success);
00850 }
00851 
00852 static inline PlankP pl_AtomicPX_Add (PlankAtomicPXRef p, PlankL operand)
00853 {
00854     PlankP newPtr, oldPtr;
00855     PlankUL oldExtra;
00856     PlankB success;
00857     
00858     do {
00859         oldPtr = p->ptr;
00860         oldExtra = p->extra;
00861         newPtr = (PlankUC*)oldPtr + operand;
00862         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00863     } while (!success);
00864     
00865     return newPtr;
00866 }
00867 
00868 static inline PlankP pl_AtomicPX_Subtract (PlankAtomicPXRef p, PlankL operand)
00869 {
00870     return pl_AtomicPX_Add (p, -operand);
00871 }
00872 
00873 static inline PlankP pl_AtomicPX_Increment (PlankAtomicPXRef p)
00874 {
00875     return pl_AtomicPX_Add (p, (PlankL)1);
00876 }
00877 
00878 static inline PlankP pl_AtomicPX_Decrement (PlankAtomicPXRef p)
00879 {
00880     return pl_AtomicPX_Add (p, (PlankL)(-1));
00881 }
00882 
00883 static inline PlankB pl_AtomicPX_CompareAndSwap (PlankAtomicPXRef p, PlankP oldPtr, PlankUL oldExtra, PlankP newPtr, PlankL newExtra)
00884 {
00885     // can't use static init as MSVC C is C89
00886     PlankAtomicPX oldAll;
00887     PlankAtomicPX newAll;
00888     PlankULL oldAllValue;
00889     PlankULL newAllValue;
00890     
00891         oldAll.ptr   = oldPtr;
00892         oldAll.extra = oldExtra;
00893         newAll.ptr   = newPtr;
00894         newAll.extra = newExtra;
00895     oldAllValue  = *(PlankULL*)&oldAll;
00896         newAllValue  = *(PlankULL*)&newAll;
00897     
00898         return oldAllValue == pl_InterlockedCompareExchange64 ((volatile PlankULL*)p, newAllValue, oldAllValue);
00899 }
00900 
00901 static inline PlankB pl_AtomicPX_CompareAndSwapP (PlankAtomicPXRef p, PlankP oldPtr, PlankP newPtr)
00902 {
00903     return pl_AtomicP_CompareAndSwap ((PlankAtomicPRef)p, oldPtr, newPtr);
00904 }
00905 
00906 static inline void pl_AtomicPX_SetAllUnchecked (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00907 {
00908     p->ptr = newPtr;
00909     p->extra = newExtra;
00910 }
00911 
00912 #define PLANK_ATOMICS_DEFINED 1
00913 
00914 #endif // PLANK_INLINING_FUNCTIONS
00915 
 All Classes Functions Typedefs Enumerations Enumerator Properties