![]() |
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 #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