This repository has been archived by the owner on Apr 3, 2023. It is now read-only.
/
stoppable.go
70 lines (56 loc) · 1.7 KB
/
stoppable.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"fmt"
"sync"
"k8s.io/klog"
)
// Stoppable implements the standard stop / shutdown logic
type Stoppable struct {
// mutex is used to enforce only a single call to Stop is active.
// Needed because we allow stopping through an http endpoint and
// allowing concurrent stoppers leads to stack traces.
// We also use it for lazy-init
mutex sync.Mutex
shutdown bool
stopChannel chan struct{}
}
// StopChannel gets the stopChannel, initializing it if needed
func (s *Stoppable) StopChannel() <-chan struct{} {
s.mutex.Lock()
defer s.mutex.Unlock()
if s.stopChannel == nil {
s.stopChannel = make(chan struct{})
}
return s.stopChannel
}
// Stop stops the controller.
func (s *Stoppable) Stop() error {
s.mutex.Lock()
defer s.mutex.Unlock()
if s.shutdown {
return fmt.Errorf("shutdown already in progress")
}
// We initialize the channel to avoid a race if we Stop before anyone is watching
if s.stopChannel == nil {
s.stopChannel = make(chan struct{})
}
close(s.stopChannel)
klog.Infof("shutting down controller")
s.shutdown = true
return nil
}
func (s *Stoppable) StopRequested() bool {
return s.shutdown
}