package main

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

// tahanBackingArray mengembalikan potongan kecil dari array besar.
// variabel kecil masih menahan backing array berukuran satu juta elemen,
// sedangkan salinan benar-benar berdiri sendiri.
func tahanBackingArray() (kecil, salinan []int) {
	besar := make([]int, 1_000_000) // ±8 MiB
	for i := range besar {
		besar[i] = i
	}
	kecil = besar[:10]
	salinan = make([]int, 10)
	copy(salinan, kecil)
	return kecil, salinan
}

func main() {
	fmt.Println("goroutine awal :", runtime.NumGoroutine())

	// pola pekerja: goroutine menunggu sinyal penutupan channel.
	// jika channel tidak pernah ditutup, goroutine menunggu selamanya.
	const jumlah = 5
	var siap atomic.Int32
	sinyal := make([]chan struct{}, jumlah)
	for i := range sinyal {
		sinyal[i] = make(chan struct{})
		go func() {
			siap.Add(1)
			<-sinyal[i]
		}()
	}

	// tunggu sampai seluruh pekerja tercipta dan menunggu
	for siap.Load() < jumlah {
		time.Sleep(time.Millisecond)
	}
	fmt.Println("pekerja menunggu:", runtime.NumGoroutine())

	// cleanup: tutup setiap channel sehingga pekerja boleh selesai
	for i := range sinyal {
		close(sinyal[i])
	}
	for runtime.NumGoroutine() > 1 {
		time.Sleep(time.Millisecond)
	}
	fmt.Println("setelah cleanup :", runtime.NumGoroutine())

	kecil, salinan := tahanBackingArray()
	fmt.Println("kecil   -> len:", len(kecil), "cap:", cap(kecil))
	fmt.Println("salinan -> len:", len(salinan), "cap:", cap(salinan))
}
