Skip to content

Commit 2787db2

Browse files
[Darwin] more XPC service tweaks (#35048)
* return `MTRDevice_XPC`s from XPC controller * more logging * move shadow property declarations to internal header * declare `_setupDeviceForNodeID` as common internal device controller method * prefetchedClusterData is nullable * fix a few properties that needed raising to base class * you get a log and you get a log EVERYONE GETS A LOG * convert device map lock for use in subclasses * check for optional delegate method impl before calling * ivar no longer necessary with accessor method underlying lock is the only state needed * Restyled by clang-format * remove more obsolete lock bits from `MTRDeviceController_XPC` --------- Co-authored-by: Restyled.io <commits@restyled.io>
1 parent 1e58f96 commit 2787db2

5 files changed

+84
-42
lines changed

src/darwin/Framework/CHIP/MTRDeviceController.mm

+17-12
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ @implementation MTRDeviceController {
120120
MTRDeviceAttestationDelegateBridge * _deviceAttestationDelegateBridge;
121121
MTRDeviceControllerFactory * _factory;
122122
NSMapTable * _nodeIDToDeviceMap;
123-
os_unfair_lock _deviceMapLock; // protects nodeIDToDeviceMap
123+
os_unfair_lock _underlyingDeviceMapLock;
124124
MTRCommissionableBrowser * _commissionableBrowser;
125125
MTRAttestationTrustStoreBridge * _attestationTrustStoreBridge;
126126

@@ -134,12 +134,17 @@ @implementation MTRDeviceController {
134134
MTRP256KeypairBridge _operationalKeypairBridge;
135135
}
136136

137+
- (os_unfair_lock_t)deviceMapLock
138+
{
139+
return &_underlyingDeviceMapLock;
140+
}
141+
137142
- (instancetype)initForSubclasses
138143
{
139144
if (self = [super init]) {
140145
// nothing, as superclass of MTRDeviceController is NSObject
141146
}
142-
147+
_underlyingDeviceMapLock = OS_UNFAIR_LOCK_INIT;
143148
return self;
144149
}
145150

@@ -250,7 +255,7 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory
250255

251256
_chipWorkQueue = queue;
252257
_factory = factory;
253-
_deviceMapLock = OS_UNFAIR_LOCK_INIT;
258+
_underlyingDeviceMapLock = OS_UNFAIR_LOCK_INIT;
254259
_nodeIDToDeviceMap = [NSMapTable strongToWeakObjectsMapTable];
255260
_serverEndpoints = [[NSMutableArray alloc] init];
256261
_commissionableBrowser = nil;
@@ -330,10 +335,10 @@ - (void)cleanupAfterStartup
330335
// while calling out into arbitrary invalidation code, snapshot the list of
331336
// devices before we start invalidating.
332337
MTR_LOG("cleanupAfterStartup MTRDeviceController: %@", self);
333-
os_unfair_lock_lock(&_deviceMapLock);
338+
os_unfair_lock_lock(self.deviceMapLock);
334339
NSEnumerator * devices = [_nodeIDToDeviceMap objectEnumerator];
335340
[_nodeIDToDeviceMap removeAllObjects];
336-
os_unfair_lock_unlock(&_deviceMapLock);
341+
os_unfair_lock_unlock(self.deviceMapLock);
337342

338343
for (MTRDevice * device in devices) {
339344
[device invalidate];
@@ -634,7 +639,7 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams
634639
[_controllerDataStore fetchAttributeDataForAllDevices:^(NSDictionary<NSNumber *, NSDictionary<MTRClusterPath *, MTRDeviceClusterData *> *> * _Nonnull clusterDataByNode) {
635640
MTR_LOG("%@ Loaded attribute values for %lu nodes from storage for controller uuid %@", self, static_cast<unsigned long>(clusterDataByNode.count), self->_uniqueIdentifier);
636641

637-
std::lock_guard lock(self->_deviceMapLock);
642+
std::lock_guard lock(*self.deviceMapLock);
638643
NSMutableArray * deviceList = [NSMutableArray array];
639644
for (NSNumber * nodeID in clusterDataByNode) {
640645
NSDictionary * clusterData = clusterDataByNode[nodeID];
@@ -1004,7 +1009,7 @@ - (MTRBaseDevice *)baseDeviceForNodeID:(NSNumber *)nodeID
10041009
// If prefetchedClusterData is not provided, load attributes individually from controller data store
10051010
- (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(NSDictionary<MTRClusterPath *, MTRDeviceClusterData *> *)prefetchedClusterData
10061011
{
1007-
os_unfair_lock_assert_owner(&_deviceMapLock);
1012+
os_unfair_lock_assert_owner(self.deviceMapLock);
10081013

10091014
MTRDevice * deviceToReturn = [[MTRDevice_Concrete alloc] initWithNodeID:nodeID controller:self];
10101015
// If we're not running, don't add the device to our map. That would
@@ -1043,7 +1048,7 @@ - (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(N
10431048

10441049
- (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID
10451050
{
1046-
std::lock_guard lock(_deviceMapLock);
1051+
std::lock_guard lock(*self.deviceMapLock);
10471052
MTRDevice * deviceToReturn = [_nodeIDToDeviceMap objectForKey:nodeID];
10481053
if (!deviceToReturn) {
10491054
deviceToReturn = [self _setupDeviceForNodeID:nodeID prefetchedClusterData:nil];
@@ -1054,7 +1059,7 @@ - (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID
10541059

10551060
- (void)removeDevice:(MTRDevice *)device
10561061
{
1057-
std::lock_guard lock(_deviceMapLock);
1062+
std::lock_guard lock(*self.deviceMapLock);
10581063
auto * nodeID = device.nodeID;
10591064
MTRDevice * deviceToRemove = [_nodeIDToDeviceMap objectForKey:nodeID];
10601065
if (deviceToRemove == device) {
@@ -1068,7 +1073,7 @@ - (void)removeDevice:(MTRDevice *)device
10681073
#ifdef DEBUG
10691074
- (NSDictionary<NSNumber *, NSNumber *> *)unitTestGetDeviceAttributeCounts
10701075
{
1071-
std::lock_guard lock(_deviceMapLock);
1076+
std::lock_guard lock(*self.deviceMapLock);
10721077
NSMutableDictionary<NSNumber *, NSNumber *> * deviceAttributeCounts = [NSMutableDictionary dictionary];
10731078
for (NSNumber * nodeID in _nodeIDToDeviceMap) {
10741079
deviceAttributeCounts[nodeID] = @([[_nodeIDToDeviceMap objectForKey:nodeID] unitTestAttributeCount]);
@@ -1508,9 +1513,9 @@ - (void)operationalInstanceAdded:(chip::NodeId)nodeID
15081513
{
15091514
// Don't use deviceForNodeID here, because we don't want to create the
15101515
// device if it does not already exist.
1511-
os_unfair_lock_lock(&_deviceMapLock);
1516+
os_unfair_lock_lock(self.deviceMapLock);
15121517
MTRDevice * device = [_nodeIDToDeviceMap objectForKey:@(nodeID)];
1513-
os_unfair_lock_unlock(&_deviceMapLock);
1518+
os_unfair_lock_unlock(self.deviceMapLock);
15141519

15151520
if (device == nil) {
15161521
return;

src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm

+19-25
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@
8282
#include <dns_sd.h>
8383
#include <string>
8484

85-
#import <os/lock.h>
86-
8785
typedef void (^SyncWorkQueueBlock)(void);
8886
typedef id (^SyncWorkQueueBlockWithReturnValue)(void);
8987
typedef BOOL (^SyncWorkQueueBlockWithBoolReturnValue)(void);
@@ -103,8 +101,6 @@ @interface MTRDeviceController_Concrete ()
103101
@property (nonatomic, readwrite) NSUUID * uniqueIdentifier;
104102
@property (nonatomic, readonly) dispatch_queue_t chipWorkQueue;
105103
@property (nonatomic, readonly, nullable) MTRDeviceControllerFactory * factory;
106-
@property (nonatomic, readonly, nullable) NSMapTable * nodeIDToDeviceMap;
107-
@property (nonatomic, readonly) os_unfair_lock deviceMapLock;
108104
@property (nonatomic, readonly, nullable) id<MTROTAProviderDelegate> otaProviderDelegate;
109105
@property (nonatomic, readonly, nullable) dispatch_queue_t otaProviderDelegateQueue;
110106
@property (nonatomic, readonly, nullable) MTRCommissionableBrowser * commissionableBrowser;
@@ -270,11 +266,9 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory
270266

271267
_otaProviderDelegate = otaProviderDelegate;
272268
_otaProviderDelegateQueue = otaProviderDelegateQueue;
273-
274269
_chipWorkQueue = queue;
275270
_factory = factory;
276-
_deviceMapLock = OS_UNFAIR_LOCK_INIT;
277-
_nodeIDToDeviceMap = [NSMapTable strongToWeakObjectsMapTable];
271+
self.nodeIDToDeviceMap = [NSMapTable strongToWeakObjectsMapTable];
278272
_serverEndpoints = [[NSMutableArray alloc] init];
279273
_commissionableBrowser = nil;
280274

@@ -352,10 +346,10 @@ - (void)cleanupAfterStartup
352346
// while calling out into arbitrary invalidation code, snapshot the list of
353347
// devices before we start invalidating.
354348
MTR_LOG("cleanupAfterStartup MTRDeviceController: %@", self);
355-
os_unfair_lock_lock(&_deviceMapLock);
356-
NSEnumerator * devices = [_nodeIDToDeviceMap objectEnumerator];
357-
[_nodeIDToDeviceMap removeAllObjects];
358-
os_unfair_lock_unlock(&_deviceMapLock);
349+
os_unfair_lock_lock(self.deviceMapLock);
350+
NSEnumerator * devices = [self.nodeIDToDeviceMap objectEnumerator];
351+
[self.nodeIDToDeviceMap removeAllObjects];
352+
os_unfair_lock_unlock(self.deviceMapLock);
359353

360354
for (MTRDevice * device in devices) {
361355
[device invalidate];
@@ -654,7 +648,7 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams
654648
[_controllerDataStore fetchAttributeDataForAllDevices:^(NSDictionary<NSNumber *, NSDictionary<MTRClusterPath *, MTRDeviceClusterData *> *> * _Nonnull clusterDataByNode) {
655649
MTR_LOG("%@ Loaded attribute values for %lu nodes from storage for controller uuid %@", self, static_cast<unsigned long>(clusterDataByNode.count), self->_uniqueIdentifier);
656650

657-
std::lock_guard lock(self->_deviceMapLock);
651+
std::lock_guard lock(*self.deviceMapLock);
658652
NSMutableArray * deviceList = [NSMutableArray array];
659653
for (NSNumber * nodeID in clusterDataByNode) {
660654
NSDictionary * clusterData = clusterDataByNode[nodeID];
@@ -1024,15 +1018,15 @@ - (MTRBaseDevice *)baseDeviceForNodeID:(NSNumber *)nodeID
10241018
// If prefetchedClusterData is not provided, load attributes individually from controller data store
10251019
- (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(NSDictionary<MTRClusterPath *, MTRDeviceClusterData *> *)prefetchedClusterData
10261020
{
1027-
os_unfair_lock_assert_owner(&_deviceMapLock);
1021+
os_unfair_lock_assert_owner(self.deviceMapLock);
10281022

10291023
MTRDevice * deviceToReturn = [[MTRDevice alloc] initWithNodeID:nodeID controller:self];
10301024
// If we're not running, don't add the device to our map. That would
10311025
// create a cycle that nothing would break. Just return the device,
10321026
// which will be in exactly the state it would be in if it were created
10331027
// while we were running and then we got shut down.
10341028
if ([self isRunning]) {
1035-
[_nodeIDToDeviceMap setObject:deviceToReturn forKey:nodeID];
1029+
[self.nodeIDToDeviceMap setObject:deviceToReturn forKey:nodeID];
10361030
}
10371031

10381032
if (prefetchedClusterData) {
@@ -1063,8 +1057,8 @@ - (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(N
10631057

10641058
- (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID
10651059
{
1066-
std::lock_guard lock(_deviceMapLock);
1067-
MTRDevice * deviceToReturn = [_nodeIDToDeviceMap objectForKey:nodeID];
1060+
std::lock_guard lock(*self.deviceMapLock);
1061+
MTRDevice * deviceToReturn = [self.nodeIDToDeviceMap objectForKey:nodeID];
10681062
if (!deviceToReturn) {
10691063
deviceToReturn = [self _setupDeviceForNodeID:nodeID prefetchedClusterData:nil];
10701064
}
@@ -1074,12 +1068,12 @@ - (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID
10741068

10751069
- (void)removeDevice:(MTRDevice *)device
10761070
{
1077-
std::lock_guard lock(_deviceMapLock);
1071+
std::lock_guard lock(*self.deviceMapLock);
10781072
auto * nodeID = device.nodeID;
1079-
MTRDevice * deviceToRemove = [_nodeIDToDeviceMap objectForKey:nodeID];
1073+
MTRDevice * deviceToRemove = [self.nodeIDToDeviceMap objectForKey:nodeID];
10801074
if (deviceToRemove == device) {
10811075
[deviceToRemove invalidate];
1082-
[_nodeIDToDeviceMap removeObjectForKey:nodeID];
1076+
[self.nodeIDToDeviceMap removeObjectForKey:nodeID];
10831077
} else {
10841078
MTR_LOG_ERROR("%@ Error: Cannot remove device %p with nodeID %llu", self, device, nodeID.unsignedLongLongValue);
10851079
}
@@ -1088,10 +1082,10 @@ - (void)removeDevice:(MTRDevice *)device
10881082
#ifdef DEBUG
10891083
- (NSDictionary<NSNumber *, NSNumber *> *)unitTestGetDeviceAttributeCounts
10901084
{
1091-
std::lock_guard lock(_deviceMapLock);
1085+
std::lock_guard lock(*self.deviceMapLock);
10921086
NSMutableDictionary<NSNumber *, NSNumber *> * deviceAttributeCounts = [NSMutableDictionary dictionary];
1093-
for (NSNumber * nodeID in _nodeIDToDeviceMap) {
1094-
deviceAttributeCounts[nodeID] = @([[_nodeIDToDeviceMap objectForKey:nodeID] unitTestAttributeCount]);
1087+
for (NSNumber * nodeID in self.nodeIDToDeviceMap) {
1088+
deviceAttributeCounts[nodeID] = @([[self.nodeIDToDeviceMap objectForKey:nodeID] unitTestAttributeCount]);
10951089
}
10961090
return deviceAttributeCounts;
10971091
}
@@ -1540,9 +1534,9 @@ - (void)operationalInstanceAdded:(chip::NodeId)nodeID
15401534
{
15411535
// Don't use deviceForNodeID here, because we don't want to create the
15421536
// device if it does not already exist.
1543-
os_unfair_lock_lock(&_deviceMapLock);
1544-
MTRDevice * device = [_nodeIDToDeviceMap objectForKey:@(nodeID)];
1545-
os_unfair_lock_unlock(&_deviceMapLock);
1537+
os_unfair_lock_lock(self.deviceMapLock);
1538+
MTRDevice * device = [self.nodeIDToDeviceMap objectForKey:@(nodeID)];
1539+
os_unfair_lock_unlock(self.deviceMapLock);
15461540

15471541
if (device == nil) {
15481542
return;

src/darwin/Framework/CHIP/MTRDeviceController_Internal.h

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include <lib/core/CHIPError.h>
3030
#include <lib/core/DataModelTypes.h>
3131

32+
#import <os/lock.h>
33+
3234
#import "MTRBaseDevice.h"
3335
#import "MTRDeviceController.h"
3436
#import "MTRDeviceControllerDataStore.h"
@@ -63,6 +65,9 @@ NS_ASSUME_NONNULL_BEGIN
6365

6466
@interface MTRDeviceController ()
6567

68+
@property (nonatomic, readwrite, nullable) NSMapTable * nodeIDToDeviceMap;
69+
@property (readonly, assign) os_unfair_lock_t deviceMapLock;
70+
6671
- (instancetype)initForSubclasses;
6772

6873
#pragma mark - MTRDeviceControllerFactory methods
@@ -270,6 +275,7 @@ NS_ASSUME_NONNULL_BEGIN
270275
#pragma mark - Device-specific data and SDK access
271276
// DeviceController will act as a central repository for this opaque dictionary that MTRDevice manages
272277
- (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID;
278+
- (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(nullable NSDictionary<MTRClusterPath *, MTRDeviceClusterData *> *)prefetchedClusterData;
273279
- (void)removeDevice:(MTRDevice *)device;
274280

275281
/**

src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm

+20-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
#import "MTRDeviceController_XPC.h"
18+
1819
#import "MTRDefines_Internal.h"
1920
#import "MTRDeviceController_Internal.h"
2021
#import "MTRDevice_XPC.h"
@@ -45,7 +46,7 @@ @implementation MTRDeviceController_XPC
4546
- (id)initWithUniqueIdentifier:(NSUUID *)UUID xpConnectionBlock:(NSXPCConnection * (^)(void) )connectionBlock
4647
{
4748
if (self = [super initForSubclasses]) {
48-
MTR_LOG("Setting up XPC Controller for UUID: %@ with connection block: %p", UUID, connectionBlock);
49+
MTR_LOG("Setting up XPC Controller for UUID: %@ with connection block: %p", UUID, connectionBlock);
4950

5051
if (UUID == nil) {
5152
MTR_LOG_ERROR("MTRDeviceController_XPC initWithUniqueIdentifier failed, nil UUID");
@@ -111,6 +112,24 @@ - (nullable instancetype)initWithParameters:(MTRDeviceControllerAbstractParamete
111112
return nil;
112113
}
113114

115+
// If prefetchedClusterData is not provided, load attributes individually from controller data store
116+
- (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(NSDictionary<MTRClusterPath *, MTRDeviceClusterData *> *)prefetchedClusterData
117+
{
118+
MTR_LOG("%s", __PRETTY_FUNCTION__);
119+
os_unfair_lock_assert_owner(self.deviceMapLock);
120+
121+
MTRDevice * deviceToReturn = [[MTRDevice_XPC alloc] initWithNodeID:nodeID controller:self];
122+
// If we're not running, don't add the device to our map. That would
123+
// create a cycle that nothing would break. Just return the device,
124+
// which will be in exactly the state it would be in if it were created
125+
// while we were running and then we got shut down.
126+
if ([self isRunning]) {
127+
[self.nodeIDToDeviceMap setObject:deviceToReturn forKey:nodeID];
128+
}
129+
MTR_LOG("%s: returning XPC device for node id %@", __PRETTY_FUNCTION__, nodeID);
130+
return deviceToReturn;
131+
}
132+
114133
#pragma mark - XPC Action Overrides
115134

116135
MTR_DEVICECONTROLLER_SIMPLE_REMOTE_XPC_GETTER(isRunning, BOOL, NO, getIsRunningWithReply)

src/darwin/Framework/CHIP/MTRDevice_XPC.mm

+22-4
Original file line numberDiff line numberDiff line change
@@ -82,41 +82,59 @@
8282

8383
@implementation MTRDevice_XPC
8484

85-
#pragma mark - Client Callbacks
85+
#pragma mark - Client Callbacks (MTRDeviceDelegate)
86+
87+
// required methods for MTRDeviceDelegates
8688
- (oneway void)device:(NSNumber *)nodeID stateChanged:(MTRDeviceState)state
8789
{
90+
MTR_LOG("%s", __PRETTY_FUNCTION__);
8891
[self _callDelegatesWithBlock:^(id<MTRDeviceDelegate> delegate) {
8992
[delegate device:self stateChanged:state];
9093
}];
9194
}
95+
9296
- (oneway void)device:(NSNumber *)nodeID receivedAttributeReport:(NSArray<NSDictionary<NSString *, id> *> *)attributeReport
9397
{
98+
MTR_LOG("%s", __PRETTY_FUNCTION__);
9499
[self _callDelegatesWithBlock:^(id<MTRDeviceDelegate> delegate) {
95100
[delegate device:self receivedAttributeReport:attributeReport];
96101
}];
97102
}
103+
98104
- (oneway void)device:(NSNumber *)nodeID receivedEventReport:(NSArray<NSDictionary<NSString *, id> *> *)eventReport
99105
{
106+
MTR_LOG("%s", __PRETTY_FUNCTION__);
100107
[self _callDelegatesWithBlock:^(id<MTRDeviceDelegate> delegate) {
101108
[delegate device:self receivedEventReport:eventReport];
102109
}];
103110
}
111+
112+
// optional methods for MTRDeviceDelegates - check for implementation before calling
104113
- (oneway void)deviceBecameActive:(NSNumber *)nodeID
105114
{
115+
MTR_LOG("%s", __PRETTY_FUNCTION__);
106116
[self _callDelegatesWithBlock:^(id<MTRDeviceDelegate> delegate) {
107-
[delegate deviceBecameActive:self];
117+
if ([delegate respondsToSelector:@selector(deviceBecameActive:)]) {
118+
[delegate deviceBecameActive:self];
119+
}
108120
}];
109121
}
122+
110123
- (oneway void)deviceCachePrimed:(NSNumber *)nodeID
111124
{
112125
[self _callDelegatesWithBlock:^(id<MTRDeviceDelegate> delegate) {
113-
[delegate deviceCachePrimed:self];
126+
if ([delegate respondsToSelector:@selector(deviceCachePrimed:)]) {
127+
[delegate deviceCachePrimed:self];
128+
}
114129
}];
115130
}
131+
116132
- (oneway void)deviceConfigurationChanged:(NSNumber *)nodeID
117133
{
118134
[self _callDelegatesWithBlock:^(id<MTRDeviceDelegate> delegate) {
119-
[delegate deviceConfigurationChanged:self];
135+
if ([delegate respondsToSelector:@selector(deviceConfigurationChanged:)]) {
136+
[delegate deviceConfigurationChanged:self];
137+
}
120138
}];
121139
}
122140

0 commit comments

Comments
 (0)