// D import file generated from '../../../../libphobos/libdruntime/core/atomic.d'
module core.atomic;
version (D_InlineAsm_X86)
{
	version = AsmX86;
	version = AsmX86_32;
	enum has64BitCAS = true;
}
version (D_InlineAsm_X86_64)
{
	version = AsmX86;
	version = AsmX86_64;
	enum has64BitCAS = true;
}
private template HeadUnshared(T)
{
	static if(is(T U : shared(U*)))
	{
		alias shared(U)* HeadUnshared;
	}
	else
	{
		alias T HeadUnshared;
	}
}

version (AsmX86)
{
	private template atomicValueIsProperlyAligned(T)
	{
		pure nothrow bool atomicValueIsProperlyAligned(size_t addr)
		{
			return addr % T.sizeof == 0;
		}

	}

}
version (CoreDdoc)
{
	template atomicOp(string op, T, V1) if (__traits(compiles,mixin("val" ~ op ~ "mod")))
	{
		nothrow HeadUnshared!(T) atomicOp(ref shared T val, V1 mod)
		{
			return HeadUnshared!(T).init;
		}

	}
	template cas(T, V1, V2) if (!is(T == class) && !is(T U : U*) && __traits(compiles,()
	{
		*here = writeThis;
	}
	))
	{
		nothrow bool cas(shared(T)* here, const V1 ifThis, const V2 writeThis);

	}
	template cas(T, V1, V2) if (is(T == class) && __traits(compiles,()
	{
		*here = writeThis;
	}
	))
	{
		nothrow bool cas(shared(T)* here, const shared(V1) ifThis, shared(V2) writeThis);

	}
	template cas(T, V1, V2) if (is(T U : U*) && __traits(compiles,()
	{
		*here = writeThis;
	}
	))
	{
		nothrow bool cas(shared(T)* here, const shared(V1)* ifThis, shared(V2)* writeThis);

	}
	template atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)
	{
		nothrow HeadUnshared!(T) atomicLoad(ref const shared T val)
		{
			return HeadUnshared!(T).init;
		}

	}
	template atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V1) if (__traits(compiles,()
	{
		val = newval;
	}
	))
	{
		nothrow void atomicStore(ref shared T val, V1 newval)
		{
		}

	}
	enum MemoryOrder 
	{
		raw,
		acq,
		rel,
		seq,
	}
	deprecated("Please use MemoryOrder instead.") alias MemoryOrder msync;

	nothrow void atomicFence();
}
else
{
	version (AsmX86_32)
	{
		template atomicOp(string op, T, V1) if (__traits(compiles,mixin("val" ~ op ~ "mod")))
		{
			nothrow HeadUnshared!(T) atomicOp(ref shared T val, V1 mod)
			in
			{
				static if(T.sizeof > size_t.sizeof)
				{
					assert(atomicValueIsProperlyAligned!(size_t)(cast(size_t)&val));
				}
				else
				{
					assert(atomicValueIsProperlyAligned!(T)(cast(size_t)&val));
				}

			}
			body
			{
				static if(op == "+" || op == "-" || op == "*" || op == "/" || op == "%" || op == "^^" || op == "&" || op == "|" || op == "^" || op == "<<" || op == ">>" || op == ">>>" || op == "~" || op == "==" || op == "!=" || op == "<" || op == "<=" || op == ">" || op == ">=")
				{
					HeadUnshared!(T) get = atomicLoad!(MemoryOrder.raw)(val);
					mixin("return get " ~ op ~ " mod;");
				}
				else
				{
					static if(op == "+=" || op == "-=" || op == "*=" || op == "/=" || op == "%=" || op == "^^=" || op == "&=" || op == "|=" || op == "^=" || op == "<<=" || op == ">>=" || op == ">>>=")
					{
						HeadUnshared!(T) get,set;
						do
						{
							get = (set = atomicLoad!(MemoryOrder.raw)(val));
							mixin("set " ~ op ~ " mod;");
						}
						while (!cas(&val, get, set));
						return set;
					}
					else
					{
						static assert(false,"Operation not supported.");
					}

				}

			}

		}
		template cas(T, V1, V2) if (!is(T == class) && !is(T U : U*) && __traits(compiles,()
		{
			*here = writeThis;
		}
		))
		{
			nothrow bool cas(shared(T)* here, const V1 ifThis, const V2 writeThis)
			{
				return casImpl(here, ifThis, writeThis);
			}

		}
		template cas(T, V1, V2) if (is(T == class) && __traits(compiles,()
		{
			*here = writeThis;
		}
		))
		{
			nothrow bool cas(shared(T)* here, const shared(V1) ifThis, shared(V2) writeThis)
			{
				return casImpl(here, ifThis, writeThis);
			}

		}
		template cas(T, V1, V2) if (is(T U : U*) && __traits(compiles,()
		{
			*here = writeThis;
		}
		))
		{
			nothrow bool cas(shared(T)* here, const shared(V1)* ifThis, shared(V2)* writeThis)
			{
				return casImpl(here, ifThis, writeThis);
			}

		}
		private template casImpl(T, V1, V2)
		{
			nothrow bool casImpl(shared(T)* here, V1 ifThis, V2 writeThis)
			in
			{
				static if(T.sizeof > size_t.sizeof)
				{
					assert(atomicValueIsProperlyAligned!(size_t)(cast(size_t)here));
				}
				else
				{
					assert(atomicValueIsProperlyAligned!(T)(cast(size_t)here));
				}

			}
			body
			{
				static if(T.sizeof == (byte).sizeof)
				{
					asm { mov DL,writeThis; }
					asm { mov AL,ifThis; }
					asm { mov ECX,here; }
					asm { lock; }
					asm { cmpxchg[ECX],DL; }
					asm { setz AL; }
				}
				else
				{
					static if(T.sizeof == (short).sizeof)
					{
						asm { mov DX,writeThis; }
						asm { mov AX,ifThis; }
						asm { mov ECX,here; }
						asm { lock; }
						asm { cmpxchg[ECX],DX; }
						asm { setz AL; }
					}
					else
					{
						static if(T.sizeof == (int).sizeof)
						{
							asm { mov EDX,writeThis; }
							asm { mov EAX,ifThis; }
							asm { mov ECX,here; }
							asm { lock; }
							asm { cmpxchg[ECX],EDX; }
							asm { setz AL; }
						}
						else
						{
							static if(T.sizeof == (long).sizeof && has64BitCAS)
							{
								asm { push EDI; }
								asm { push EBX; }
								asm { lea EDI,writeThis; }
								asm { mov EBX,[EDI]; }
								asm { mov ECX,4[EDI]; }
								asm { lea EDI,ifThis; }
								asm { mov EAX,[EDI]; }
								asm { mov EDX,4[EDI]; }
								asm { mov EDI,here; }
								asm { lock; }
								asm { cmpxchg8b[EDI]; }
								asm { setz AL; }
								asm { pop EBX; }
								asm { pop EDI; }
							}
							else
							{
								static assert(false,"Invalid template type specified.");
							}

						}

					}

				}

			}

		}

		enum MemoryOrder 
		{
			raw,
			acq,
			rel,
			seq,
		}
		deprecated("Please use MemoryOrder instead.") alias MemoryOrder msync;

		private 
		{
			template isHoistOp(MemoryOrder ms)
			{
				enum bool isHoistOp = ms == MemoryOrder.acq || ms == MemoryOrder.seq;
			}
			template isSinkOp(MemoryOrder ms)
			{
				enum bool isSinkOp = ms == MemoryOrder.rel || ms == MemoryOrder.seq;
			}
			template needsLoadBarrier(MemoryOrder ms)
			{
				enum bool needsLoadBarrier = ms != MemoryOrder.raw;
			}
			template needsStoreBarrier(MemoryOrder ms)
			{
				enum bool needsStoreBarrier = ms == MemoryOrder.seq || isHoistOp!(ms);
			}
		}
		template atomicLoad(MemoryOrder ms = MemoryOrder.seq, T) if (!__traits(isFloating,T))
		{
			nothrow HeadUnshared!(T) atomicLoad(ref const shared T val)
			{
				static if(!__traits(isPOD,T))
				{
					static assert(false,"argument to atomicLoad() must be POD");
				}
				else
				{
					static if(T.sizeof == (byte).sizeof)
					{
						static if(needsLoadBarrier!(ms))
						{
							asm { mov DL,0; }
							asm { mov AL,0; }
							asm { mov ECX,val; }
							asm { lock; }
							asm { cmpxchg[ECX],DL; }
						}
						else
						{
							asm { mov EAX,val; }
							asm { mov AL,[EAX]; }
						}

					}
					else
					{
						static if(T.sizeof == (short).sizeof)
						{
							static if(needsLoadBarrier!(ms))
							{
								asm { mov DX,0; }
								asm { mov AX,0; }
								asm { mov ECX,val; }
								asm { lock; }
								asm { cmpxchg[ECX],DX; }
							}
							else
							{
								asm { mov EAX,val; }
								asm { mov AX,[EAX]; }
							}

						}
						else
						{
							static if(T.sizeof == (int).sizeof)
							{
								static if(needsLoadBarrier!(ms))
								{
									asm { mov EDX,0; }
									asm { mov EAX,0; }
									asm { mov ECX,val; }
									asm { lock; }
									asm { cmpxchg[ECX],EDX; }
								}
								else
								{
									asm { mov EAX,val; }
									asm { mov EAX,[EAX]; }
								}

							}
							else
							{
								static if(T.sizeof == (long).sizeof && has64BitCAS)
								{
									asm { push EDI; }
									asm { push EBX; }
									asm { mov EBX,0; }
									asm { mov ECX,0; }
									asm { mov EAX,0; }
									asm { mov EDX,0; }
									asm { mov EDI,val; }
									asm { lock; }
									asm { cmpxchg8b[EDI]; }
									asm { pop EBX; }
									asm { pop EDI; }
								}
								else
								{
									static assert(false,"Invalid template type specified.");
								}

							}

						}

					}

				}

			}

		}
		template atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V1) if (__traits(compiles,()
		{
			val = newval;
		}
		))
		{
			nothrow void atomicStore(ref shared T val, V1 newval)
			{
				static if(T.sizeof == (byte).sizeof)
				{
					static if(needsStoreBarrier!(ms))
					{
						asm { mov EAX,val; }
						asm { mov DL,newval; }
						asm { lock; }
						asm { xchg[EAX],DL; }
					}
					else
					{
						asm { mov EAX,val; }
						asm { mov DL,newval; }
						asm { mov[EAX],DL; }
					}

				}
				else
				{
					static if(T.sizeof == (short).sizeof)
					{
						static if(needsStoreBarrier!(ms))
						{
							asm { mov EAX,val; }
							asm { mov DX,newval; }
							asm { lock; }
							asm { xchg[EAX],DX; }
						}
						else
						{
							asm { mov EAX,val; }
							asm { mov DX,newval; }
							asm { mov[EAX],DX; }
						}

					}
					else
					{
						static if(T.sizeof == (int).sizeof)
						{
							static if(needsStoreBarrier!(ms))
							{
								asm { mov EAX,val; }
								asm { mov EDX,newval; }
								asm { lock; }
								asm { xchg[EAX],EDX; }
							}
							else
							{
								asm { mov EAX,val; }
								asm { mov EDX,newval; }
								asm { mov[EAX],EDX; }
							}

						}
						else
						{
							static if(T.sizeof == (long).sizeof && has64BitCAS)
							{
								asm { push EDI; }
								asm { push EBX; }
								asm { lea EDI,newval; }
								asm { mov EBX,[EDI]; }
								asm { mov ECX,4[EDI]; }
								asm { mov EDI,val; }
								asm { mov EAX,[EDI]; }
								asm { mov EDX,4[EDI]; }
								L1:
								asm { lock; }
								asm { cmpxchg8b[EDI]; }
								asm { jne L1; }
								asm { pop EBX; }
								asm { pop EDI; }
							}
							else
							{
								static assert(false,"Invalid template type specified.");
							}

						}

					}

				}

			}

		}
		nothrow void atomicFence();
	}
	else
	{
		version (AsmX86_64)
		{
			template atomicOp(string op, T, V1) if (__traits(compiles,mixin("val" ~ op ~ "mod")))
			{
				nothrow HeadUnshared!(T) atomicOp(ref shared T val, V1 mod)
				in
				{
					static if(T.sizeof > size_t.sizeof)
					{
						assert(atomicValueIsProperlyAligned!(size_t)(cast(size_t)&val));
					}
					else
					{
						assert(atomicValueIsProperlyAligned!(T)(cast(size_t)&val));
					}

				}
				body
				{
					static if(op == "+" || op == "-" || op == "*" || op == "/" || op == "%" || op == "^^" || op == "&" || op == "|" || op == "^" || op == "<<" || op == ">>" || op == ">>>" || op == "~" || op == "==" || op == "!=" || op == "<" || op == "<=" || op == ">" || op == ">=")
					{
						HeadUnshared!(T) get = atomicLoad!(MemoryOrder.raw)(val);
						mixin("return get " ~ op ~ " mod;");
					}
					else
					{
						static if(op == "+=" || op == "-=" || op == "*=" || op == "/=" || op == "%=" || op == "^^=" || op == "&=" || op == "|=" || op == "^=" || op == "<<=" || op == ">>=" || op == ">>>=")
						{
							HeadUnshared!(T) get,set;
							do
							{
								get = (set = atomicLoad!(MemoryOrder.raw)(val));
								mixin("set " ~ op ~ " mod;");
							}
							while (!cas(&val, get, set));
							return set;
						}
						else
						{
							static assert(false,"Operation not supported.");
						}

					}

				}

			}
			template cas(T, V1, V2) if (!is(T == class) && !is(T U : U*) && __traits(compiles,()
			{
				*here = writeThis;
			}
			))
			{
				nothrow bool cas(shared(T)* here, const V1 ifThis, const V2 writeThis)
				{
					return casImpl(here, ifThis, writeThis);
				}

			}
			template cas(T, V1, V2) if (is(T == class) && __traits(compiles,()
			{
				*here = writeThis;
			}
			))
			{
				nothrow bool cas(shared(T)* here, const shared(V1) ifThis, shared(V2) writeThis)
				{
					return casImpl(here, ifThis, writeThis);
				}

			}
			template cas(T, V1, V2) if (is(T U : U*) && __traits(compiles,()
			{
				*here = writeThis;
			}
			))
			{
				nothrow bool cas(shared(T)* here, const shared(V1)* ifThis, shared(V2)* writeThis)
				{
					return casImpl(here, ifThis, writeThis);
				}

			}
			private template casImpl(T, V1, V2)
			{
				nothrow bool casImpl(shared(T)* here, V1 ifThis, V2 writeThis)
				in
				{
					static if(T.sizeof > size_t.sizeof)
					{
						assert(atomicValueIsProperlyAligned!(size_t)(cast(size_t)here));
					}
					else
					{
						assert(atomicValueIsProperlyAligned!(T)(cast(size_t)here));
					}

				}
				body
				{
					static if(T.sizeof == (byte).sizeof)
					{
						asm { mov DL,writeThis; }
						asm { mov AL,ifThis; }
						asm { mov RCX,here; }
						asm { lock; }
						asm { cmpxchg[RCX],DL; }
						asm { setz AL; }
					}
					else
					{
						static if(T.sizeof == (short).sizeof)
						{
							asm { mov DX,writeThis; }
							asm { mov AX,ifThis; }
							asm { mov RCX,here; }
							asm { lock; }
							asm { cmpxchg[RCX],DX; }
							asm { setz AL; }
						}
						else
						{
							static if(T.sizeof == (int).sizeof)
							{
								asm { mov EDX,writeThis; }
								asm { mov EAX,ifThis; }
								asm { mov RCX,here; }
								asm { lock; }
								asm { cmpxchg[RCX],EDX; }
								asm { setz AL; }
							}
							else
							{
								static if(T.sizeof == (long).sizeof)
								{
									asm { mov RDX,writeThis; }
									asm { mov RAX,ifThis; }
									asm { mov RCX,here; }
									asm { lock; }
									asm { cmpxchg[RCX],RDX; }
									asm { setz AL; }
								}
								else
								{
									static assert(false,"Invalid template type specified.");
								}

							}

						}

					}

				}

			}

			enum MemoryOrder 
			{
				raw,
				acq,
				rel,
				seq,
			}
			deprecated("Please use MemoryOrder instead.") alias MemoryOrder msync;

			private 
			{
				template isHoistOp(MemoryOrder ms)
				{
					enum bool isHoistOp = ms == MemoryOrder.acq || ms == MemoryOrder.seq;
				}
				template isSinkOp(MemoryOrder ms)
				{
					enum bool isSinkOp = ms == MemoryOrder.rel || ms == MemoryOrder.seq;
				}
				template needsLoadBarrier(MemoryOrder ms)
				{
					enum bool needsLoadBarrier = ms != MemoryOrder.raw;
				}
				template needsStoreBarrier(MemoryOrder ms)
				{
					enum bool needsStoreBarrier = ms == MemoryOrder.seq || isHoistOp!(ms);
				}
			}
			template atomicLoad(MemoryOrder ms = MemoryOrder.seq, T) if (!__traits(isFloating,T))
			{
				nothrow HeadUnshared!(T) atomicLoad(ref const shared T val)
				{
					static if(T.sizeof == (byte).sizeof)
					{
						static if(needsLoadBarrier!(ms))
						{
							asm { mov DL,0; }
							asm { mov AL,0; }
							asm { mov RCX,val; }
							asm { lock; }
							asm { cmpxchg[RCX],DL; }
						}
						else
						{
							asm { mov RAX,val; }
							asm { mov AL,[RAX]; }
						}

					}
					else
					{
						static if(T.sizeof == (short).sizeof)
						{
							static if(needsLoadBarrier!(ms))
							{
								asm { mov DX,0; }
								asm { mov AX,0; }
								asm { mov RCX,val; }
								asm { lock; }
								asm { cmpxchg[RCX],DX; }
							}
							else
							{
								asm { mov RAX,val; }
								asm { mov AX,[RAX]; }
							}

						}
						else
						{
							static if(T.sizeof == (int).sizeof)
							{
								static if(needsLoadBarrier!(ms))
								{
									asm { mov EDX,0; }
									asm { mov EAX,0; }
									asm { mov RCX,val; }
									asm { lock; }
									asm { cmpxchg[RCX],EDX; }
								}
								else
								{
									asm { mov RAX,val; }
									asm { mov EAX,[RAX]; }
								}

							}
							else
							{
								static if(T.sizeof == (long).sizeof)
								{
									static if(needsLoadBarrier!(ms))
									{
										asm { mov RDX,0; }
										asm { mov RAX,0; }
										asm { mov RCX,val; }
										asm { lock; }
										asm { cmpxchg[RCX],RDX; }
									}
									else
									{
										asm { mov RAX,val; }
										asm { mov RAX,[RAX]; }
									}

								}
								else
								{
									static assert(false,"Invalid template type specified.");
								}

							}

						}

					}

				}

			}
			template atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V1) if (__traits(compiles,()
			{
				val = newval;
			}
			))
			{
				nothrow void atomicStore(ref shared T val, V1 newval)
				{
					static if(T.sizeof == (byte).sizeof)
					{
						static if(needsStoreBarrier!(ms))
						{
							asm { mov RAX,val; }
							asm { mov DL,newval; }
							asm { lock; }
							asm { xchg[RAX],DL; }
						}
						else
						{
							asm { mov RAX,val; }
							asm { mov DL,newval; }
							asm { mov[RAX],DL; }
						}

					}
					else
					{
						static if(T.sizeof == (short).sizeof)
						{
							static if(needsStoreBarrier!(ms))
							{
								asm { mov RAX,val; }
								asm { mov DX,newval; }
								asm { lock; }
								asm { xchg[RAX],DX; }
							}
							else
							{
								asm { mov RAX,val; }
								asm { mov DX,newval; }
								asm { mov[RAX],DX; }
							}

						}
						else
						{
							static if(T.sizeof == (int).sizeof)
							{
								static if(needsStoreBarrier!(ms))
								{
									asm { mov RAX,val; }
									asm { mov EDX,newval; }
									asm { lock; }
									asm { xchg[RAX],EDX; }
								}
								else
								{
									asm { mov RAX,val; }
									asm { mov EDX,newval; }
									asm { mov[RAX],EDX; }
								}

							}
							else
							{
								static if(T.sizeof == (long).sizeof && has64BitCAS)
								{
									static if(needsStoreBarrier!(ms))
									{
										asm { mov RAX,val; }
										asm { mov RDX,newval; }
										asm { lock; }
										asm { xchg[RAX],RDX; }
									}
									else
									{
										asm { mov RAX,val; }
										asm { mov RDX,newval; }
										asm { mov[RAX],RDX; }
									}

								}
								else
								{
									static assert(false,"Invalid template type specified.");
								}

							}

						}

					}

				}

			}
			nothrow void atomicFence();
		}
		else
		{
			version (GNU)
			{
				import gcc.atomics;
				import gcc.builtins;
				template atomicOp(string op, T, V1) if (__traits(compiles,mixin("val" ~ op ~ "mod")))
				{
					HeadUnshared!(T) atomicOp(ref shared T val, V1 mod)
					{
						static if(op == "+" || op == "-" || op == "*" || op == "/" || op == "%" || op == "^^" || op == "&" || op == "|" || op == "^" || op == "<<" || op == ">>" || op == ">>>" || op == "~" || op == "==" || op == "!=" || op == "<" || op == "<=" || op == ">" || op == ">=")
						{
							HeadUnshared!(T) get = atomicLoad!(MemoryOrder.raw)(val);
							mixin("return get " ~ op ~ " mod;");
						}
						else
						{
							static if(op == "+=" || op == "-=" || op == "*=" || op == "/=" || op == "%=" || op == "^^=" || op == "&=" || op == "|=" || op == "^=" || op == "<<=" || op == ">>=" || op == ">>>=")
							{
								HeadUnshared!(T) get,set;
								do
								{
									get = (set = atomicLoad!(MemoryOrder.raw)(val));
									mixin("set " ~ op ~ " mod;");
								}
								while (!cas(&val, get, set));
								return set;
							}
							else
							{
								static assert(false,"Operation not supported.");
							}

						}

					}

				}
				template cas(T, V1, V2) if (!is(T == class) && !is(T U : U*) && __traits(compiles,()
				{
					*here = writeThis;
				}
				))
				{
					bool cas(shared(T)* here, const V1 ifThis, const V2 writeThis)
					{
						return casImpl(here, ifThis, writeThis);
					}

				}
				template cas(T, V1, V2) if (is(T == class) && __traits(compiles,()
				{
					*here = writeThis;
				}
				))
				{
					bool cas(shared(T)* here, const shared(V1) ifThis, shared(V2) writeThis)
					{
						return casImpl(here, ifThis, writeThis);
					}

				}
				template cas(T, V1, V2) if (is(T U : U*) && __traits(compiles,()
				{
					*here = writeThis;
				}
				))
				{
					bool cas(shared(T)* here, const shared(V1)* ifThis, shared(V2)* writeThis)
					{
						return casImpl(here, ifThis, writeThis);
					}

				}
				private template casImpl(T, V1, V2)
				{
					bool casImpl(shared(T)* here, V1 ifThis, V2 writeThis)
					{
						bool res = void;
						static if(__traits(isFloating,T))
						{
							static if(T.sizeof == (int).sizeof)
							{
								static assert(is(T : float));
								res = __sync_bool_compare_and_swap!(int)(cast(shared(int*))here, *cast(int*)&ifThis, *cast(int*)&writeThis);
							}
							else
							{
								static if(T.sizeof == (long).sizeof)
								{
									static assert(is(T : double));
									res = __sync_bool_compare_and_swap!(long)(cast(shared(long*))here, *cast(long*)&ifThis, *cast(long*)&writeThis);
								}
								else
								{
									static assert(false,"Cannot atomically store 80-bit reals.");
								}

							}

						}
						else
						{
							static if(is(T P == U*,U) || _passAsSizeT!(T))
							{
								res = __sync_bool_compare_and_swap!(size_t)(cast(shared(size_t*))here, cast(size_t)ifThis, cast(size_t)writeThis);
							}
							else
							{
								static if(T.sizeof == (bool).sizeof)
								{
									res = __sync_bool_compare_and_swap!(ubyte)(cast(shared(ubyte*))here, ifThis ? 1 : 0, writeThis ? 1 : 0) ? 1 : 0;
								}
								else
								{
									res = __sync_bool_compare_and_swap!(T)(here, cast(T)ifThis, cast(T)writeThis);
								}

							}

						}

						return res;
					}

				}

				enum MemoryOrder 
				{
					raw,
					acq,
					rel,
					seq,
				}
				deprecated("Please use MemoryOrder instead.") alias MemoryOrder msync;

				private 
				{
					template isHoistOp(MemoryOrder ms)
					{
						enum bool isHoistOp = ms == MemoryOrder.acq || ms == MemoryOrder.seq;
					}
					template isSinkOp(MemoryOrder ms)
					{
						enum bool isSinkOp = ms == MemoryOrder.rel || ms == MemoryOrder.seq;
					}
					template needsLoadBarrier(MemoryOrder ms)
					{
						enum bool needsLoadBarrier = ms != MemoryOrder.raw;
					}
					template needsStoreBarrier(MemoryOrder ms)
					{
						const bool needsStoreBarrier = ms == MemoryOrder.seq || isHoistOp!(ms);

					}
					template _passAsSizeT(T)
					{
						static if(is(T P == U*,U))
						{
							enum _passAsSizeT = true;
						}
						else
						{
							static if(is(T == interface) || is(T == class))
							{
								enum _passAsSizeT = true;
							}
							else
							{
								enum _passAsSizeT = false;
							}
						}
					}
				}
				template atomicLoad(MemoryOrder ms = MemoryOrder.seq, T) if (!__traits(isFloating,T))
				{
					HeadUnshared!(T) atomicLoad(ref const shared T val)
					{
						static if(needsLoadBarrier!(ms))
						{
							__sync_synchronize();
						}

						return cast(HeadUnshared!(T))val;
					}

				}
				template atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V1) if (__traits(compiles,()
				{
					val = newval;
				}
				))
				{
					void atomicStore(ref shared T val, V1 newval)
					{
						static if(needsLoadBarrier!(ms))
						{
							__sync_synchronize();
						}

						val = newval;
					}

				}
				nothrow void atomicFence();
			}
		}
	}
}
template atomicLoad(MemoryOrder ms = MemoryOrder.seq, T) if (__traits(isFloating,T))
{
	nothrow HeadUnshared!(T) atomicLoad(ref const shared T val)
	{
		static if(T.sizeof == (int).sizeof)
		{
			static assert(is(T : float));
			auto ptr = cast(shared(const(int*)))&val;
			auto asInt = atomicLoad!(ms)(*ptr);
			return *cast(typeof(return)*)&asInt;
		}
		else
		{
			static if(T.sizeof == (long).sizeof)
			{
				static assert(is(T : double));
				auto ptr = cast(shared(const(long*)))&val;
				auto asLong = atomicLoad!(ms)(*ptr);
				return *cast(typeof(return)*)&asLong;
			}
			else
			{
				static assert(0,"Cannot atomically load 80-bit reals.");
			}

		}

	}

}
version (unittest)
{
	template testCAS(T)
	{
		pure nothrow void testCAS(T val)
		in
		{
			assert(val !is T.init);
		}
		body
		{
			T base;
			shared(T) atom;
			assert(base !is val,T.stringof);
			assert(atom is base,T.stringof);
			assert(cas(&atom, base, val),T.stringof);
			assert(atom is val,T.stringof);
			assert(!cas(&atom, base, base),T.stringof);
			assert(atom is val,T.stringof);
		}

	}
	template testLoadStore(MemoryOrder ms = MemoryOrder.seq, T)
	{
		pure nothrow void testLoadStore(T val = T.init + 1)
		{
			T base = cast(T)0;
			shared(T) atom = cast(T)0;
			assert(base !is val);
			assert(atom is base);
			atomicStore!(ms)(atom, val);
			base = atomicLoad!(ms)(atom);
			assert(base is val,T.stringof);
			assert(atom is val);
		}

	}
	template testType(T)
	{
		pure nothrow void testType(T val = T.init + 1)
		{
			testCAS!(T)(val);
			testLoadStore!(MemoryOrder.seq, T)(val);
			testLoadStore!(MemoryOrder.raw, T)(val);
		}

	}
}
