package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

func Published() int {
	var value int
	done := make(chan struct{})
	go func() { value = 42; close(done) }()
	<-done
	return value
}

// Both read operations are atomic. The compound business operation is not.
func BrokenReservation() int64 {
	var stock atomic.Int64
	stock.Store(1)
	var ready, finished sync.WaitGroup
	ready.Add(2)
	finished.Add(2)
	release := make(chan struct{})
	for range 2 {
		go func() {
			defer finished.Done()
			available := stock.Load() > 0
			ready.Done()
			<-release
			if available {
				stock.Add(-1)
			}
		}()
	}
	ready.Wait()
	close(release)
	finished.Wait()
	return stock.Load()
}
func Reserve(stock *atomic.Int64) bool {
	for {
		n := stock.Load()
		if n <= 0 {
			return false
		}
		if stock.CompareAndSwap(n, n-1) {
			return true
		}
	}
}
func main() {
	fmt.Println("published:", Published())
	fmt.Println("atomic but oversold:", BrokenReservation())
	var stock atomic.Int64
	stock.Store(1)
	fmt.Println("CAS:", Reserve(&stock), Reserve(&stock), stock.Load())
}
