forked from aws/amazon-ssm-agent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cancelflag.go
116 lines (97 loc) · 3.66 KB
/
cancelflag.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 task contains a default implementation of the interfaces in the task package.
package task
import (
"sync"
)
// State represents the state of a job.
type State int
const (
// Canceled indicates a job for which cancellation has been requested.
Canceled State = 1
// Completed indicates a completed job.
Completed State = 2
// ShutDown indicates a job for which ShutDown has been requested.
ShutDown State = 3
)
// CancelFlag is an object that is passed to any job submitted to a task in order to
// communicated job cancellation. Job cancellation has to be cooperative.
type CancelFlag interface {
// Canceled returns true if a cancel or Shutdown has been requested, false otherwise.
// This method should be called periodically in the job.
Canceled() bool
// Set sets the state of this flag and wakes up waiting callers.
Set(state State)
// ShutDown returns true if a ShutDown has been requested, false otherwise.
// This method should be called periodically in the job.
ShutDown() bool
// State returns the current flag state
State() State
// Wait blocks the caller until either a cancel has been requested or the
// task has completed normally. Returns Canceled if cancel has been requested,
// or Completed if the task completed normally.
// This is intended to be used to wake up a job that may be waiting on some resources, as follows:
// The main job starts a go routine that calls Wait. The main job then does its processing.
// During processing the job may be waiting on certain events/conditions.
// In the go routine, once Wait returns, if the return value indicates that a cancel
// request has been received, the go routine wakes up the running job.
Wait() (state State)
}
// ChanneledCancelFlag is a default implementation of the task.CancelFlag interface.
type ChanneledCancelFlag struct {
state State
ch chan struct{}
closed bool
m sync.RWMutex
}
// NewChanneledCancelFlag creates a new instance of ChanneledCancelFlag.
func NewChanneledCancelFlag() *ChanneledCancelFlag {
flag := &ChanneledCancelFlag{ch: make(chan struct{})}
return flag
}
// Canceled returns true if this flag has been set to Cancel state, false otherwise.
func (t *ChanneledCancelFlag) Canceled() bool {
t.m.RLock()
defer t.m.RUnlock()
return t.state == Canceled || t.state == ShutDown
}
// ShutDown returns true if this flag has been set to ShutDown state, false otherwise.
func (t *ChanneledCancelFlag) ShutDown() bool {
t.m.RLock()
defer t.m.RUnlock()
return t.state == ShutDown
}
// State returns the current flag state.
func (t *ChanneledCancelFlag) State() State {
t.m.RLock()
defer t.m.RUnlock()
return t.state
}
// Wait blocks until the flag is set to either Cancel or Completed state. Returns the state.
func (t *ChanneledCancelFlag) Wait() (state State) {
<-t.ch
return t.State()
}
// Set sets the state of this flag and wakes up waiting callers.
func (t *ChanneledCancelFlag) Set(state State) {
t.m.Lock()
defer t.m.Unlock()
t.state = state
// close channel to wake up routines that are waiting
if !t.closed {
// avoid double closing, which would panic
close(t.ch)
t.closed = true
}
}