pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plank_AtomicInline_Lock.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 #warning Using full mutex locks for atomic operations on this platform
00043 
00044 #include "../../../core/plank_Lock.h"
00045 
00046 #if PLANK_32BIT
00047     #define PLANK_ATOMIC_XBITS          32
00048     #define PLANK_ATOMIC_XREFCOUNTBITS  16
00049     #define PLANK_ATOMIC_XWEAKCOUNTBITS 16
00050     #define PLANK_ATOMIC_XREFCOUNTMAX   0x0000FFFFUL
00051     #define PLANK_ATOMIC_XREFCOUNTMASK  PLANK_ATOMIC_XREFCOUNTMAX
00052     #define PLANK_ATOMIC_XWEAKCOUNTMAX  0x0000FFFFUL
00053     #define PLANK_ATOMIC_XWEAKCOUNTMASK 0xFFFF0000UL
00054     #define PLANK_ATOMIC_XMAX           0xFFFFFFFFUL
00055     #define PLANK_ATOMIC_PMASK          0xFFFFFFFFUL
00056 #endif
00057 
00058 #if PLANK_64BIT
00059     #define PLANK_ATOMIC_XBITS          64
00060     #define PLANK_ATOMIC_XREFCOUNTBITS  32
00061     #define PLANK_ATOMIC_XWEAKCOUNTBITS 32
00062     #define PLANK_ATOMIC_XREFCOUNTMAX   0x00000000FFFFFFFFUL
00063     #define PLANK_ATOMIC_XREFCOUNTMASK  PLANK_ATOMIC_XREFCOUNTMAX
00064     #define PLANK_ATOMIC_XWEAKCOUNTMAX  0x00000000FFFFFFFFUL
00065     #define PLANK_ATOMIC_XWEAKCOUNTMASK 0xFFFFFFFF00000000UL
00066     #define PLANK_ATOMIC_XMAX           0xFFFFFFFFFFFFFFFFUL
00067     #define PLANK_ATOMIC_PMASK          0xFFFFFFFFFFFFFFFFUL
00068 #endif
00069 
00070 #if !DOXYGEN
00071 typedef struct PlankAtomicI
00072 {
00073     PlankI value;
00074     PlankLock lock;
00075 } PlankAtomicI;
00076 
00077 typedef struct PlankAtomicL
00078 {
00079     PlankL value;
00080     PlankLock lock;
00081 } PlankAtomicL;
00082 
00083 typedef struct PlankAtomicLL
00084 {
00085     PlankLL value;
00086     PlankLock lock;
00087 } PlankAtomicLL;
00088 
00089 typedef struct PlankAtomicF
00090 {
00091     PlankF value;
00092     PlankLock lock;
00093 } PlankAtomicF;
00094 
00095 typedef struct PlankAtomicD
00096 {
00097     PlankD value;
00098     PlankLock lock;
00099 } PlankAtomicD;
00100 
00101 typedef struct PlankAtomicP
00102 {
00103     PlankP ptr;
00104     PlankLock lock;
00105 } PlankAtomicP;
00106 
00107 typedef struct PlankAtomicPX
00108 {
00109     PlankP ptr;
00110     PlankUL extra;
00111     PlankLock lock;
00112 } PlankAtomicPX;
00113 #endif
00114 
00115 static PlankLock* getBarrierLock()
00116 {
00117     static PlankLock lock;
00118     static PlankB firstTime = PLANK_TRUE;
00119     
00120     if (firstTime)
00121     {
00122         pl_Lock_Init (&lock);
00123         firstTime = PLANK_FALSE;
00124     }
00125     
00126     return &lock;
00127 }
00128 
00129 static inline void pl_AtomicMemoryBarrier()
00130 {
00131     if (pl_Lock_TryLock (getBarrierLock()))
00132         pl_Lock_Unlock (getBarrierLock());
00133 }
00134 
00135 //------------------------------------------------------------------------------
00136 static inline PlankResult pl_AtomicI_Init (PlankAtomicIRef p)
00137 {
00138     if (p == PLANK_NULL)
00139         return PlankResult_MemoryError;
00140     
00141     pl_MemoryZero (p, sizeof (PlankAtomicI));
00142     pl_Lock_Init (&p->lock);
00143     
00144     return PlankResult_OK;
00145 }
00146 
00147 static inline PlankResult pl_AtomicI_DeInit (PlankAtomicIRef p)
00148 {
00149     if (p == PLANK_NULL)
00150         return PlankResult_MemoryError;
00151     
00152     pl_Lock_DeInit (&p->lock);
00153     
00154     return PlankResult_OK;
00155 }
00156 
00157 static inline PlankI pl_AtomicI_Get (PlankAtomicIRef p)
00158 {
00159     PlankI result;
00160     pl_Lock_Lock (&p->lock);
00161     result = p->value;
00162     pl_Lock_Unlock (&p->lock);
00163     return result;
00164 }
00165 
00166 static inline PlankI pl_AtomicI_GetUnchecked (PlankAtomicIRef p)
00167 {
00168     return p->value;
00169 }
00170 
00171 static inline PlankI pl_AtomicI_Swap (PlankAtomicIRef p, PlankI newValue)
00172 {
00173     PlankI oldValue;
00174     PlankB success;
00175     
00176     do {
00177         oldValue = *(PlankI*)p;
00178         success = pl_AtomicI_CompareAndSwap (p, oldValue, newValue);
00179     } while (!success);
00180     
00181     return oldValue;
00182 }
00183 
00184 static inline void pl_AtomicI_SwapOther (PlankAtomicIRef p1, PlankAtomicIRef p2)
00185 {
00186     PlankI value1, value2;
00187     PlankB success;
00188     
00189     do {
00190         value1 = *(PlankI*)p1;
00191         value2 = *(PlankI*)p2;
00192         success = pl_AtomicI_CompareAndSwap (p1, value1, value2);
00193     } while (!success);
00194     
00195     *(PlankI*)p2 = value1;
00196 }
00197 
00198 static inline void pl_AtomicI_Set (PlankAtomicIRef p, PlankI newValue)
00199 {
00200     pl_AtomicI_Swap (p, newValue);
00201 }
00202 
00203 static inline PlankI pl_AtomicI_Add (PlankAtomicIRef p, PlankI operand)
00204 {
00205     PlankI oldValue, newValue;
00206     PlankB success;
00207     
00208     do {
00209         oldValue = *(PlankI*)p;
00210         newValue = oldValue + operand;
00211         success = pl_AtomicI_CompareAndSwap (p, oldValue, newValue);
00212     } while (!success);
00213     
00214     return newValue;
00215 }
00216 
00217 static inline PlankB  pl_AtomicI_CompareAndSwap (PlankAtomicIRef p, PlankI oldValue, PlankI newValue)
00218 {
00219     if (! pl_Lock_TryLock (&p->lock))
00220         return PLANK_FALSE;
00221     
00222     if (p->value != oldValue)
00223     {
00224         pl_Lock_Unlock (&p->lock);
00225         return PLANK_FALSE;
00226     }
00227     
00228     p->value = newValue;
00229     pl_Lock_Unlock (&p->lock);
00230     
00231     return PLANK_TRUE;
00232 }
00233 
00234 static inline PlankI pl_AtomicI_Subtract (PlankAtomicIRef p, PlankI operand)
00235 {
00236     return pl_AtomicI_Add (p, -operand);
00237 }
00238 
00239 static inline PlankI pl_AtomicI_Increment (PlankAtomicIRef p)
00240 {
00241     return pl_AtomicI_Add (p, 1);
00242 }
00243 
00244 static inline PlankI pl_AtomicI_Decrement (PlankAtomicIRef p)
00245 {
00246     return pl_AtomicI_Add (p, -1);
00247 }
00248 
00249 //------------------------------------------------------------------------------
00250 static inline PlankResult pl_AtomicL_Init (PlankAtomicLRef p)
00251 {
00252     if (p == PLANK_NULL)
00253         return PlankResult_MemoryError;
00254     
00255     pl_MemoryZero (p, sizeof (PlankAtomicL));
00256     pl_Lock_Init (&p->lock);
00257     
00258     return PlankResult_OK;
00259 }
00260 
00261 static inline PlankResult pl_AtomicL_DeInit (PlankAtomicLRef p)
00262 {
00263     if (p == PLANK_NULL)
00264         return PlankResult_MemoryError;
00265     
00266     pl_Lock_DeInit (&p->lock);
00267     
00268     return PlankResult_OK;
00269 }
00270 
00271 static inline PlankL pl_AtomicL_Get (PlankAtomicLRef p)
00272 {
00273     PlankL result;
00274     pl_Lock_Lock (&p->lock);
00275     result = p->value;
00276     pl_Lock_Unlock (&p->lock);
00277     return result;
00278 }
00279 
00280 static inline PlankL pl_AtomicL_GetUnchecked (PlankAtomicLRef p)
00281 {
00282     return p->value;
00283 }
00284 
00285 static inline PlankL pl_AtomicL_Swap (PlankAtomicLRef p, PlankL newValue)
00286 {
00287     PlankL oldValue;
00288     PlankB success;
00289     
00290     do {
00291         oldValue = *(PlankL*)p;
00292         success = pl_AtomicL_CompareAndSwap (p, oldValue, newValue);
00293     } while (!success);
00294     
00295     return oldValue;
00296 }
00297 
00298 static inline void pl_AtomicL_SwapOther (PlankAtomicLRef p1, PlankAtomicLRef p2)
00299 {
00300     PlankL value1, value2;
00301     PlankB success;
00302     
00303     do {
00304         value1 = *(PlankL*)p1;
00305         value2 = *(PlankL*)p2;
00306         success = pl_AtomicL_CompareAndSwap (p1, value1, value2);
00307     } while (!success);
00308     
00309     *(PlankL*)p2 = value1;
00310 }
00311 
00312 static inline void pl_AtomicL_Set (PlankAtomicLRef p, PlankL newValue)
00313 {
00314     pl_AtomicL_Swap (p, newValue);
00315 }
00316 
00317 static inline PlankL pl_AtomicL_Add (PlankAtomicLRef p, PlankL operand)
00318 {
00319     PlankL oldValue, newValue;
00320     PlankB success;
00321     
00322     do {
00323         oldValue = *(PlankL*)p;
00324         newValue = oldValue + operand;
00325         success = pl_AtomicL_CompareAndSwap (p, oldValue, newValue);
00326     } while (!success);
00327     
00328     return newValue;
00329 }
00330 
00331 static inline PlankB pl_AtomicL_CompareAndSwap (PlankAtomicLRef p, PlankL oldValue, PlankL newValue)
00332 {    
00333     if (! pl_Lock_TryLock (&p->lock))
00334         return PLANK_FALSE;
00335     
00336     if (p->value != oldValue)
00337     {
00338         pl_Lock_Unlock (&p->lock);
00339         return PLANK_FALSE;
00340     }
00341     
00342     p->value = newValue;
00343     pl_Lock_Unlock (&p->lock);
00344     
00345     return PLANK_TRUE;
00346 }
00347         
00348 static inline PlankL pl_AtomicL_Subtract (PlankAtomicLRef p, PlankL operand)
00349 {
00350     return pl_AtomicL_Add (p, -operand);
00351 }
00352 
00353 static inline PlankL pl_AtomicL_Increment (PlankAtomicLRef p)
00354 {
00355     return pl_AtomicL_Add (p, (PlankL)1);
00356 }
00357 
00358 static inline PlankL pl_AtomicL_Decrement (PlankAtomicLRef p)
00359 {
00360     return pl_AtomicL_Add (p, (PlankL)(-1));
00361 }
00362 
00363 //------------------------------------------------------------------------------
00364 
00365 static inline PlankResult pl_AtomicLL_Init (PlankAtomicLLRef p)
00366 {
00367     PlankResult result = PlankResult_OK;
00368     
00369     if (p == PLANK_NULL)
00370     {
00371         result = PlankResult_MemoryError;
00372         goto exit;
00373     }
00374 
00375     pl_MemoryZero (p, sizeof (PlankAtomicLL));
00376     pl_Lock_Init (&p->lock);
00377     
00378 exit:
00379     return result;
00380 }
00381 
00382 static inline PlankResult pl_AtomicLL_DeInit (PlankAtomicLLRef p)
00383 {
00384     PlankResult result = PlankResult_OK;
00385     
00386     if (p == PLANK_NULL)
00387     {
00388         result = PlankResult_MemoryError;
00389         goto exit;
00390     }
00391     
00392     pl_Lock_DeInit (&p->lock);
00393     
00394 exit:
00395     return result;
00396 }
00397 
00398 static inline PlankLL pl_AtomicLL_Get (PlankAtomicLLRef p)
00399 {
00400     PlankLL result;
00401     pl_Lock_Lock (&p->lock);
00402     result = p->value;
00403     pl_Lock_Unlock (&p->lock);
00404     return result;
00405 }
00406 
00407 static inline PlankLL pl_AtomicLL_GetUnchecked (PlankAtomicLLRef p)
00408 {
00409     return p->value;
00410 }
00411 
00412 static inline PlankLL pl_AtomicLL_Swap (PlankAtomicLLRef p, PlankLL newValue)
00413 {
00414     PlankLL oldValue;
00415     PlankB success;
00416     
00417     do {
00418         oldValue = *(PlankLL*)p;
00419         success = pl_AtomicLL_CompareAndSwap (p, oldValue, newValue);
00420     } while (!success);
00421     
00422     return oldValue;
00423 }
00424 
00425 static inline void pl_AtomicLL_SwapOther (PlankAtomicLLRef p1, PlankAtomicLLRef p2)
00426 {
00427     PlankLL value1, value2;
00428     PlankB success;
00429     
00430     do {
00431         value1 = *(PlankLL*)p1;
00432         value2 = *(PlankLL*)p2;
00433         success = pl_AtomicLL_CompareAndSwap (p1, value1, value2);
00434     } while (!success);
00435     
00436     *(PlankLL*)p2 = value1;
00437 }
00438 
00439 static inline void pl_AtomicLL_Set (PlankAtomicLLRef p, PlankLL newValue)
00440 {
00441     pl_AtomicLL_Swap (p, newValue);
00442 }
00443 
00444 static inline PlankLL pl_AtomicLL_Add (PlankAtomicLLRef p, PlankLL operand)
00445 {
00446     PlankLL oldValue, newValue;
00447     PlankB success;
00448     
00449     do {
00450         oldValue = *(PlankLL*)p;
00451         newValue = oldValue + operand;
00452         success = pl_AtomicLL_CompareAndSwap (p, oldValue, newValue);
00453     } while (!success);
00454     
00455     return newValue;
00456 }
00457 
00458 static inline PlankB pl_AtomicLL_CompareAndSwap (PlankAtomicLLRef p, PlankLL oldValue, PlankLL newValue)
00459 {    
00460     if (! pl_Lock_TryLock (&p->lock))
00461         return PLANK_FALSE;
00462     
00463     if (p->value != oldValue)
00464     {
00465         pl_Lock_Unlock (&p->lock);
00466         return PLANK_FALSE;
00467     }
00468     
00469     p->value = newValue;
00470     pl_Lock_Unlock (&p->lock);
00471     
00472     return PLANK_TRUE;
00473 }
00474 
00475 static inline PlankLL pl_AtomicLL_Subtract (PlankAtomicLLRef p, PlankLL operand)
00476 {
00477     return pl_AtomicLL_Add (p, -operand);
00478 }
00479 
00480 static inline PlankLL pl_AtomicLL_Increment (PlankAtomicLLRef p)
00481 {
00482     return pl_AtomicLL_Add (p, (PlankLL)1);
00483 }
00484 
00485 static inline PlankLL pl_AtomicLL_Decrement (PlankAtomicLLRef p)
00486 {
00487     return pl_AtomicLL_Add (p, (PlankLL)(-1));
00488 }
00489 
00490 //------------------------------------------------------------------------------
00491 
00492 static inline PlankResult pl_AtomicF_Init (PlankAtomicFRef p)
00493 {
00494     if (p == PLANK_NULL)
00495         return PlankResult_MemoryError;
00496     
00497     pl_MemoryZero (p, sizeof (PlankAtomicF));
00498     pl_Lock_Init (&p->lock);
00499     
00500     return PlankResult_OK;
00501 }
00502 
00503 static inline PlankResult pl_AtomicF_DeInit (PlankAtomicFRef p)
00504 {
00505     if (p == PLANK_NULL)
00506         return PlankResult_MemoryError;
00507     
00508     pl_Lock_DeInit (&p->lock);
00509     
00510     return PlankResult_OK;
00511 }
00512 
00513 static inline PlankF pl_AtomicF_Get (PlankAtomicFRef p)
00514 {
00515     PlankF result;
00516     pl_Lock_Lock (&p->lock);
00517     result = p->value;
00518     pl_Lock_Unlock (&p->lock);
00519     return result;
00520 }
00521 
00522 static inline PlankF pl_AtomicF_GetUnchecked (PlankAtomicFRef p)
00523 {
00524     return  p->value;
00525 }
00526 
00527 static inline PlankF pl_AtomicF_Swap (PlankAtomicFRef p, PlankF newValue)
00528 {
00529     PlankF oldValue;
00530     PlankB success;
00531     
00532     do
00533     {
00534         oldValue = *(PlankF*)p;
00535         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00536     } while (!success);
00537     
00538     return oldValue;
00539 }
00540 
00541 static inline void pl_AtomicF_SwapOther (PlankAtomicFRef p1, PlankAtomicFRef p2)
00542 {
00543     PlankF value1, value2;
00544     PlankB success;
00545     
00546     do {
00547         value1 = *(PlankF*)p1;
00548         value2 = *(PlankF*)p2;
00549         success = pl_AtomicF_CompareAndSwap (p1, value1, value2);
00550     } while (!success);
00551     
00552     *(PlankF*)p2 = value1;
00553 }
00554 
00555 static inline void pl_AtomicF_Set (PlankAtomicFRef p, PlankF newValue)
00556 {
00557     pl_AtomicF_Swap (p, newValue);
00558 }
00559 
00560 static inline PlankF pl_AtomicF_Add (PlankAtomicFRef p, PlankF operand)
00561 {
00562     PlankF newValue, oldValue;
00563     PlankB success;
00564     
00565     do {
00566         oldValue = *(PlankF*)p;
00567         newValue = oldValue + operand;
00568         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00569     } while (!success);
00570     
00571     return newValue;
00572 }
00573 
00574 static inline PlankB pl_AtomicF_CompareAndSwap (PlankAtomicFRef p, PlankF oldValue, PlankF newValue)
00575 {    
00576     if (! pl_Lock_TryLock (&p->lock))
00577         return PLANK_FALSE;
00578     
00579     if (p->value != oldValue)
00580     {
00581         pl_Lock_Unlock (&p->lock);
00582         return PLANK_FALSE;
00583     }
00584     
00585     p->value = newValue;
00586     pl_Lock_Unlock (&p->lock);
00587     
00588     return PLANK_TRUE;
00589 }
00590 
00591 static inline PlankF pl_AtomicF_Subtract (PlankAtomicFRef p, PlankF operand)
00592 {
00593     return pl_AtomicF_Add (p, -operand);
00594 }
00595 
00596 static inline PlankF pl_AtomicF_Increment (PlankAtomicFRef p)
00597 {
00598     return pl_AtomicF_Add (p, 1.f);
00599 }
00600 
00601 static inline PlankF pl_AtomicF_Decrement (PlankAtomicFRef p)
00602 {
00603     return pl_AtomicF_Add (p, -1.f);
00604 }
00605 
00606 //------------------------------------------------------------------------------
00607 
00608 static inline PlankResult pl_AtomicD_Init (PlankAtomicDRef p)
00609 {
00610     PlankResult result = PlankResult_OK;
00611     
00612     if (p == PLANK_NULL)
00613     {
00614         result = PlankResult_MemoryError;
00615         goto exit;
00616     }
00617     
00618     pl_MemoryZero (p, sizeof (PlankAtomicD));
00619     pl_Lock_Init (&p->lock);
00620     
00621 exit:
00622     return result;
00623 }
00624 
00625 static inline PlankResult pl_AtomicD_DeInit (PlankAtomicDRef p)
00626 {
00627     PlankResult result = PlankResult_OK;
00628     
00629     if (p == PLANK_NULL)
00630     {
00631         result = PlankResult_MemoryError;
00632         goto exit;
00633     }
00634     
00635     pl_Lock_DeInit (&p->lock);
00636     
00637 exit:
00638     return result;
00639 }
00640 
00641 static inline PlankD pl_AtomicD_Get (PlankAtomicDRef p)
00642 {
00643     PlankD result;
00644     pl_Lock_Lock (&p->lock);
00645     result = p->value;
00646     pl_Lock_Unlock (&p->lock);
00647     return result;
00648 }
00649 
00650 static inline PlankD pl_AtomicD_GetUnchecked (PlankAtomicDRef p)
00651 {
00652     return p->value;
00653 }
00654 
00655 static inline PlankD pl_AtomicD_Swap (PlankAtomicDRef p, PlankD newValue)
00656 {
00657     PlankD oldValue;
00658     PlankB success;
00659     
00660     do {
00661         oldValue = *(PlankD*)p;
00662         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00663     } while (!success);
00664     
00665     return oldValue;
00666 }
00667 
00668 static inline void pl_AtomicD_SwapOther (PlankAtomicDRef p1, PlankAtomicDRef p2)
00669 {
00670     PlankD value1, value2;
00671     PlankB success;
00672     
00673     do {
00674         value1 = *(PlankD*)p1;
00675         value2 = *(PlankD*)p2;
00676         success = pl_AtomicD_CompareAndSwap (p1, value1, value2);
00677     } while (!success);
00678     
00679     *(PlankD*)p2 = value1;
00680 }
00681 
00682 static inline void pl_AtomicD_Set (PlankAtomicDRef p, PlankD newValue)
00683 {
00684     pl_AtomicD_Swap (p, newValue);
00685 }
00686 
00687 static inline PlankD pl_AtomicD_Add (PlankAtomicDRef p, PlankD operand)
00688 {
00689     PlankD newValue, oldValue;
00690     PlankB success;
00691     
00692     do {
00693         oldValue = *(PlankD*)p;
00694         newValue = oldValue + operand;
00695         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00696     } while (!success);
00697     
00698     return newValue;
00699 }
00700 
00701 static inline PlankB pl_AtomicD_CompareAndSwap (PlankAtomicDRef p, PlankD oldValue, PlankD newValue)
00702 {    
00703     if (! pl_Lock_TryLock (&p->lock))
00704         return PLANK_FALSE;
00705     
00706     if (p->value != oldValue)
00707     {
00708         pl_Lock_Unlock (&p->lock);
00709         return PLANK_FALSE;
00710     }
00711     
00712     p->value = newValue;
00713     pl_Lock_Unlock (&p->lock);
00714     
00715     return PLANK_TRUE;
00716 }
00717 
00718 static inline PlankD pl_AtomicD_Subtract (PlankAtomicDRef p, PlankD operand)
00719 {
00720     return pl_AtomicD_Add (p, -operand);
00721 }
00722 
00723 static inline PlankD pl_AtomicD_Increment (PlankAtomicDRef p)
00724 {
00725     return pl_AtomicD_Add (p, 1.0);
00726 }
00727 
00728 static inline PlankD pl_AtomicD_Decrement (PlankAtomicDRef p)
00729 {
00730     return pl_AtomicD_Add (p, -1.0);
00731 }
00732 
00733 //------------------------------------------------------------------------------
00734 
00735 static inline PlankResult pl_AtomicP_Init (PlankAtomicPRef p)
00736 {
00737     if (p == PLANK_NULL)
00738         return PlankResult_MemoryError;
00739     
00740     pl_MemoryZero (p, sizeof (PlankAtomicP));
00741     pl_Lock_Init (&p->lock);
00742     
00743     return PlankResult_OK;
00744 }
00745 
00746 static inline PlankResult pl_AtomicP_DeInit (PlankAtomicPRef p)
00747 {
00748     if (p == PLANK_NULL)
00749         return PlankResult_MemoryError;
00750     
00751     pl_Lock_DeInit (&p->lock);
00752     
00753     return PlankResult_OK;
00754 }
00755 
00756 static inline PlankP pl_AtomicP_Get (PlankAtomicPRef p)
00757 {
00758     PlankP result;
00759     pl_Lock_Lock (&p->lock);
00760     result = p->ptr;
00761     pl_Lock_Unlock (&p->lock);
00762     return result;
00763 }
00764 
00765 static inline PlankP pl_AtomicP_GetUnchecked (PlankAtomicPRef p)
00766 {
00767     return p->ptr;
00768 }
00769 
00770 static inline PlankP pl_AtomicP_Swap (PlankAtomicPRef p, PlankP newPtr)
00771 {
00772     PlankP oldPtr;
00773     PlankB success;
00774     
00775     do {
00776         oldPtr = *(PlankP*)p;
00777         success = pl_AtomicP_CompareAndSwap (p, oldPtr, newPtr);
00778     } while (!success);
00779     
00780     return oldPtr;    
00781 }
00782 
00783 static inline void pl_AtomicP_SwapOther (PlankAtomicPRef p1, PlankAtomicPRef p2)
00784 {
00785     PlankP value1, value2;
00786     PlankB success;
00787     
00788     do {
00789         value1 = *(PlankP*)p1;
00790         value2 = *(PlankP*)p2;
00791         success = pl_AtomicP_CompareAndSwap (p1, value1, value2);
00792     } while (!success);
00793     
00794     *(PlankP*)p2 = value1;
00795 }
00796 
00797 static inline void pl_AtomicP_Set (PlankAtomicPRef p, PlankP newPtr)
00798 {
00799     pl_AtomicP_Swap (p, newPtr);
00800 }
00801 
00802 static inline PlankP pl_AtomicP_Add (PlankAtomicPRef p, PlankL operand)
00803 {
00804     PlankP newPtr, oldPtr;
00805     PlankB success;
00806     
00807     do {
00808         oldPtr = *(PlankP*)p;
00809         newPtr = (PlankUC*)oldPtr + operand;
00810         success = pl_AtomicP_CompareAndSwap (p, oldPtr, newPtr);
00811     } while (!success);
00812     
00813     return newPtr;
00814 }
00815 
00816 static inline PlankB pl_AtomicP_CompareAndSwap (PlankAtomicPRef p, PlankP oldPtr, PlankP newPtr)
00817 {
00818     if (! pl_Lock_TryLock (&p->lock))
00819         return PLANK_FALSE;
00820     
00821     if (p->ptr != oldPtr)
00822     {
00823         pl_Lock_Unlock (&p->lock);
00824         return PLANK_FALSE;
00825     }
00826     
00827     p->ptr = newPtr;
00828     pl_Lock_Unlock (&p->lock);
00829     
00830     return PLANK_TRUE;
00831 }
00832 
00833 static inline PlankP pl_AtomicP_Subtract (PlankAtomicPRef p, PlankL operand)
00834 {
00835     return pl_AtomicP_Add (p, -operand);
00836 }
00837 
00838 static inline PlankP pl_AtomicP_Increment (PlankAtomicPRef p)
00839 {
00840     return pl_AtomicP_Add (p, (PlankL)1);
00841 }
00842 
00843 static inline PlankP pl_AtomicP_Decrement (PlankAtomicPRef p)
00844 {
00845     return pl_AtomicP_Add (p, (PlankL)(-1));
00846 }
00847 
00848 //------------------------------------------------------------------------------
00849 
00850 static inline PlankAtomicPXRef pl_AtomicPX_CreateAndInit()
00851 {
00852     PlankAtomicPXRef p = pl_AtomicPX_Create();
00853     if (p != PLANK_NULL) pl_AtomicPX_Init (p);
00854     return p;
00855 }
00856 
00857 static inline PlankAtomicPXRef pl_AtomicPX_Create()
00858 {
00859     PlankMemoryRef m;
00860     PlankAtomicPXRef p;
00861     
00862     m = pl_MemoryGlobal();
00863     p = (PlankAtomicPXRef)pl_Memory_AllocateBytes (m, sizeof (PlankAtomicPX));
00864     
00865     if (p != PLANK_NULL)
00866         pl_MemoryZero (p, sizeof (PlankAtomicPX));
00867     
00868     return p;
00869 }
00870 
00871 static inline PlankResult pl_AtomicPX_Init (PlankAtomicPXRef p)
00872 {
00873     PlankResult result = PlankResult_OK;
00874     
00875     if (p == PLANK_NULL)
00876     {
00877         result = PlankResult_MemoryError;
00878         goto exit;
00879     }
00880     
00881     pl_MemoryZero (p, sizeof (PlankAtomicPX));
00882     pl_Lock_Init (&p->lock);
00883     
00884 exit:
00885     return result;
00886 }
00887 
00888 static inline PlankResult pl_AtomicPX_DeInit (PlankAtomicPXRef p)
00889 {
00890     PlankResult result = PlankResult_OK;
00891     
00892     if (p == PLANK_NULL)
00893     {
00894         result = PlankResult_MemoryError;
00895         goto exit;
00896     }
00897     
00898     pl_Lock_DeInit (&p->lock);
00899     
00900 exit:
00901     return result;
00902 }
00903 
00904 static inline PlankResult pl_AtomicPX_Destroy (PlankAtomicPXRef p)
00905 {
00906     PlankResult result;
00907     PlankMemoryRef m;
00908     
00909     result = PlankResult_OK;
00910     m = pl_MemoryGlobal();
00911     
00912     if ((result = pl_AtomicPX_DeInit (p)) != PlankResult_OK)
00913         goto exit;
00914     
00915     result = pl_Memory_Free (m, p);
00916     
00917 exit:
00918     return result;
00919 }
00920 
00921 static inline PlankP pl_AtomicPX_Get (PlankAtomicPXRef p)
00922 {
00923     PlankP result;
00924     pl_Lock_Lock (&p->lock);
00925     result = p->ptr;
00926     pl_Lock_Unlock (&p->lock);
00927     return result;
00928 }
00929 
00930 static inline PlankP pl_AtomicPX_GetUnchecked (PlankAtomicPXRef p)
00931 {
00932     return p->ptr;
00933 }
00934 
00935 static inline PlankUL pl_AtomicPX_GetExtra (PlankAtomicPXRef p)
00936 {
00937     PlankUL result;
00938     pl_Lock_Lock (&p->lock);
00939     result = p->extra;
00940     pl_Lock_Unlock (&p->lock);
00941     return result;
00942 }
00943 
00944 static inline PlankUL pl_AtomicPX_GetExtraUnchecked (PlankAtomicPXRef p)
00945 {
00946     return p->extra;
00947 }
00948 
00949 static inline PlankP pl_AtomicPX_SwapAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra, PlankUL* oldExtraPtr)
00950 {
00951     PlankP oldPtr;
00952     PlankUL oldExtra;
00953     PlankB success;
00954     
00955     do {
00956         oldPtr = p->ptr;
00957         oldExtra = p->extra;
00958         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, newExtra);
00959     } while (!success);
00960     
00961     if (oldExtraPtr != PLANK_NULL)
00962         *oldExtraPtr = oldExtra;
00963     
00964     return oldPtr;
00965 }
00966 
00967 static inline PlankP pl_AtomicPX_Swap (PlankAtomicPXRef p, PlankP newPtr)
00968 {
00969     PlankP oldPtr;
00970     PlankUL oldExtra;
00971     PlankB success;
00972     
00973     do {
00974         oldPtr = p->ptr;
00975         oldExtra = p->extra;
00976         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00977     } while (!success);
00978     
00979     return oldPtr;
00980 }
00981 
00982 static inline void pl_AtomicPX_SwapOther (PlankAtomicPXRef p1, PlankAtomicPXRef p2)
00983 {
00984     PlankAtomicPX tmp1, tmp2;
00985     PlankB success;
00986     
00987     do {
00988         tmp1 = *p1;
00989         tmp2 = *p2;
00990         success = pl_AtomicPX_CompareAndSwap (p1, tmp1.ptr, tmp1.extra, tmp2.ptr, tmp1.extra + 1);
00991     } while (!success);
00992     
00993     pl_AtomicPX_Set (p2, tmp1.ptr);
00994 }
00995 
00996 static inline void pl_AtomicPX_SetAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00997 {
00998     pl_AtomicPX_SwapAll (p, newPtr, newExtra, (PlankUL*)PLANK_NULL);
00999 }
01000 
01001 static inline void pl_AtomicPX_Set (PlankAtomicPXRef p, PlankP newPtr)
01002 {
01003     PlankP oldPtr;
01004     PlankUL oldExtra;
01005     PlankB success;
01006     
01007     do {
01008         oldPtr = p->ptr;
01009         oldExtra = p->extra;
01010         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
01011     } while (!success);
01012 }
01013 
01014 static inline PlankP pl_AtomicPX_Add (PlankAtomicPXRef p, PlankL operand)
01015 {
01016     PlankP newPtr, oldPtr;
01017     PlankUL oldExtra;
01018     PlankB success;
01019     
01020     do {
01021         oldPtr = p->ptr;
01022         oldExtra = p->extra;
01023         newPtr = (PlankUC*)oldPtr + operand;
01024         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
01025     } while (!success);
01026     
01027     return newPtr;
01028 }
01029 
01030 static inline PlankP pl_AtomicPX_Subtract (PlankAtomicPXRef p, PlankL operand)
01031 {
01032     return pl_AtomicPX_Add (p, -operand);
01033 }
01034 
01035 static inline PlankP pl_AtomicPX_Increment (PlankAtomicPXRef p)
01036 {
01037     return pl_AtomicPX_Add (p, (PlankL)1);
01038 }
01039 
01040 static inline PlankP pl_AtomicPX_Decrement (PlankAtomicPXRef p)
01041 {
01042     return pl_AtomicPX_Add (p, (PlankL)(-1));
01043 }
01044 
01045 static inline  PlankB pl_AtomicPX_CompareAndSwap (PlankAtomicPXRef p, PlankP oldPtr, PlankUL oldExtra, PlankP newPtr, PlankUL newExtra)
01046 {
01047     if (! pl_Lock_TryLock (&p->lock))
01048         return PLANK_FALSE;
01049     
01050     if ((p->ptr != oldPtr) || (p->extra != oldExtra))
01051     {
01052         pl_Lock_Unlock (&p->lock);
01053         return PLANK_FALSE;
01054     }
01055     
01056     p->ptr = newPtr;
01057     p->extra = newExtra;
01058     pl_Lock_Unlock (&p->lock);
01059     
01060     return PLANK_TRUE;
01061 }
01062 
01063 static inline PlankB pl_AtomicPX_CompareAndSwapP (PlankAtomicPXRef p, PlankP oldPtr, PlankP newPtr)
01064 {
01065     return pl_AtomicP_CompareAndSwap ((PlankAtomicPRef)p, oldPtr, newPtr);
01066 }
01067 
01068 static inline void pl_AtomicPX_SetAllUnchecked (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
01069 {
01070     p->ptr = newPtr;
01071     p->extra = newExtra;
01072 }
01073 
01074 #define PLANK_ATOMICS_DEFINED 1
01075 
01076 #endif // PLANK_INLINING_FUNCTIONS
01077 
 All Classes Functions Typedefs Enumerations Enumerator Properties