pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plank_AtomicInline_Mac_PPC_64.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          64
00043 #define PLANK_ATOMIC_XREFCOUNTBITS  32
00044 #define PLANK_ATOMIC_XWEAKCOUNTBITS 32
00045 #define PLANK_ATOMIC_XREFCOUNTMAX   0x00000000FFFFFFFFUL
00046 #define PLANK_ATOMIC_XREFCOUNTMASK  PLANK_ATOMIC_XREFCOUNTMAX
00047 #define PLANK_ATOMIC_XWEAKCOUNTMAX  0x00000000FFFFFFFFUL
00048 #define PLANK_ATOMIC_XWEAKCOUNTMASK 0xFFFFFFFF00000000UL
00049 #define PLANK_ATOMIC_XMAX           0xFFFFFFFFFFFFFFFFUL
00050 #define PLANK_ATOMIC_PMASK          0xFFFFFFFFFFFFFFFFUL
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(8);
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(8);
00082 
00083 typedef struct PlankAtomicPX
00084 {
00085     volatile PlankP ptr;
00086     volatile PlankUL extra;
00087     PlankThreadSpinLock lock;
00088 } PlankAtomicPX PLANK_ALIGN(16);
00089 #endif
00090 
00091 static inline void pl_AtomicMemoryBarrier()
00092 {
00093     OSMemoryBarrier();
00094 }
00095 
00096 //------------------------------------------------------------------------------
00097 static inline PlankResult pl_AtomicI_Init (PlankAtomicIRef p)
00098 {
00099     if (p == PLANK_NULL)
00100         return PlankResult_MemoryError;
00101     
00102     pl_MemoryZero (p, sizeof (PlankAtomicI));
00103     
00104     return PlankResult_OK;
00105 }
00106 
00107 static inline PlankResult pl_AtomicI_DeInit (PlankAtomicIRef p)
00108 {
00109     if (p == PLANK_NULL)
00110         return PlankResult_MemoryError;
00111     return PlankResult_OK;
00112 }
00113 
00114 static inline PlankI pl_AtomicI_Get (PlankAtomicIRef p)
00115 {
00116     return p->value; // should be aligned anyway and volatile so OK // pl_AtomicI_Add (p, 0);
00117 }
00118 
00119 static inline PlankI pl_AtomicI_GetUnchecked (PlankAtomicIRef p)
00120 {
00121     return p->value;
00122 }
00123 
00124 static inline PlankI pl_AtomicI_Swap (PlankAtomicIRef p, PlankI newValue)
00125 {
00126     PlankI oldValue;
00127     PlankB success;
00128     
00129     do {
00130         oldValue = *(PlankI*)p;
00131         success = pl_AtomicI_CompareAndSwap (p, oldValue, newValue);
00132     } while (!success);
00133     
00134     return oldValue;
00135 }
00136 
00137 static inline void pl_AtomicI_SwapOther (PlankAtomicIRef p1, PlankAtomicIRef p2)
00138 {
00139     PlankI value1, value2;
00140     PlankB success;
00141     
00142     do {
00143         value1 = *(PlankI*)p1;
00144         value2 = *(PlankI*)p2;
00145         success = pl_AtomicI_CompareAndSwap (p1, value1, value2);
00146     } while (!success);
00147     
00148     *(PlankI*)p2 = value1;
00149 }
00150 
00151 static inline void pl_AtomicI_Set (PlankAtomicIRef p, PlankI newValue)
00152 {
00153     pl_AtomicI_Swap (p, newValue);
00154 }
00155 
00156 static inline PlankI pl_AtomicI_Add (PlankAtomicIRef p, PlankI operand)
00157 {
00158     return OSAtomicAdd32Barrier (*(int32_t*)&operand, 
00159                                  (volatile int32_t*)p);
00160 }
00161 
00162 static inline PlankB  pl_AtomicI_CompareAndSwap (PlankAtomicIRef p, PlankI oldValue, PlankI newValue)
00163 {    
00164     return OSAtomicCompareAndSwap32Barrier (*(int32_t*)&oldValue, 
00165                                             *(int32_t*)&newValue, 
00166                                             (volatile int32_t*)p);
00167 }
00168 
00169 static inline PlankI pl_AtomicI_Subtract (PlankAtomicIRef p, PlankI operand)
00170 {
00171     return pl_AtomicI_Add (p, -operand);
00172 }
00173 
00174 static inline PlankI pl_AtomicI_Increment (PlankAtomicIRef p)
00175 {
00176     return pl_AtomicI_Add (p, 1);
00177 }
00178 
00179 static inline PlankI pl_AtomicI_Decrement (PlankAtomicIRef p)
00180 {
00181     return pl_AtomicI_Add (p, -1);
00182 }
00183 
00184 //------------------------------------------------------------------------------
00185 static inline PlankResult pl_AtomicL_Init (PlankAtomicLRef p)
00186 {
00187     if (p == PLANK_NULL)
00188         return PlankResult_MemoryError;
00189     
00190     pl_MemoryZero (p, sizeof (PlankAtomicL));
00191     
00192     return PlankResult_OK;
00193 }
00194 
00195 static inline PlankResult pl_AtomicL_DeInit (PlankAtomicLRef p)
00196 {
00197     if (p == PLANK_NULL)
00198         return PlankResult_MemoryError;
00199     return PlankResult_OK;
00200 }
00201 
00202 static inline PlankL pl_AtomicL_Get (PlankAtomicLRef p)
00203 {
00204     return p->value; // should be aligned anyway and volatile so OK // pl_AtomicL_Add (p, (PlankL)0);
00205 }
00206 
00207 static inline PlankL pl_AtomicL_GetUnchecked (PlankAtomicLRef p)
00208 {
00209     return p->value;
00210 }
00211 
00212 static inline PlankL pl_AtomicL_Swap (PlankAtomicLRef p, PlankL newValue)
00213 {
00214     PlankL oldValue;
00215     PlankB success;
00216     
00217     do {
00218         oldValue = *(PlankL*)p;
00219         success = pl_AtomicL_CompareAndSwap (p, oldValue, newValue);
00220     } while (!success);
00221     
00222     return oldValue;
00223 }
00224 
00225 static inline void pl_AtomicL_SwapOther (PlankAtomicLRef p1, PlankAtomicLRef p2)
00226 {
00227     PlankL value1, value2;
00228     PlankB success;
00229     
00230     do {
00231         value1 = *(PlankL*)p1;
00232         value2 = *(PlankL*)p2;
00233         success = pl_AtomicL_CompareAndSwap (p1, value1, value2);
00234     } while (!success);
00235     
00236     *(PlankL*)p2 = value1;
00237 }
00238 
00239 static inline void pl_AtomicL_Set (PlankAtomicLRef p, PlankL newValue)
00240 {
00241     pl_AtomicL_Swap (p, newValue);
00242 }
00243 
00244 static inline PlankL pl_AtomicL_Add (PlankAtomicLRef p, PlankL operand)
00245 {
00246     return OSAtomicAdd64Barrier (*(int64_t*)&operand, 
00247                                  (volatile int64_t*)p);
00248 }
00249 
00250 static inline PlankB  pl_AtomicL_CompareAndSwap (PlankAtomicLRef p, PlankL oldValue, PlankL newValue)
00251 {    
00252     return OSAtomicCompareAndSwap64Barrier (*(int64_t*)&oldValue, 
00253                                             *(int64_t*)&newValue, 
00254                                             (volatile int64_t*)p);
00255 }
00256 
00257 static inline PlankL pl_AtomicL_Subtract (PlankAtomicLRef p, PlankL operand)
00258 {
00259     return pl_AtomicL_Add (p, -operand);
00260 }
00261 
00262 static inline PlankL pl_AtomicL_Increment (PlankAtomicLRef p)
00263 {
00264     return pl_AtomicL_Add (p, (PlankL)1);
00265 }
00266 
00267 static inline PlankL pl_AtomicL_Decrement (PlankAtomicLRef p)
00268 {
00269     return pl_AtomicL_Add (p, (PlankL)(-1));
00270 }
00271 
00272 //------------------------------------------------------------------------------
00273 
00274 static inline PlankResult pl_AtomicLL_Init (PlankAtomicLLRef p)
00275 {
00276     PlankResult result = PlankResult_OK;
00277     
00278     if (p == PLANK_NULL)
00279     {
00280         result = PlankResult_MemoryError;
00281         goto exit;
00282     }
00283     
00284     pl_MemoryZero (p, sizeof (PlankAtomicLL));
00285     
00286 exit:
00287     return result;
00288 }
00289 
00290 static inline PlankResult pl_AtomicLL_DeInit (PlankAtomicLLRef p)
00291 {
00292     PlankResult result = PlankResult_OK;
00293     
00294     if (p == PLANK_NULL)
00295     {
00296         result = PlankResult_MemoryError;
00297         goto exit;
00298     }
00299     
00300 exit:
00301     return result;
00302 }
00303 
00304 static inline PlankLL pl_AtomicLL_Get (PlankAtomicLLRef p)
00305 {
00306     return p->value; // should be aligned anyway and volatile so OK
00307 }
00308 
00309 static inline PlankLL pl_AtomicLL_GetUnchecked (PlankAtomicLLRef p)
00310 {
00311     return p->value;
00312 }
00313 
00314 static inline PlankLL pl_AtomicLL_Swap (PlankAtomicLLRef p, PlankLL newValue)
00315 {
00316     PlankLL oldValue;
00317     PlankB success;
00318     
00319     do {
00320         oldValue = *(PlankLL*)p;
00321         success = pl_AtomicLL_CompareAndSwap (p, oldValue, newValue);
00322     } while (!success);
00323     
00324     return oldValue;
00325 }
00326 
00327 static inline void pl_AtomicLL_SwapOther (PlankAtomicLLRef p1, PlankAtomicLLRef p2)
00328 {
00329     PlankLL value1, value2;
00330     PlankB success;
00331     
00332     do {
00333         value1 = *(PlankLL*)p1;
00334         value2 = *(PlankLL*)p2;
00335         success = pl_AtomicLL_CompareAndSwap (p1, value1, value2);
00336     } while (!success);
00337     
00338     *(PlankLL*)p2 = value1;
00339 }
00340 
00341 static inline void pl_AtomicLL_Set (PlankAtomicLLRef p, PlankLL newValue)
00342 {
00343     pl_AtomicLL_Swap (p, newValue);
00344 }
00345 
00346 static inline PlankLL pl_AtomicLL_Add (PlankAtomicLLRef p, PlankLL operand)
00347 {
00348     return OSAtomicAdd64Barrier (*(int64_t*)&operand, 
00349                                  (volatile int64_t*)p);
00350 }
00351 
00352 static inline PlankB pl_AtomicLL_CompareAndSwap (PlankAtomicLLRef p, PlankLL oldValue, PlankLL newValue)
00353 {    
00354     return OSAtomicCompareAndSwap64Barrier (*(int64_t*)&oldValue, 
00355                                             *(int64_t*)&newValue, 
00356                                             (volatile int64_t*)p);
00357 }
00358 
00359 static inline PlankLL pl_AtomicLL_Subtract (PlankAtomicLLRef p, PlankLL operand)
00360 {
00361     return pl_AtomicLL_Add (p, -operand);
00362 }
00363 
00364 static inline PlankLL pl_AtomicLL_Increment (PlankAtomicLLRef p)
00365 {
00366     return pl_AtomicLL_Add (p, (PlankLL)1);
00367 }
00368 
00369 static inline PlankLL pl_AtomicLL_Decrement (PlankAtomicLLRef p)
00370 {
00371     return pl_AtomicLL_Add (p, (PlankLL)(-1));
00372 }
00373 
00374 //------------------------------------------------------------------------------
00375 
00376 static inline PlankResult pl_AtomicF_Init (PlankAtomicFRef p)
00377 {
00378     if (p == PLANK_NULL)
00379         return PlankResult_MemoryError;
00380     
00381     pl_MemoryZero (p, sizeof (PlankAtomicF));
00382     
00383     return PlankResult_OK;
00384 }
00385 
00386 static inline PlankResult pl_AtomicF_DeInit (PlankAtomicFRef p)
00387 {
00388     if (p == PLANK_NULL)
00389         return PlankResult_MemoryError;
00390     return PlankResult_OK;
00391 }
00392 
00393 static inline PlankF pl_AtomicF_Get (PlankAtomicFRef p)
00394 {
00395     return p->value; // should be aligned anyway and volatile so OK
00396 }
00397 
00398 static inline PlankF pl_AtomicF_GetUnchecked (PlankAtomicFRef p)
00399 {
00400     return  p->value;
00401 }
00402 
00403 static inline PlankF pl_AtomicF_Swap (PlankAtomicFRef p, PlankF newValue)
00404 {
00405     PlankF oldValue;
00406     PlankB success;
00407     
00408     do
00409     {
00410         oldValue = *(PlankF*)p;
00411         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00412     } while (!success);
00413     
00414     return oldValue;
00415 }
00416 
00417 static inline void pl_AtomicF_SwapOther (PlankAtomicFRef p1, PlankAtomicFRef p2)
00418 {
00419     PlankF value1, value2;
00420     PlankB success;
00421     
00422     do {
00423         value1 = *(PlankF*)p1;
00424         value2 = *(PlankF*)p2;
00425         success = pl_AtomicF_CompareAndSwap (p1, value1, value2);
00426     } while (!success);
00427     
00428     *(PlankF*)p2 = value1;
00429 }
00430 
00431 static inline void pl_AtomicF_Set (PlankAtomicFRef p, PlankF newValue)
00432 {
00433     pl_AtomicF_Swap (p, newValue);
00434 }
00435 
00436 static inline PlankF pl_AtomicF_Add (PlankAtomicFRef p, PlankF operand)
00437 {
00438     PlankF newValue, oldValue;
00439     PlankB success;
00440     
00441     do {
00442         oldValue = *(PlankF*)p;
00443         newValue = oldValue + operand;
00444         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00445     } while (!success);
00446     
00447     return newValue;
00448 }
00449 
00450 static inline PlankB pl_AtomicF_CompareAndSwap (PlankAtomicFRef p, PlankF oldValue, PlankF newValue)
00451 {    
00452     return OSAtomicCompareAndSwap32Barrier (*(int32_t*)&oldValue, 
00453                                             *(int32_t*)&newValue, 
00454                                             (volatile int32_t*)p);
00455 }
00456 
00457 static inline PlankF pl_AtomicF_Subtract (PlankAtomicFRef p, PlankF operand)
00458 {
00459     return pl_AtomicF_Add (p, -operand);
00460 }
00461 
00462 static inline PlankF pl_AtomicF_Increment (PlankAtomicFRef p)
00463 {
00464     return pl_AtomicF_Add (p, 1.f);
00465 }
00466 
00467 static inline PlankF pl_AtomicF_Decrement (PlankAtomicFRef p)
00468 {
00469     return pl_AtomicF_Add (p, -1.f);
00470 }
00471 
00472 //------------------------------------------------------------------------------
00473 
00474 static inline PlankResult pl_AtomicD_Init (PlankAtomicDRef p)
00475 {
00476     PlankResult result = PlankResult_OK;
00477     
00478     if (p == PLANK_NULL)
00479     {
00480         result = PlankResult_MemoryError;
00481         goto exit;
00482     }
00483     
00484     pl_MemoryZero (p, sizeof (PlankAtomicD));
00485     
00486 exit:
00487     return result;
00488 }
00489 
00490 static inline PlankResult pl_AtomicD_DeInit (PlankAtomicDRef p)
00491 {
00492     PlankResult result = PlankResult_OK;
00493     
00494     if (p == PLANK_NULL)
00495     {
00496         result = PlankResult_MemoryError;
00497         goto exit;
00498     }
00499     
00500 exit:
00501     return result;
00502 }
00503 
00504 static inline PlankD pl_AtomicD_Get (PlankAtomicDRef p)
00505 {
00506     return p->value; // should be aligned anyway and volatile so OK
00507 }
00508 
00509 static inline PlankD pl_AtomicD_GetUnchecked (PlankAtomicDRef p)
00510 {
00511     return p->value;
00512 }
00513 
00514 static inline PlankD pl_AtomicD_Swap (PlankAtomicDRef p, PlankD newValue)
00515 {
00516     PlankD oldValue;
00517     PlankB success;
00518     
00519     do {
00520         oldValue = *(PlankD*)p;
00521         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00522     } while (!success);
00523     
00524     return oldValue;
00525 }
00526 
00527 static inline void pl_AtomicD_SwapOther (PlankAtomicDRef p1, PlankAtomicDRef p2)
00528 {
00529     PlankD value1, value2;
00530     PlankB success;
00531     
00532     do {
00533         value1 = *(PlankD*)p1;
00534         value2 = *(PlankD*)p2;
00535         success = pl_AtomicD_CompareAndSwap (p1, value1, value2);
00536     } while (!success);
00537     
00538     *(PlankD*)p2 = value1;
00539 }
00540 
00541 static inline void pl_AtomicD_Set (PlankAtomicDRef p, PlankD newValue)
00542 {
00543     pl_AtomicD_Swap (p, newValue);
00544 }
00545 
00546 static inline PlankD pl_AtomicD_Add (PlankAtomicDRef p, PlankD operand)
00547 {
00548     PlankD newValue, oldValue;
00549     PlankB success;
00550     
00551     do {
00552         oldValue = *(PlankD*)p;
00553         newValue = oldValue + operand;
00554         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00555     } while (!success);
00556     
00557     return newValue;
00558 }
00559 
00560 static inline PlankB pl_AtomicD_CompareAndSwap (PlankAtomicDRef p, PlankD oldValue, PlankD newValue)
00561 {    
00562     return OSAtomicCompareAndSwap64Barrier (*(int64_t*)&oldValue, 
00563                                             *(int64_t*)&newValue, 
00564                                             (volatile int64_t*)p);
00565 }
00566 
00567 static inline PlankD pl_AtomicD_Subtract (PlankAtomicDRef p, PlankD operand)
00568 {
00569     return pl_AtomicD_Add (p, -operand);
00570 }
00571 
00572 static inline PlankD pl_AtomicD_Increment (PlankAtomicDRef p)
00573 {
00574     return pl_AtomicD_Add (p, 1.0);
00575 }
00576 
00577 static inline PlankD pl_AtomicD_Decrement (PlankAtomicDRef p)
00578 {
00579     return pl_AtomicD_Add (p, -1.0);
00580 }
00581 
00582 //------------------------------------------------------------------------------
00583 
00584 static inline PlankResult pl_AtomicP_Init (PlankAtomicPRef p)
00585 {
00586     if (p == PLANK_NULL)
00587         return PlankResult_MemoryError;
00588     
00589     pl_MemoryZero (p, sizeof (PlankAtomicP));
00590     
00591     return PlankResult_OK;
00592 }
00593 
00594 static inline PlankResult pl_AtomicP_DeInit (PlankAtomicPRef p)
00595 {
00596     if (p == PLANK_NULL)
00597         return PlankResult_MemoryError;
00598     return PlankResult_OK;
00599 }
00600 
00601 static inline PlankP pl_AtomicP_Get (PlankAtomicPRef p)
00602 {
00603     return p->ptr; // should be aligned anyway and volatile so OK // pl_AtomicP_Add (p, (PlankL)0);
00604 }
00605 
00606 static inline PlankP pl_AtomicP_GetUnchecked (PlankAtomicPRef p)
00607 {
00608     return p->ptr;
00609 }
00610 
00611 static inline PlankP pl_AtomicP_Swap (PlankAtomicPRef p, PlankP newPtr)
00612 {
00613     PlankP oldPtr;
00614     PlankB success;
00615     
00616     do {
00617         oldPtr = *(PlankP*)p;
00618         success = pl_AtomicP_CompareAndSwap (p, oldPtr, newPtr);
00619     } while (!success);
00620     
00621     return oldPtr;    
00622 }
00623 
00624 static inline void pl_AtomicP_SwapOther (PlankAtomicPRef p1, PlankAtomicPRef p2)
00625 {
00626     PlankP value1, value2;
00627     PlankB success;
00628     
00629     do {
00630         value1 = *(PlankP*)p1;
00631         value2 = *(PlankP*)p2;
00632         success = pl_AtomicP_CompareAndSwap (p1, value1, value2);
00633     } while (!success);
00634     
00635     *(PlankP*)p2 = value1;
00636 }
00637 
00638 static inline void pl_AtomicP_Set (PlankAtomicPRef p, PlankP newPtr)
00639 {
00640     pl_AtomicP_Swap (p, newPtr);
00641 }
00642 
00643 static inline PlankP pl_AtomicP_Add (PlankAtomicPRef p, PlankL operand)
00644 {
00645     return (PlankP)OSAtomicAdd64Barrier (*(int64_t*)&operand, (volatile int64_t*)p);
00646 }
00647 
00648 static inline PlankB pl_AtomicP_CompareAndSwap (PlankAtomicPRef p, PlankP oldValue, PlankP newValue)
00649 {
00650     return OSAtomicCompareAndSwap64Barrier (*(int64_t*)&oldValue, 
00651                                             *(int64_t*)&newValue, 
00652                                             (volatile int64_t*)p);
00653 }
00654 
00655 static inline PlankP pl_AtomicP_Subtract (PlankAtomicPRef p, PlankL operand)
00656 {
00657     return pl_AtomicP_Add (p, -operand);
00658 }
00659 
00660 static inline PlankP pl_AtomicP_Increment (PlankAtomicPRef p)
00661 {
00662     return pl_AtomicP_Add (p, (PlankL)1);
00663 }
00664 
00665 static inline PlankP pl_AtomicP_Decrement (PlankAtomicPRef p)
00666 {
00667     return pl_AtomicP_Add (p, (PlankL)(-1));
00668 }
00669 
00670 //------------------------------------------------------------------------------
00671 
00672 static inline PlankAtomicPXRef pl_AtomicPX_CreateAndInit()
00673 {
00674     PlankAtomicPXRef p = pl_AtomicPX_Create();
00675     if (p != PLANK_NULL) pl_AtomicPX_Init (p);
00676     return p;
00677 }
00678 
00679 static inline PlankAtomicPXRef pl_AtomicPX_Create()
00680 {
00681     PlankMemoryRef m;
00682     PlankAtomicPXRef p;
00683     
00684     m = pl_MemoryGlobal();
00685     p = (PlankAtomicPXRef)pl_Memory_AllocateBytes (m, sizeof (PlankAtomicPX));
00686     
00687     if (p != PLANK_NULL)
00688         pl_MemoryZero (p, sizeof (PlankAtomicPX));
00689     
00690     return p;
00691 }
00692 
00693 static inline PlankResult pl_AtomicPX_Init (PlankAtomicPXRef p)
00694 {
00695     PlankResult result = PlankResult_OK;
00696     
00697     if (p == PLANK_NULL)
00698     {
00699         result = PlankResult_MemoryError;
00700         goto exit;
00701     }
00702     
00703     pl_MemoryZero (p, sizeof (PlankAtomicPX));
00704     
00705 exit:
00706     return result;
00707 }
00708 
00709 static inline PlankResult pl_AtomicPX_DeInit (PlankAtomicPXRef p)
00710 {
00711     PlankResult result = PlankResult_OK;
00712     
00713     if (p == PLANK_NULL)
00714     {
00715         result = PlankResult_MemoryError;
00716         goto exit;
00717     }
00718         
00719 exit:
00720     return result;
00721 }
00722 
00723 static inline PlankResult pl_AtomicPX_Destroy (PlankAtomicPXRef p)
00724 {
00725     PlankResult result;
00726     PlankMemoryRef m;
00727     
00728     result = PlankResult_OK;
00729     m = pl_MemoryGlobal();
00730     
00731     if ((result = pl_AtomicPX_DeInit (p)) != PlankResult_OK)
00732         goto exit;
00733     
00734     result = pl_Memory_Free (m, p);
00735     
00736 exit:
00737     return result;
00738 }
00739 
00740 static inline PlankP pl_AtomicPX_Get (PlankAtomicPXRef p)
00741 {
00742     return p->ptr; // should be aligned anyway and volatile so OK // pl_AtomicP_Get ((PlankAtomicPRef)p);
00743 }
00744 
00745 static inline PlankP pl_AtomicPX_GetUnchecked (PlankAtomicPXRef p)
00746 {
00747     return p->ptr;
00748 }
00749 
00750 static inline PlankUL pl_AtomicPX_GetExtra (PlankAtomicPXRef p)
00751 {
00752     return p->extra; // should be aligned anyway and volatile so OK // pl_AtomicL_Get ((PlankAtomicLRef)&(p->extra));
00753 }
00754 
00755 static inline PlankUL pl_AtomicPX_GetExtraUnchecked (PlankAtomicPXRef p)
00756 {
00757     return p->extra;
00758 }
00759 
00760 static inline PlankP pl_AtomicPX_SwapAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra, PlankUL* oldExtraPtr)
00761 {
00762     PlankP oldPtr;
00763     PlankUL oldExtra;
00764     PlankB success;
00765     
00766     do {
00767         oldPtr = p->ptr;
00768         oldExtra = p->extra;
00769         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, newExtra);
00770     } while (!success);
00771     
00772     if (oldExtraPtr != PLANK_NULL)
00773         *oldExtraPtr = oldExtra;
00774     
00775     return oldPtr;
00776 }
00777 
00778 static inline PlankP pl_AtomicPX_Swap (PlankAtomicPXRef p, PlankP newPtr)
00779 {
00780     PlankP oldPtr;
00781     PlankUL oldExtra;
00782     PlankB success;
00783     
00784     do {
00785         oldPtr = p->ptr;
00786         oldExtra = p->extra;
00787         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00788     } while (!success);
00789     
00790     return oldPtr;
00791 }
00792 
00793 static inline void pl_AtomicPX_SwapOther (PlankAtomicPXRef p1, PlankAtomicPXRef p2)
00794 {
00795     PlankAtomicPX tmp1, tmp2;
00796     PlankB success;
00797     
00798     do {
00799         tmp1 = *p1;
00800         tmp2 = *p2;
00801         success = pl_AtomicPX_CompareAndSwap (p1, tmp1.ptr, tmp1.extra, tmp2.ptr, tmp1.extra + 1);
00802     } while (!success);
00803     
00804     pl_AtomicPX_Set (p2, tmp1.ptr);
00805 }
00806 
00807 static inline void pl_AtomicPX_SetAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00808 {
00809     pl_AtomicPX_SwapAll (p, newPtr, newExtra, (PlankUL*)PLANK_NULL);
00810 }
00811 
00812 static inline void pl_AtomicPX_Set (PlankAtomicPXRef p, PlankP newPtr)
00813 {
00814     PlankP oldPtr;
00815     PlankUL oldExtra;
00816     PlankB success;
00817     
00818     do {
00819         oldPtr = p->ptr;
00820         oldExtra = p->extra;
00821         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00822     } while (!success);
00823 }
00824 
00825 static inline PlankP pl_AtomicPX_Add (PlankAtomicPXRef p, PlankL operand)
00826 {
00827     PlankP newPtr, oldPtr;
00828     PlankUL oldExtra;
00829     PlankB success;
00830     
00831     do {
00832         oldPtr = p->ptr;
00833         oldExtra = p->extra;
00834         newPtr = (PlankUC*)oldPtr + operand;
00835         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00836     } while (!success);
00837     
00838     return newPtr;
00839 }
00840 
00841 static inline PlankP pl_AtomicPX_Subtract (PlankAtomicPXRef p, PlankL operand)
00842 {
00843     return pl_AtomicPX_Add (p, -operand);
00844 }
00845 
00846 static inline PlankP pl_AtomicPX_Increment (PlankAtomicPXRef p)
00847 {
00848     return pl_AtomicPX_Add (p, (PlankL)1);
00849 }
00850 
00851 static inline PlankP pl_AtomicPX_Decrement (PlankAtomicPXRef p)
00852 {
00853     return pl_AtomicPX_Add (p, (PlankL)(-1));
00854 }
00855 
00856 static inline  PlankB pl_AtomicPX_CompareAndSwap (PlankAtomicPXRef p, PlankP oldPtr, PlankUL oldExtra, PlankP newPtr, PlankUL newExtra)
00857 {
00858     if (! pl_ThreadSpinLock_TryLock (&p->lock))
00859         return PLANK_FALSE;
00860     
00861     if ((p->ptr != oldPtr) || (p->extra != oldExtra))
00862     {
00863         pl_ThreadSpinLock_Unlock (&p->lock);
00864         return PLANK_FALSE;
00865     }
00866     
00867     p->ptr = newPtr;
00868     p->extra = newExtra;
00869     pl_ThreadSpinLock_Unlock (&p->lock);
00870     
00871     return PLANK_TRUE;
00872 }
00873 
00874 static inline PlankB pl_AtomicPX_CompareAndSwapP (PlankAtomicPXRef p, PlankP oldPtr, PlankP newPtr)
00875 {
00876     return pl_AtomicP_CompareAndSwap ((PlankAtomicPRef)p, oldPtr, newPtr);
00877 }
00878 
00879 static inline void pl_AtomicPX_SetAllUnchecked (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00880 {
00881     p->ptr = newPtr;
00882     p->extra = newExtra;
00883 }
00884 
00885 #define PLANK_ATOMICS_DEFINED 1
00886 
00887 #endif // PLANK_INLINING_FUNCTIONS
00888 
 All Classes Functions Typedefs Enumerations Enumerator Properties