package main

import (
	"fmt"
	"sync"
)

// section: broken
// Counter has a race condition - multiple goroutines access count without synchronization
type Counter struct {
	count int
}

// Increment has a race condition
func (c *Counter) Increment() {
	// This is NOT atomic - it's actually three operations:
	// 1. Read c.count
	// 2. Add 1
	// 3. Write back to c.count
	c.count++
}

// Value returns the current count (also has race condition with Increment)
func (c *Counter) Value() int {
	return c.count
}

// section: broken

// section: main
func main() {
	counter := &Counter{}
	var wg sync.WaitGroup

	// Launch 1000 goroutines that each increment 100 times
	// Expected result: 100,000
	// Actual result: Less than 100,000 due to race condition
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for j := 0; j < 100; j++ {
				counter.Increment()
			}
		}()
	}

	wg.Wait()
	fmt.Printf("Expected: 100000\n")
	fmt.Printf("Actual:   %d\n", counter.Value())
	fmt.Println("\nRun with: go run -race main.go")
	fmt.Println("To see the race detector find this bug!")
}

// section: main

// section: output
// Output when run WITHOUT -race flag:
// Expected: 100000
// Actual:   93547  (or some other number less than 100000)
//
// Run with: go run -race main.go
// To see the race detector find this bug!
//
// Output when run WITH -race flag:
// ==================
// WARNING: DATA RACE
// Read at 0x00c00001a0a8 by goroutine 8:
//   main.(*Counter).Increment()
//       /path/to/main.go:18 +0x3a
// ...
// section: output
