36 lines
2.1 KiB
Markdown
36 lines
2.1 KiB
Markdown
## cond
|
||
|
||
[sync.Cond](https://golang.org/pkg/sync/#Cond) — примитив синхронизации для эффективных межгорутинных нотификаций.
|
||
|
||
Обычно использование выглядит так: одни горутины ждут выполнения некоторого условия,
|
||
а другие горутины выполняют это условие и информируют ждущих.
|
||
|
||
### Что нужно сделать?
|
||
|
||
Нужно написать реализацию Cond используя каналы.
|
||
|
||
Использование пакета [sync](https://golang.org/pkg/sync) в этой задаче запрещено!
|
||
|
||
```go
|
||
type Cond struct {
|
||
L Locker
|
||
}
|
||
|
||
func New(l Locker) *Cond {}
|
||
|
||
func (c *Cond) Wait() {}
|
||
func (c *Cond) Signal() {}
|
||
func (c *Cond) Broadcast() {}
|
||
```
|
||
|
||
`Locker` это [sync.Locker](https://golang.org/pkg/sync/#Locker), но мы не хотим использовать [sync](https://golang.org/pkg/sync).
|
||
|
||
У каждого `Cond` есть блокировка `L`, передающаяся в конструкторе.
|
||
`Cond` поддерживает FIFO очередь ожидающих горутин.
|
||
|
||
* `Wait()` паникует, если `L` не взята.
|
||
* `Wait()` добавляет текущую горутину в очередь, возвращает блокировку `L`, блокирует текущую горутину.
|
||
Заснувшая горутина может быть разбужена другой горутиной через вызов `Signal()` или `Broadcast()`.
|
||
При просыпании засыпавшая горутина продолжит исполнение, возьмёт `L` и завершит вызов `Wait()`.
|
||
* `Signal()` извлекает и разблокирует первую блокировку из очереди, если такая есть, иначе no-op.
|
||
* `Broadcast()` извлекает и разблокирует все блокировки из очереди. no-op, если очередь пустая.
|