20
20
#import " MTRLogging_Internal.h"
21
21
#import " MTRServerAttribute_Internal.h"
22
22
#import " MTRServerEndpoint_Internal.h"
23
+ #import " MTRUnfairLock.h"
23
24
#import " NSDataSpanConversion.h"
25
+
24
26
#import < Matter/MTRServerAttribute.h>
25
27
26
28
#include < app/reporting/reporting.h>
32
34
33
35
MTR_DIRECT_MEMBERS
34
36
@implementation MTRServerAttribute {
37
+ // _lock always protects access to _deviceController, _value, and
38
+ // _parentCluster. _serializedValue is protected when we are modifying it
39
+ // directly while we have no _deviceController. Once we have one,
40
+ // _serializedValue is only modified on the Matter thread.
41
+ os_unfair_lock _lock;
35
42
MTRDeviceController * __weak _deviceController;
43
+ NSDictionary <NSString *, id > * _value;
44
+ app::ConcreteClusterPath _parentCluster;
36
45
}
37
46
38
47
- (nullable instancetype )initAttributeWithID : (NSNumber *)attributeID initialValue : (NSDictionary <NSString *, id> *)value requiredReadPrivilege : (MTRAccessControlEntryPrivilege)requiredReadPrivilege writable : (BOOL )writable
@@ -66,6 +75,7 @@ - (nullable instancetype)initWithAttributeID:(NSNumber *)attributeID value:(NSDi
66
75
return nil ;
67
76
}
68
77
78
+ _lock = OS_UNFAIR_LOCK_INIT;
69
79
_attributeID = attributeID;
70
80
_requiredReadPrivilege = requiredReadPrivilege;
71
81
_writable = writable;
@@ -121,7 +131,10 @@ - (BOOL)setValueInternal:(NSDictionary<NSString *, id> *)value logIfNotAssociate
121
131
}
122
132
}
123
133
124
- // We serialized properly, so should be good to go on the value.
134
+ // We serialized properly, so should be good to go on the value. Lock
135
+ // around our ivar accesses.
136
+ std::lock_guard lock (_lock);
137
+
125
138
_value = [value copy ];
126
139
127
140
MTRDeviceController * deviceController = _deviceController;
@@ -147,8 +160,16 @@ - (BOOL)setValueInternal:(NSDictionary<NSString *, id> *)value logIfNotAssociate
147
160
return YES ;
148
161
}
149
162
163
+ - (NSDictionary <NSString *, id> *)value
164
+ {
165
+ std::lock_guard lock (_lock);
166
+ return [_value copy ];
167
+ }
168
+
150
169
- (BOOL )associateWithController : (nullable MTRDeviceController *)controller
151
170
{
171
+ std::lock_guard lock (_lock);
172
+
152
173
MTRDeviceController * existingController = _deviceController;
153
174
if (existingController != nil ) {
154
175
#if MTR_PER_CONTROLLER_STORAGE_ENABLED
@@ -167,7 +188,34 @@ - (BOOL)associateWithController:(nullable MTRDeviceController *)controller
167
188
168
189
- (void )invalidate
169
190
{
191
+ std::lock_guard lock (_lock);
192
+
170
193
_deviceController = nil ;
171
194
}
172
195
196
+ - (BOOL )addToCluster : (const app::ConcreteClusterPath &)cluster
197
+ {
198
+ std::lock_guard lock (_lock);
199
+
200
+ if (_parentCluster.mClusterId != kInvalidClusterId ) {
201
+ MTR_LOG_ERROR (" Cannot add attribute to cluster " ChipLogFormatMEI " ; already added to cluster " ChipLogFormatMEI, ChipLogValueMEI (cluster.mClusterId ), ChipLogValueMEI (_parentCluster.mClusterId ));
202
+ return NO ;
203
+ }
204
+
205
+ _parentCluster = cluster;
206
+ return YES ;
207
+ }
208
+
209
+ - (void )updateParentCluster : (const app::ConcreteClusterPath &)cluster
210
+ {
211
+ std::lock_guard lock (_lock);
212
+ _parentCluster = cluster;
213
+ }
214
+
215
+ - (const chip::app::ConcreteClusterPath &)parentCluster
216
+ {
217
+ std::lock_guard lock (_lock);
218
+ return _parentCluster;
219
+ }
220
+
173
221
@end
0 commit comments