package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
type Semaphore chan struct{}
func NewSemaphore(value int, maxcapacity int) Semaphore {
channel := make(Semaphore, maxcapacity)
for i := 0; i < value; i++ {
channel <- struct{}{}
}
return channel
}
func (s Semaphore) Acquire() {
<-s
}
func (s Semaphore) Release() {
s <- struct{}{}
}
const (
initialPartyCapacity = 5
maxPartyCapacity = 10
totalGuests = 15
)
func guest(id int, partyRoom Semaphore, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Guest %d is trying to enter the party room\n", id)
partyRoom.Acquire()
fmt.Printf("Guest %d has entered the party room\n", id)
// Party for a random duration
partyDuration := time.Duration(rand.Intn(3)+1) * time.Second
time.Sleep(partyDuration)
fmt.Printf("Guest %d is leaving the party room\n", id)
partyRoom.Release()
}
func expandPartyRoom(partyRoom Semaphore) {
time.Sleep(5 * time.Second) // Wait for 5 seconds before expanding
fmt.Println("Expanding the party room capacity!")
partyRoom.Release()
partyRoom.Release()
}
func main() {
partyRoom := NewSemaphore(initialPartyCapacity, maxPartyCapacity)
var wg sync.WaitGroup
// Start the party room expansion routine
go expandPartyRoom(partyRoom)
for i := 0; i < totalGuests; i++ {
wg.Add(1)
go guest(i, partyRoom, &wg)
// Small delay to make output more readable
time.Sleep(100 * time.Millisecond)
}
wg.Wait()
fmt.Println("The party is over!")
}