![]() |
pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
|
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