Sobes.tech
Middle

Define the Sem interface and its methods.

sobes.tech AI

Answer from AI

The Sem interface describes a semaphore with the ability to lock and release resources, as well as to obtain status information.

For implementation, a buffered channel in Go can be used, where the buffer size corresponds to the capacity — the maximum number of goroutines that can operate simultaneously.

  • Lock() error — attempts to acquire a slot; if the channel is full (all slots are occupied), it returns an error.
  • TryLock() bool — attempts to acquire a slot without blocking; returns true if successful.
  • Release() — releases a slot, freeing space in the channel.
  • Cap() int — returns the capacity of the channel (maximum number of slots).
  • FreeSpace() int — returns the number of free slots (available space in the channel).

Example implementation:

Type Sem interface {
    Lock() error
    TryLock() bool
    Release()
    Cap() int
    FreeSpace() int
}

Type semaphore struct {
    ch chan struct{}
}

func NewSemaphore(capacity int) Sem {
    return &semaphore{ch: make(chan struct{}, capacity)}
}

func (s *semaphore) Lock() error {
    select {
    case s.ch <- struct{}{}:
        return nil
    default:
        return errors.New("semaphore is full")
    }
}

func (s *semaphore) TryLock() bool {
    select {
    case s.ch <- struct{}{}:
        return true
    default:
        return false
    }
}

func (s *semaphore) Release() {
    select {
    case <-s.ch:
    default:
        panic("release called on empty semaphore")
    }
}

func (s *semaphore) Cap() int {
    return cap(s.ch)
}

func (s *semaphore) FreeSpace() int {
    return cap(s.ch) - len(s.ch)
}

Thus, the channel acts as a counter for occupied slots, and the buffer as the maximum number of goroutines that can run simultaneously. Mutex is not needed here, as channel operations are thread-safe.