1
1
/****************************************************************************
2
- * Copyright 2019, Optimizely, Inc. and contributors *
2
+ * Copyright 2019-2020 , Optimizely, Inc. and contributors *
3
3
* *
4
4
* Licensed under the Apache License, Version 2.0 (the "License"); *
5
5
* you may not use this file except in compliance with the License. *
@@ -19,6 +19,7 @@ package notification
19
19
20
20
import (
21
21
"fmt"
22
+ "sync"
22
23
"sync/atomic"
23
24
24
25
"github.com/optimizely/go-sdk/pkg/logging"
@@ -37,6 +38,7 @@ type Manager interface {
37
38
type AtomicManager struct {
38
39
handlers map [uint32 ]func (interface {})
39
40
counter uint32
41
+ lock sync.RWMutex
40
42
}
41
43
42
44
// NewAtomicManager creates a new instance of the atomic manager
@@ -48,13 +50,19 @@ func NewAtomicManager() *AtomicManager {
48
50
49
51
// Add adds the given handler
50
52
func (am * AtomicManager ) Add (newHandler func (interface {})) (int , error ) {
53
+ am .lock .Lock ()
54
+ defer am .lock .Unlock ()
55
+
51
56
atomic .AddUint32 (& am .counter , 1 )
52
57
am .handlers [am .counter ] = newHandler
53
58
return int (am .counter ), nil
54
59
}
55
60
56
61
// Remove removes handler with the given id
57
62
func (am * AtomicManager ) Remove (id int ) {
63
+ am .lock .Lock ()
64
+ defer am .lock .Unlock ()
65
+
58
66
handlerID := uint32 (id )
59
67
if _ , ok := am .handlers [handlerID ]; ok {
60
68
delete (am .handlers , handlerID )
@@ -66,7 +74,19 @@ func (am *AtomicManager) Remove(id int) {
66
74
67
75
// Send sends the notification to the registered handlers
68
76
func (am * AtomicManager ) Send (notification interface {}) {
69
- for _ , handler := range am .handlers {
77
+ // copying handler to avoid race condition
78
+ handlers := am .copyHandlers ()
79
+ for _ , handler := range handlers {
70
80
handler (notification )
71
81
}
72
82
}
83
+
84
+ // Return a copy of the given handlers
85
+ func (am * AtomicManager ) copyHandlers () (handlers []func (interface {})) {
86
+ am .lock .RLock ()
87
+ defer am .lock .RUnlock ()
88
+ for _ , v := range am .handlers {
89
+ handlers = append (handlers , v )
90
+ }
91
+ return handlers
92
+ }
0 commit comments