| | 273 | // LDC Atomics Implementation |
|---|
| | 274 | //////////////////////////////////////////////////////////////////////////////// |
|---|
| | 275 | |
|---|
| | 276 | |
|---|
| | 277 | else version( LDC ) |
|---|
| | 278 | { |
|---|
| | 279 | import ldc.intrinsics; |
|---|
| | 280 | |
|---|
| | 281 | |
|---|
| | 282 | //////////////////////////////////////////////////////////////////////////// |
|---|
| | 283 | // Atomic Load |
|---|
| | 284 | //////////////////////////////////////////////////////////////////////////// |
|---|
| | 285 | |
|---|
| | 286 | |
|---|
| | 287 | template atomicLoad( msync ms = msync.seq, T ) |
|---|
| | 288 | { |
|---|
| | 289 | T atomicLoad(ref T val) |
|---|
| | 290 | { |
|---|
| | 291 | llvm_memory_barrier( |
|---|
| | 292 | ms == msync.hlb || ms == msync.acq || ms == msync.seq, |
|---|
| | 293 | ms == msync.hsb || ms == msync.acq || ms == msync.seq, |
|---|
| | 294 | ms == msync.slb || ms == msync.rel || ms == msync.seq, |
|---|
| | 295 | ms == msync.ssb || ms == msync.rel || ms == msync.seq, |
|---|
| | 296 | false); |
|---|
| | 297 | static if (isPointerType!(T)) |
|---|
| | 298 | { |
|---|
| | 299 | return cast(T)llvm_atomic_load_add!(size_t)(cast(size_t*)&val, 0); |
|---|
| | 300 | } |
|---|
| | 301 | else static if (is(T == bool)) |
|---|
| | 302 | { |
|---|
| | 303 | return llvm_atomic_load_add!(ubyte)(cast(ubyte*)&val, cast(ubyte)0) ? 1 : 0; |
|---|
| | 304 | } |
|---|
| | 305 | else |
|---|
| | 306 | { |
|---|
| | 307 | return llvm_atomic_load_add!(T)(&val, cast(T)0); |
|---|
| | 308 | } |
|---|
| | 309 | } |
|---|
| | 310 | } |
|---|
| | 311 | |
|---|
| | 312 | |
|---|
| | 313 | //////////////////////////////////////////////////////////////////////////// |
|---|
| | 314 | // Atomic Store |
|---|
| | 315 | //////////////////////////////////////////////////////////////////////////// |
|---|
| | 316 | |
|---|
| | 317 | |
|---|
| | 318 | template atomicStore( msync ms = msync.seq, T ) |
|---|
| | 319 | { |
|---|
| | 320 | void atomicStore( ref T val, T newval ) |
|---|
| | 321 | { |
|---|
| | 322 | llvm_memory_barrier( |
|---|
| | 323 | ms == msync.hlb || ms == msync.acq || ms == msync.seq, |
|---|
| | 324 | ms == msync.hsb || ms == msync.acq || ms == msync.seq, |
|---|
| | 325 | ms == msync.slb || ms == msync.rel || ms == msync.seq, |
|---|
| | 326 | ms == msync.ssb || ms == msync.rel || ms == msync.seq, |
|---|
| | 327 | false); |
|---|
| | 328 | static if (isPointerType!(T)) |
|---|
| | 329 | { |
|---|
| | 330 | llvm_atomic_swap!(size_t)(cast(size_t*)&val, cast(size_t)newval); |
|---|
| | 331 | } |
|---|
| | 332 | else static if (is(T == bool)) |
|---|
| | 333 | { |
|---|
| | 334 | llvm_atomic_swap!(ubyte)(cast(ubyte*)&val, newval?1:0); |
|---|
| | 335 | } |
|---|
| | 336 | else |
|---|
| | 337 | { |
|---|
| | 338 | llvm_atomic_swap!(T)(&val, newval); |
|---|
| | 339 | } |
|---|
| | 340 | } |
|---|
| | 341 | } |
|---|
| | 342 | |
|---|
| | 343 | |
|---|
| | 344 | //////////////////////////////////////////////////////////////////////////// |
|---|
| | 345 | // Atomic Store If |
|---|
| | 346 | //////////////////////////////////////////////////////////////////////////// |
|---|
| | 347 | |
|---|
| | 348 | |
|---|
| | 349 | template atomicStoreIf( msync ms = msync.seq, T ) |
|---|
| | 350 | { |
|---|
| | 351 | bool atomicStoreIf( ref T val, T newval, T equalTo ) |
|---|
| | 352 | { |
|---|
| | 353 | llvm_memory_barrier( |
|---|
| | 354 | ms == msync.hlb || ms == msync.acq || ms == msync.seq, |
|---|
| | 355 | ms == msync.hsb || ms == msync.acq || ms == msync.seq, |
|---|
| | 356 | ms == msync.slb || ms == msync.rel || ms == msync.seq, |
|---|
| | 357 | ms == msync.ssb || ms == msync.rel || ms == msync.seq, |
|---|
| | 358 | false); |
|---|
| | 359 | T oldval = void; |
|---|
| | 360 | static if (isPointerType!(T)) |
|---|
| | 361 | { |
|---|
| | 362 | oldval = cast(T)llvm_atomic_cmp_swap!(size_t)(cast(size_t*)&val, cast(size_t)equalTo, cast(size_t)newval); |
|---|
| | 363 | } |
|---|
| | 364 | else static if (is(T == bool)) |
|---|
| | 365 | { |
|---|
| | 366 | oldval = llvm_atomic_cmp_swap!(ubyte)(cast(ubyte*)&val, equalTo?1:0, newval?1:0)?0:1; |
|---|
| | 367 | } |
|---|
| | 368 | else |
|---|
| | 369 | { |
|---|
| | 370 | oldval = llvm_atomic_cmp_swap!(T)(&val, equalTo, newval); |
|---|
| | 371 | } |
|---|
| | 372 | return oldval == equalTo; |
|---|
| | 373 | } |
|---|
| | 374 | } |
|---|
| | 375 | |
|---|
| | 376 | |
|---|
| | 377 | //////////////////////////////////////////////////////////////////////////// |
|---|
| | 378 | // Atomic Increment |
|---|
| | 379 | //////////////////////////////////////////////////////////////////////////// |
|---|
| | 380 | |
|---|
| | 381 | |
|---|
| | 382 | template atomicIncrement( msync ms = msync.seq, T ) |
|---|
| | 383 | { |
|---|
| | 384 | // |
|---|
| | 385 | // NOTE: This operation is only valid for integer or pointer types |
|---|
| | 386 | // |
|---|
| | 387 | static assert( isValidNumericType!(T) ); |
|---|
| | 388 | |
|---|
| | 389 | |
|---|
| | 390 | T atomicIncrement( ref T val ) |
|---|
| | 391 | { |
|---|
| | 392 | static if (isPointerType!(T)) |
|---|
| | 393 | { |
|---|
| | 394 | llvm_atomic_load_add!(size_t)(cast(size_t*)&val, 1); |
|---|
| | 395 | } |
|---|
| | 396 | else |
|---|
| | 397 | { |
|---|
| | 398 | llvm_atomic_load_add!(T)(&val, cast(T)1); |
|---|
| | 399 | } |
|---|
| | 400 | return val; |
|---|
| | 401 | } |
|---|
| | 402 | } |
|---|
| | 403 | |
|---|
| | 404 | |
|---|
| | 405 | //////////////////////////////////////////////////////////////////////////// |
|---|
| | 406 | // Atomic Decrement |
|---|
| | 407 | //////////////////////////////////////////////////////////////////////////// |
|---|
| | 408 | |
|---|
| | 409 | |
|---|
| | 410 | template atomicDecrement( msync ms = msync.seq, T ) |
|---|
| | 411 | { |
|---|
| | 412 | // |
|---|
| | 413 | // NOTE: This operation is only valid for integer or pointer types |
|---|
| | 414 | // |
|---|
| | 415 | static assert( isValidNumericType!(T) ); |
|---|
| | 416 | |
|---|
| | 417 | |
|---|
| | 418 | T atomicDecrement( ref T val ) |
|---|
| | 419 | { |
|---|
| | 420 | static if (isPointerType!(T)) |
|---|
| | 421 | { |
|---|
| | 422 | llvm_atomic_load_sub!(size_t)(cast(size_t*)&val, 1); |
|---|
| | 423 | } |
|---|
| | 424 | else |
|---|
| | 425 | { |
|---|
| | 426 | llvm_atomic_load_sub!(T)(&val, cast(T)1); |
|---|
| | 427 | } |
|---|
| | 428 | return val; |
|---|
| | 429 | } |
|---|
| | 430 | } |
|---|
| | 431 | } |
|---|
| | 432 | |
|---|
| | 433 | //////////////////////////////////////////////////////////////////////////////// |
|---|