blob: 9b1df419e292c789b1f73f459f6d43d16c0745a1 [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -05001// Copyright 2015 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Package wait provides utility functions for polling, listening using Go
16// channel.
17package wait
18
19import (
20 "log"
21 "sync"
22)
23
24// Wait is an interface that provides the ability to wait and trigger events that
25// are associated with IDs.
26type Wait interface {
27 // Register waits returns a chan that waits on the given ID.
28 // The chan will be triggered when Trigger is called with
29 // the same ID.
30 Register(id uint64) <-chan interface{}
31 // Trigger triggers the waiting chans with the given ID.
32 Trigger(id uint64, x interface{})
33 IsRegistered(id uint64) bool
34}
35
36type list struct {
37 l sync.RWMutex
38 m map[uint64]chan interface{}
39}
40
41// New creates a Wait.
42func New() Wait {
43 return &list{m: make(map[uint64]chan interface{})}
44}
45
46func (w *list) Register(id uint64) <-chan interface{} {
47 w.l.Lock()
48 defer w.l.Unlock()
49 ch := w.m[id]
50 if ch == nil {
51 ch = make(chan interface{}, 1)
52 w.m[id] = ch
53 } else {
54 log.Panicf("dup id %x", id)
55 }
56 return ch
57}
58
59func (w *list) Trigger(id uint64, x interface{}) {
60 w.l.Lock()
61 ch := w.m[id]
62 delete(w.m, id)
63 w.l.Unlock()
64 if ch != nil {
65 ch <- x
66 close(ch)
67 }
68}
69
70func (w *list) IsRegistered(id uint64) bool {
71 w.l.RLock()
72 defer w.l.RUnlock()
73 _, ok := w.m[id]
74 return ok
75}
76
77type waitWithResponse struct {
78 ch <-chan interface{}
79}
80
81func NewWithResponse(ch <-chan interface{}) Wait {
82 return &waitWithResponse{ch: ch}
83}
84
85func (w *waitWithResponse) Register(id uint64) <-chan interface{} {
86 return w.ch
87}
88func (w *waitWithResponse) Trigger(id uint64, x interface{}) {}
89func (w *waitWithResponse) IsRegistered(id uint64) bool {
90 panic("waitWithResponse.IsRegistered() shouldn't be called")
91}