Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2456239

Browse files
authoredMay 7, 2024··
Merge branch 'master' into feature/unittest--transport-tests
2 parents cbb528e + d75f73c commit 2456239

File tree

13 files changed

+656
-531
lines changed

13 files changed

+656
-531
lines changed
 

‎examples/light-switch-app/silabs/src/ZclCallbacks.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ using namespace ::chip::app::Clusters;
3333
void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
3434
uint8_t * value)
3535
{
36-
ClusterId clusterId = attributePath.mClusterId;
37-
AttributeId attributeId = attributePath.mAttributeId;
36+
ClusterId clusterId = attributePath.mClusterId;
37+
[[maybe_unused]] AttributeId attributeId = attributePath.mAttributeId;
3838
ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));
3939

4040
if (clusterId == OnOffSwitchConfiguration::Id)

‎examples/lock-app/silabs/src/ZclCallbacks.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
4848

4949
if (clusterId == DoorLock::Id && attributeId == DoorLock::Attributes::LockState::Id)
5050
{
51-
DoorLock::DlLockState lockState = *(reinterpret_cast<DoorLock::DlLockState *>(value));
51+
[[maybe_unused]] DoorLock::DlLockState lockState = *(reinterpret_cast<DoorLock::DlLockState *>(value));
5252
ChipLogProgress(Zcl, "Door lock cluster: " ChipLogFormatMEI " state %d", ChipLogValueMEI(clusterId),
5353
to_underlying(lockState));
5454
#ifdef DIC_ENABLE

‎src/darwin/Framework/CHIP/MTRAsyncWorkQueue.h

+11
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,17 @@ MTR_TESTABLE
192192
/// is lost.
193193
- (instancetype)initWithContext:(ContextType)context;
194194

195+
/// Creates a work queue with the given context object and a queue width.
196+
///
197+
/// The queue will call readyHandler on up to "width" number of work items
198+
/// concurrently. Once "width" number of work items have started, no other
199+
/// work items will get a readyHandler call until one of the running work items
200+
/// has called its completion block with MTRAsyncWorkComplete.
201+
///
202+
/// This allows the a MTRAsyncWorkQueue object to manage a pool of
203+
/// resources that can be use concurrently at any given time.
204+
- (instancetype)initWithContext:(ContextType)context width:(NSUInteger)width;
205+
195206
/// Enqueues the specified work item, making it eligible for execution.
196207
///
197208
/// Once a work item is enqueued, ownership of it passes to the queue and

‎src/darwin/Framework/CHIP/MTRAsyncWorkQueue.mm

+78-35
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ @implementation MTRAsyncWorkQueue {
197197
os_unfair_lock _lock;
198198
__weak id _context;
199199
NSMutableArray<MTRAsyncWorkItem *> * _items;
200-
NSInteger _runningWorkItemCount;
200+
NSUInteger _runningWorkItemCount;
201+
NSUInteger _width;
201202
}
202203

203204
// A helper struct that facilitates access to _context while
@@ -216,11 +217,17 @@ @implementation MTRAsyncWorkQueue {
216217
};
217218

218219
- (instancetype)initWithContext:(id)context
220+
{
221+
return [self initWithContext:context width:1];
222+
}
223+
224+
- (instancetype)initWithContext:(id)context width:(NSUInteger)width
219225
{
220226
NSParameterAssert(context);
221227
if (self = [super init]) {
222228
_context = context;
223229
_items = [NSMutableArray array];
230+
_width = width;
224231
}
225232
return self;
226233
}
@@ -286,35 +293,84 @@ - (void)_postProcessWorkItem:(MTRAsyncWorkItem *)workItem
286293
{
287294
os_unfair_lock_assert_owner(&_lock);
288295

289-
MTRAsyncWorkItem * runningWorkItem = (_runningWorkItemCount) ? _items.firstObject : nil;
290-
if (workItem != runningWorkItem) {
296+
BOOL foundWorkItem = NO;
297+
NSUInteger indexOfWorkItem = 0;
298+
for (NSUInteger i = 0; i < _width; i++) {
299+
if (_items[i] == workItem) {
300+
foundWorkItem = YES;
301+
indexOfWorkItem = i;
302+
break;
303+
}
304+
}
305+
if (!foundWorkItem) {
291306
NSAssert(NO, @"work item to post-process is not running");
292307
return;
293308
}
294309

310+
// already part of the running work items allowed by width - retry directly
295311
if (retry) {
296312
MTR_LOG_DEFAULT("MTRAsyncWorkQueue<%@> retry needed for work item [%llu]", context.description, workItem.uniqueID);
297-
} else {
298-
[workItem markComplete];
299-
[_items removeObjectAtIndex:0];
300-
MTR_LOG_DEFAULT("MTRAsyncWorkQueue<%@, items count: %tu> completed work item [%llu]", context.description, _items.count, workItem.uniqueID);
313+
[self _callWorkItem:workItem withContext:context];
314+
return;
301315
}
302316

303-
// when "concurrency width" is implemented this will be decremented instead
304-
_runningWorkItemCount = 0;
317+
[workItem markComplete];
318+
[_items removeObjectAtIndex:indexOfWorkItem];
319+
MTR_LOG_DEFAULT("MTRAsyncWorkQueue<%@, items count: %tu> completed work item [%llu]", context.description, _items.count, workItem.uniqueID);
320+
321+
// sanity check running work item count is positive
322+
if (_runningWorkItemCount == 0) {
323+
NSAssert(NO, @"running work item count should be positive");
324+
return;
325+
}
326+
327+
_runningWorkItemCount--;
305328
[self _callNextReadyWorkItemWithContext:context];
306329
}
307330

331+
- (void)_callWorkItem:(MTRAsyncWorkItem *)workItem withContext:(ContextSnapshot const &)context
332+
{
333+
os_unfair_lock_assert_owner(&_lock);
334+
335+
mtr_weakify(self);
336+
[workItem callReadyHandlerWithContext:context.reference completion:^(MTRAsyncWorkOutcome outcome) {
337+
mtr_strongify(self);
338+
BOOL handled = NO;
339+
if (self) {
340+
ContextSnapshot context(self); // re-acquire a new snapshot
341+
std::lock_guard lock(self->_lock);
342+
if (!workItem.isComplete) {
343+
[self _postProcessWorkItem:workItem context:context retry:(outcome == MTRAsyncWorkNeedsRetry)];
344+
handled = YES;
345+
}
346+
}
347+
return handled;
348+
}];
349+
}
350+
308351
- (void)_callNextReadyWorkItemWithContext:(ContextSnapshot const &)context
309352
{
310353
os_unfair_lock_assert_owner(&_lock);
311354

312-
// when "concurrency width" is implemented this will be checked against the width
313-
if (_runningWorkItemCount) {
314-
return; // can't run next work item until the current one is done
355+
// sanity check not running more than allowed
356+
if (_runningWorkItemCount > _width) {
357+
NSAssert(NO, @"running work item count larger than the maximum width");
358+
return;
315359
}
316360

317-
if (!_items.count) {
361+
// sanity check consistent counts
362+
if (_items.count < _runningWorkItemCount) {
363+
NSAssert(NO, @"work item count is less than running work item count");
364+
return;
365+
}
366+
367+
// can't run more work items if already running at max concurrent width
368+
if (_runningWorkItemCount == _width) {
369+
return;
370+
}
371+
372+
// no more items to run
373+
if (_items.count == _runningWorkItemCount) {
318374
return; // nothing to run
319375
}
320376

@@ -324,16 +380,16 @@ - (void)_callNextReadyWorkItemWithContext:(ContextSnapshot const &)context
324380
return;
325381
}
326382

327-
// when "concurrency width" is implemented this will be incremented instead
328-
_runningWorkItemCount = 1;
329-
330-
MTRAsyncWorkItem * workItem = _items.firstObject;
383+
NSUInteger nextWorkItemToRunIndex = _runningWorkItemCount;
384+
MTRAsyncWorkItem * workItem = _items[nextWorkItemToRunIndex];
385+
_runningWorkItemCount++;
331386

332-
// Check if batching is possible or needed. Only ask work item to batch once for simplicity
387+
// Check if batching is possible or needed.
333388
auto batchingHandler = workItem.batchingHandler;
334-
if (batchingHandler && workItem.retryCount == 0) {
335-
while (_items.count >= 2) {
336-
MTRAsyncWorkItem * nextWorkItem = _items[1];
389+
if (batchingHandler) {
390+
while (_items.count > _runningWorkItemCount) {
391+
NSUInteger firstNonRunningItemIndex = _runningWorkItemCount;
392+
MTRAsyncWorkItem * nextWorkItem = _items[firstNonRunningItemIndex];
337393
if (!nextWorkItem.batchingHandler || nextWorkItem.batchingID != workItem.batchingID) {
338394
goto done; // next item is not eligible to merge with this one
339395
}
@@ -355,20 +411,7 @@ - (void)_callNextReadyWorkItemWithContext:(ContextSnapshot const &)context
355411
done:;
356412
}
357413

358-
mtr_weakify(self);
359-
[workItem callReadyHandlerWithContext:context.reference completion:^(MTRAsyncWorkOutcome outcome) {
360-
mtr_strongify(self);
361-
BOOL handled = NO;
362-
if (self) {
363-
ContextSnapshot context(self); // re-acquire a new snapshot
364-
std::lock_guard lock(self->_lock);
365-
if (!workItem.isComplete) {
366-
[self _postProcessWorkItem:workItem context:context retry:(outcome == MTRAsyncWorkNeedsRetry)];
367-
handled = YES;
368-
}
369-
}
370-
return handled;
371-
}];
414+
[self _callWorkItem:workItem withContext:context];
372415
}
373416

374417
- (BOOL)hasDuplicateForTypeID:(NSUInteger)opaqueDuplicateTypeID workItemData:(id)opaqueWorkItemData

‎src/darwin/Framework/CHIP/MTRDeviceConnectivityMonitor.mm

+36-22
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,23 @@
2323
#import <os/lock.h>
2424

2525
#include <lib/dnssd/ServiceNaming.h>
26+
#include <lib/support/CodeUtils.h>
27+
#include <vector>
2628

2729
@implementation MTRDeviceConnectivityMonitor {
2830
NSString * _instanceName;
29-
DNSServiceRef _resolver;
31+
std::vector<DNSServiceRef> _resolvers;
3032
NSMutableDictionary<NSString *, nw_connection_t> * _connections;
3133

3234
MTRDeviceConnectivityMonitorHandler _monitorHandler;
3335
dispatch_queue_t _handlerQueue;
3436
}
3537

3638
namespace {
37-
constexpr char kLocalDot[] = "local.";
39+
constexpr const char * kResolveDomains[] = {
40+
"default.service.arpa.", // SRP
41+
"local.",
42+
};
3843
constexpr char kOperationalType[] = "_matter._tcp";
3944
constexpr int64_t kSharedConnectionLingerIntervalSeconds = (10);
4045
}
@@ -68,8 +73,8 @@ - (instancetype)initWithCompressedFabricID:(NSNumber *)compressedFabricID nodeID
6873

6974
- (void)dealloc
7075
{
71-
if (_resolver) {
72-
DNSServiceRefDeallocate(_resolver);
76+
for (auto & resolver : _resolvers) {
77+
DNSServiceRefDeallocate(resolver);
7378
}
7479
}
7580

@@ -188,32 +193,39 @@ - (void)startMonitoringWithHandler:(MTRDeviceConnectivityMonitorHandler)handler
188193
_handlerQueue = queue;
189194

190195
// If there's already a resolver running, just return
191-
if (_resolver) {
196+
if (_resolvers.size() != 0) {
192197
MTR_LOG_INFO("%@ connectivity monitor already running", self);
193198
return;
194199
}
195200

196201
MTR_LOG_INFO("%@ start connectivity monitoring for %@ (%lu monitoring objects)", self, _instanceName, static_cast<unsigned long>(sConnectivityMonitorCount));
197202

198-
_resolver = [MTRDeviceConnectivityMonitor _sharedResolverConnection];
199-
if (!_resolver) {
203+
auto sharedConnection = [MTRDeviceConnectivityMonitor _sharedResolverConnection];
204+
if (!sharedConnection) {
200205
MTR_LOG_ERROR("%@ failed to get shared resolver connection", self);
201206
return;
202207
}
203-
DNSServiceErrorType dnsError = DNSServiceResolve(&_resolver,
204-
kDNSServiceFlagsShareConnection,
205-
kDNSServiceInterfaceIndexAny,
206-
_instanceName.UTF8String,
207-
kOperationalType,
208-
kLocalDot,
209-
ResolveCallback,
210-
(__bridge void *) self);
211-
if (dnsError != kDNSServiceErr_NoError) {
212-
MTR_LOG_ERROR("%@ failed to create resolver", self);
213-
return;
208+
209+
for (auto domain : kResolveDomains) {
210+
DNSServiceRef resolver = sharedConnection;
211+
DNSServiceErrorType dnsError = DNSServiceResolve(&resolver,
212+
kDNSServiceFlagsShareConnection,
213+
kDNSServiceInterfaceIndexAny,
214+
_instanceName.UTF8String,
215+
kOperationalType,
216+
domain,
217+
ResolveCallback,
218+
(__bridge void *) self);
219+
if (dnsError == kDNSServiceErr_NoError) {
220+
_resolvers.emplace_back(std::move(resolver));
221+
} else {
222+
MTR_LOG_ERROR("%@ failed to create resolver for \"%s\" domain: %" PRId32, self, StringOrNullMarker(domain), dnsError);
223+
}
214224
}
215225

216-
sConnectivityMonitorCount++;
226+
if (_resolvers.size() != 0) {
227+
sConnectivityMonitorCount++;
228+
}
217229
}
218230

219231
- (void)_stopMonitoring
@@ -227,9 +239,11 @@ - (void)_stopMonitoring
227239
_monitorHandler = nil;
228240
_handlerQueue = nil;
229241

230-
if (_resolver) {
231-
DNSServiceRefDeallocate(_resolver);
232-
_resolver = NULL;
242+
if (_resolvers.size() != 0) {
243+
for (auto & resolver : _resolvers) {
244+
DNSServiceRefDeallocate(resolver);
245+
}
246+
_resolvers.clear();
233247

234248
// If no monitor objects exist, schedule to deallocate shared connection and queue
235249
sConnectivityMonitorCount--;

‎src/darwin/Framework/CHIP/MTROperationalBrowser.mm

+17-7
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@
2121

2222
#include <cinttypes>
2323
#include <lib/dnssd/ServiceNaming.h>
24+
#include <lib/support/CodeUtils.h>
2425
#include <lib/support/logging/CHIPLogging.h>
2526
#include <platform/LockTracker.h>
2627

2728
namespace {
28-
constexpr char kLocalDot[] = "local.";
29+
constexpr const char * kBrowseDomains[] = {
30+
"default.service.arpa.", // SRP
31+
"local.",
32+
};
2933
constexpr char kOperationalType[] = "_matter._tcp";
30-
constexpr DNSServiceFlags kBrowseFlags = 0;
3134
}
3235

3336
MTROperationalBrowser::MTROperationalBrowser(MTRDeviceControllerFactory * aFactory, dispatch_queue_t aQueue)
@@ -43,23 +46,30 @@
4346
{
4447
assertChipStackLockedByCurrentThread();
4548

46-
ChipLogProgress(Controller, "Trying to start operational browse");
49+
ChipLogProgress(Controller, "Trying to start persistent operational browse");
4750

48-
auto err
49-
= DNSServiceBrowse(&mBrowseRef, kBrowseFlags, kDNSServiceInterfaceIndexAny, kOperationalType, kLocalDot, OnBrowse, this);
51+
auto err = DNSServiceCreateConnection(&mBrowseRef);
5052
if (err != kDNSServiceErr_NoError) {
51-
ChipLogError(Controller, "Failed to start operational browse: %" PRId32, err);
53+
ChipLogError(Controller, "Failed to create connection for persistent operational browse: %" PRId32, err);
5254
return;
5355
}
5456

5557
err = DNSServiceSetDispatchQueue(mBrowseRef, mQueue);
5658
if (err != kDNSServiceErr_NoError) {
57-
ChipLogError(Controller, "Failed to set up dispatch queue properly");
59+
ChipLogError(Controller, "Failed to set up dispatch queue properly for persistent operational browse: %" PRId32, err);
5860
DNSServiceRefDeallocate(mBrowseRef);
5961
return;
6062
}
6163

6264
mInitialized = true;
65+
66+
for (auto domain : kBrowseDomains) {
67+
auto browseRef = mBrowseRef; // Mandatory copy because of kDNSServiceFlagsShareConnection.
68+
err = DNSServiceBrowse(&browseRef, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexAny, kOperationalType, domain, OnBrowse, this);
69+
if (err != kDNSServiceErr_NoError) {
70+
ChipLogError(Controller, "Failed to start persistent operational browse for \"%s\" domain: %" PRId32, StringOrNullMarker(domain), err);
71+
}
72+
}
6373
}
6474

6575
void MTROperationalBrowser::OnBrowse(DNSServiceRef aServiceRef, DNSServiceFlags aFlags, uint32_t aInterfaceId,

0 commit comments

Comments
 (0)
Please sign in to comment.