Skip to content

Commit ddd8686

Browse files
authored
pkg/component/runtime: use atomic.Pointer rather than locks for current component (#7369)
Locking to obtain write boundaries when obtaining the current component.Component makes use of a read-write mutex. This protection only protects the access and does not ensure that the current is not mutated with a logical race. The same semantics can be obtained more cheaply and without the risk of recursive read-lock deadlock by using an atomic value. This could either be via atomic.Value or atomic.Pointer; atomic.Pointer is chosen since it can be type-defined in code, rather than by the addition of a comment.
1 parent 5f3bfa3 commit ddd8686

File tree

1 file changed

+11
-16
lines changed

1 file changed

+11
-16
lines changed

pkg/component/runtime/runtime.go

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,9 @@ type componentRuntimeState struct {
8080
logger *logger.Logger
8181
comm *runtimeComm
8282

83-
id string
84-
currCompMx sync.RWMutex
85-
currComp component.Component
86-
runtime componentRuntime
83+
id string
84+
currComp atomic.Pointer[component.Component]
85+
runtime componentRuntime
8786

8887
shuttingDown atomic.Bool
8988

@@ -105,19 +104,19 @@ func newComponentRuntimeState(m *Manager, logger *logger.Logger, monitor Monitor
105104
}
106105

107106
state := &componentRuntimeState{
108-
manager: m,
109-
logger: logger,
110-
comm: comm,
111-
id: comp.ID,
112-
currComp: comp,
113-
runtime: runtime,
107+
manager: m,
108+
logger: logger,
109+
comm: comm,
110+
id: comp.ID,
111+
runtime: runtime,
114112
latestState: ComponentState{
115113
State: client.UnitStateStarting,
116114
Message: "Starting",
117115
Units: nil,
118116
},
119117
actions: make(map[string]func(response *proto.ActionResponse)),
120118
}
119+
state.currComp.Store(&comp)
121120

122121
// Start the goroutine that spawns and monitors the component runtime.
123122
go state.runLoop()
@@ -160,15 +159,11 @@ func (s *componentRuntimeState) runLoop() {
160159
}
161160

162161
func (s *componentRuntimeState) getCurrent() component.Component {
163-
s.currCompMx.RLock()
164-
defer s.currCompMx.RUnlock()
165-
return s.currComp
162+
return *s.currComp.Load()
166163
}
167164

168165
func (s *componentRuntimeState) setCurrent(current component.Component) {
169-
s.currCompMx.Lock()
170-
s.currComp = current
171-
s.currCompMx.Unlock()
166+
s.currComp.Store(&current)
172167
}
173168

174169
func (s *componentRuntimeState) getLatest() ComponentState {

0 commit comments

Comments
 (0)