// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package atomic

import 

// A Bool is an atomic boolean value.
// The zero value is false.
type Bool struct {
	_ noCopy
	v uint32
}

// Load atomically loads and returns the value stored in x.
func ( *Bool) () bool { return LoadUint32(&.v) != 0 }

// Store atomically stores val into x.
func ( *Bool) ( bool) { StoreUint32(&.v, b32()) }

// Swap atomically stores new into x and returns the previous value.
func ( *Bool) ( bool) ( bool) { return SwapUint32(&.v, b32()) != 0 }

// CompareAndSwap executes the compare-and-swap operation for the boolean value x.
func ( *Bool) (,  bool) ( bool) {
	return CompareAndSwapUint32(&.v, b32(), b32())
}

// b32 returns a uint32 0 or 1 representing b.
func b32( bool) uint32 {
	if  {
		return 1
	}
	return 0
}

// For testing *Pointer[T]'s methods can be inlined.
// Keep in sync with cmd/compile/internal/test/inl_test.go:TestIntendedInlining.
var _ = &Pointer[int]{}

// A Pointer is an atomic pointer of type *T. The zero value is a nil *T.
type Pointer[ any] struct {
	// Mention *T in a field to disallow conversion between Pointer types.
	// See go.dev/issue/56603 for more details.
	// Use *T, not T, to avoid spurious recursive type definition errors.
	_ [0]*

	_ noCopy
	v unsafe.Pointer
}

// Load atomically loads and returns the value stored in x.
func ( *Pointer[]) () * { return (*)(LoadPointer(&.v)) }

// Store atomically stores val into x.
func ( *Pointer[]) ( *) { StorePointer(&.v, unsafe.Pointer()) }

// Swap atomically stores new into x and returns the previous value.
func ( *Pointer[]) ( *) ( *) { return (*)(SwapPointer(&.v, unsafe.Pointer())) }

// CompareAndSwap executes the compare-and-swap operation for x.
func ( *Pointer[]) (,  *) ( bool) {
	return CompareAndSwapPointer(&.v, unsafe.Pointer(), unsafe.Pointer())
}

// An Int32 is an atomic int32. The zero value is zero.
type Int32 struct {
	_ noCopy
	v int32
}

// Load atomically loads and returns the value stored in x.
func ( *Int32) () int32 { return LoadInt32(&.v) }

// Store atomically stores val into x.
func ( *Int32) ( int32) { StoreInt32(&.v, ) }

// Swap atomically stores new into x and returns the previous value.
func ( *Int32) ( int32) ( int32) { return SwapInt32(&.v, ) }

// CompareAndSwap executes the compare-and-swap operation for x.
func ( *Int32) (,  int32) ( bool) {
	return CompareAndSwapInt32(&.v, , )
}

// Add atomically adds delta to x and returns the new value.
func ( *Int32) ( int32) ( int32) { return AddInt32(&.v, ) }

// An Int64 is an atomic int64. The zero value is zero.
type Int64 struct {
	_ noCopy
	_ align64
	v int64
}

// Load atomically loads and returns the value stored in x.
func ( *Int64) () int64 { return LoadInt64(&.v) }

// Store atomically stores val into x.
func ( *Int64) ( int64) { StoreInt64(&.v, ) }

// Swap atomically stores new into x and returns the previous value.
func ( *Int64) ( int64) ( int64) { return SwapInt64(&.v, ) }

// CompareAndSwap executes the compare-and-swap operation for x.
func ( *Int64) (,  int64) ( bool) {
	return CompareAndSwapInt64(&.v, , )
}

// Add atomically adds delta to x and returns the new value.
func ( *Int64) ( int64) ( int64) { return AddInt64(&.v, ) }

// A Uint32 is an atomic uint32. The zero value is zero.
type Uint32 struct {
	_ noCopy
	v uint32
}

// Load atomically loads and returns the value stored in x.
func ( *Uint32) () uint32 { return LoadUint32(&.v) }

// Store atomically stores val into x.
func ( *Uint32) ( uint32) { StoreUint32(&.v, ) }

// Swap atomically stores new into x and returns the previous value.
func ( *Uint32) ( uint32) ( uint32) { return SwapUint32(&.v, ) }

// CompareAndSwap executes the compare-and-swap operation for x.
func ( *Uint32) (,  uint32) ( bool) {
	return CompareAndSwapUint32(&.v, , )
}

// Add atomically adds delta to x and returns the new value.
func ( *Uint32) ( uint32) ( uint32) { return AddUint32(&.v, ) }

// A Uint64 is an atomic uint64. The zero value is zero.
type Uint64 struct {
	_ noCopy
	_ align64
	v uint64
}

// Load atomically loads and returns the value stored in x.
func ( *Uint64) () uint64 { return LoadUint64(&.v) }

// Store atomically stores val into x.
func ( *Uint64) ( uint64) { StoreUint64(&.v, ) }

// Swap atomically stores new into x and returns the previous value.
func ( *Uint64) ( uint64) ( uint64) { return SwapUint64(&.v, ) }

// CompareAndSwap executes the compare-and-swap operation for x.
func ( *Uint64) (,  uint64) ( bool) {
	return CompareAndSwapUint64(&.v, , )
}

// Add atomically adds delta to x and returns the new value.
func ( *Uint64) ( uint64) ( uint64) { return AddUint64(&.v, ) }

// A Uintptr is an atomic uintptr. The zero value is zero.
type Uintptr struct {
	_ noCopy
	v uintptr
}

// Load atomically loads and returns the value stored in x.
func ( *Uintptr) () uintptr { return LoadUintptr(&.v) }

// Store atomically stores val into x.
func ( *Uintptr) ( uintptr) { StoreUintptr(&.v, ) }

// Swap atomically stores new into x and returns the previous value.
func ( *Uintptr) ( uintptr) ( uintptr) { return SwapUintptr(&.v, ) }

// CompareAndSwap executes the compare-and-swap operation for x.
func ( *Uintptr) (,  uintptr) ( bool) {
	return CompareAndSwapUintptr(&.v, , )
}

// Add atomically adds delta to x and returns the new value.
func ( *Uintptr) ( uintptr) ( uintptr) { return AddUintptr(&.v, ) }

// noCopy may be added to structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
//
// Note that it must not be embedded, due to the Lock and Unlock methods.
type noCopy struct{}

// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) ()   {}
func (*noCopy) () {}

// align64 may be added to structs that must be 64-bit aligned.
// This struct is recognized by a special case in the compiler
// and will not work if copied to any other package.
type align64 struct{}