91
91
NSString * const MTREventIsHistoricalKey = @" eventIsHistorical" ;
92
92
93
93
class MTRDataValueDictionaryCallbackBridge ;
94
+ class MTRDataValueDictionaryDecodableType ;
95
+ template <typename DecodableValueType>
96
+ class BufferedReadClientCallback ;
94
97
95
98
@interface MTRReadClientContainer : NSObject
96
99
@property (nonatomic , readwrite ) app::ReadClient * readClientPtr;
100
+ @property (nonatomic , readwrite ) BufferedReadClientCallback<MTRDataValueDictionaryDecodableType> * callback;
97
101
@property (nonatomic , readwrite ) app::AttributePathParams * pathParams;
98
102
@property (nonatomic , readwrite ) app::EventPathParams * eventPathParams;
99
103
@property (nonatomic , readwrite ) uint64_t deviceID;
104
+
105
+ - (void )cleanup ;
100
106
- (void )onDone ;
101
107
@end
102
108
@@ -157,22 +163,7 @@ static void PurgeReadClientContainers(
157
163
[controller
158
164
asyncDispatchToMatterQueue: ^() {
159
165
for (MTRReadClientContainer * container in listToDelete) {
160
- if (container.readClientPtr ) {
161
- Platform::Delete (container.readClientPtr );
162
- container.readClientPtr = nullptr ;
163
- }
164
- if (container.pathParams ) {
165
- static_assert (std::is_trivially_destructible<AttributePathParams>::value,
166
- " AttributePathParams destructors won't get run" );
167
- Platform::MemoryFree (container.pathParams );
168
- container.pathParams = nullptr ;
169
- }
170
- if (container.eventPathParams ) {
171
- static_assert (
172
- std::is_trivially_destructible<EventPathParams>::value, " EventPathParams destructors won't get run" );
173
- Platform::MemoryFree (container.eventPathParams );
174
- container.eventPathParams = nullptr ;
175
- }
166
+ [container cleanup ];
176
167
}
177
168
[listToDelete removeAllObjects ];
178
169
if (completion) {
@@ -204,47 +195,13 @@ static void PurgeCompletedReadClientContainers(uint64_t deviceId)
204
195
[readClientContainersLock unlock ];
205
196
}
206
197
207
- #ifdef DEBUG
208
- // This function is for unit testing only. This function closes all read clients.
209
- static void CauseReadClientFailure (
210
- MTRDeviceController * controller, uint64_t deviceId, dispatch_queue_t queue, void (^_Nullable completion)(void ))
211
- {
212
- InitializeReadClientContainers ();
213
-
214
- NSMutableArray <MTRReadClientContainer *> * listToFail;
215
- NSNumber * key = [NSNumber numberWithUnsignedLongLong: deviceId];
216
- [readClientContainersLock lock ];
217
- listToFail = readClientContainers[key];
218
- [readClientContainers removeObjectForKey: key];
219
- [readClientContainersLock unlock ];
220
-
221
- [controller
222
- asyncDispatchToMatterQueue: ^() {
223
- for (MTRReadClientContainer * container in listToFail) {
224
- // Send auto resubscribe request again by read clients, which must fail.
225
- chip::app::ReadPrepareParams readParams;
226
- if (container.readClientPtr ) {
227
- container.readClientPtr ->SendAutoResubscribeRequest (std::move (readParams));
228
- }
229
- }
230
- if (completion) {
231
- dispatch_async (queue, completion);
232
- }
233
- }
234
- errorHandler: ^(NSError * error) {
235
- // Can't fail things. Just put them back.
236
- ReinstateReadClientList (listToFail, key, queue, completion);
237
- }];
238
- }
239
- #endif
240
-
241
198
static bool CheckMemberOfType (NSDictionary <NSString *, id > * responseValue, NSString * memberName, Class expectedClass,
242
199
NSString * errorMessage, NSError * __autoreleasing * error);
243
200
static void LogStringAndReturnError (NSString * errorStr, CHIP_ERROR errorCode, NSError * __autoreleasing * error);
244
201
static void LogStringAndReturnError (NSString * errorStr, MTRErrorCode errorCode, NSError * __autoreleasing * error);
245
202
246
203
@implementation MTRReadClientContainer
247
- - (void )onDone
204
+ - (void )cleanup
248
205
{
249
206
if (_readClientPtr) {
250
207
Platform::Delete (_readClientPtr);
@@ -260,26 +217,19 @@ - (void)onDone
260
217
Platform::MemoryFree (_eventPathParams);
261
218
_eventPathParams = nullptr ;
262
219
}
263
- PurgeCompletedReadClientContainers (_deviceID);
220
+ if (_callback) {
221
+ Platform::Delete (_callback);
222
+ _callback = nullptr ;
223
+ }
264
224
}
265
225
266
- - (void )dealloc
226
+ - (void )onDone
267
227
{
268
- if (_readClientPtr) {
269
- Platform::Delete (_readClientPtr);
270
- _readClientPtr = nullptr ;
271
- }
272
- if (_pathParams) {
273
- static_assert (std::is_trivially_destructible<AttributePathParams>::value, " AttributePathParams destructors won't get run" );
274
- Platform::MemoryFree (_pathParams);
275
- _pathParams = nullptr ;
276
- }
277
- if (_eventPathParams) {
278
- static_assert (std::is_trivially_destructible<EventPathParams>::value, " EventPathParams destructors won't get run" );
279
- Platform::MemoryFree (_eventPathParams);
280
- _eventPathParams = nullptr ;
281
- }
228
+ [self cleanup ];
229
+
230
+ PurgeCompletedReadClientContainers (_deviceID);
282
231
}
232
+
283
233
@end
284
234
285
235
@implementation MTRBaseDevice
@@ -1730,6 +1680,7 @@ - (void)subscribeToAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullabl
1730
1680
dispatch_async (queue, ^{
1731
1681
reportHandler (nil , [MTRError errorForCHIPErrorCode: CHIP_ERROR_NO_MEMORY]);
1732
1682
});
1683
+ [container cleanup ];
1733
1684
return ;
1734
1685
}
1735
1686
for (MTRAttributeRequestPath * attribute in attributes) {
@@ -1744,6 +1695,7 @@ - (void)subscribeToAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullabl
1744
1695
dispatch_async (queue, ^{
1745
1696
reportHandler (nil , [MTRError errorForCHIPErrorCode: CHIP_ERROR_NO_MEMORY]);
1746
1697
});
1698
+ [container cleanup ];
1747
1699
return ;
1748
1700
}
1749
1701
for (MTREventRequestPath * event in events) {
@@ -1763,9 +1715,6 @@ - (void)subscribeToAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullabl
1763
1715
1764
1716
auto onDone = [container](BufferedReadClientCallback<MTRDataValueDictionaryDecodableType> * callback) {
1765
1717
[container onDone ];
1766
- // Make sure we delete callback last, because doing that actually destroys our
1767
- // lambda, so we can't access captured values after that.
1768
- chip::Platform::Delete (callback);
1769
1718
};
1770
1719
1771
1720
auto callback = chip::Platform::MakeUnique<BufferedReadClientCallback<MTRDataValueDictionaryDecodableType>>(
@@ -1775,6 +1724,9 @@ - (void)subscribeToAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullabl
1775
1724
auto readClient = Platform::New<app::ReadClient>(
1776
1725
engine, exchangeManager, callback->GetBufferedCallback (), chip::app::ReadClient::InteractionType::Subscribe);
1777
1726
1727
+ container.readClientPtr = readClient;
1728
+ container.callback = callback.release ();
1729
+
1778
1730
if (!params.resubscribeAutomatically ) {
1779
1731
err = readClient->SendRequest (readParams);
1780
1732
} else {
@@ -1785,23 +1737,12 @@ - (void)subscribeToAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullabl
1785
1737
dispatch_async (queue, ^{
1786
1738
reportHandler (nil , [MTRError errorForCHIPErrorCode: err]);
1787
1739
});
1788
- Platform::Delete (readClient);
1789
- if (container.pathParams != nullptr ) {
1790
- Platform::MemoryFree (container.pathParams );
1791
- }
1792
-
1793
- if (container.eventPathParams != nullptr ) {
1794
- Platform::MemoryFree (container.eventPathParams );
1795
- }
1796
- container.pathParams = nullptr ;
1797
- container.eventPathParams = nullptr ;
1740
+ [container cleanup ];
1798
1741
return ;
1799
1742
}
1800
1743
1801
1744
// Read clients will be purged when deregistered.
1802
- container.readClientPtr = readClient;
1803
1745
AddReadClientContainer (container.deviceID , container);
1804
- callback.release ();
1805
1746
}];
1806
1747
}
1807
1748
@@ -2024,13 +1965,6 @@ - (void)openCommissioningWindowWithDiscriminator:(NSNumber *)discriminator
2024
1965
}
2025
1966
2026
1967
#ifdef DEBUG
2027
- // This method is for unit testing only
2028
- - (void )failSubscribers : (dispatch_queue_t )queue completion : (void (^)(void ))completion
2029
- {
2030
- MTR_LOG_DEBUG (" Causing failure in subscribers on purpose" );
2031
- CauseReadClientFailure (self.deviceController , self.nodeID , queue, completion);
2032
- }
2033
-
2034
1968
// The following method is for unit testing purpose only
2035
1969
+ (id )CHIPEncodeAndDecodeNSObject : (id )object
2036
1970
{
0 commit comments