Skip to content

Commit

Permalink
[Darwin] Enable taking assertion on MTRDeviceController
Browse files Browse the repository at this point in the history
- Added ability to take assertion on MTRDeviceController to keep it
  running until all assertions are removed
- A request to shutdown will take place only if there are no assertions
  are present
  • Loading branch information
anush-apple committed Aug 22, 2024
1 parent 07789d4 commit 910c152
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ - (instancetype)initForSubclasses
// nothing, as superclass of MTRDeviceController is NSObject
}
_underlyingDeviceMapLock = OS_UNFAIR_LOCK_INIT;

// Setup assertion counters
_keepRunningAssertionCounter = 0;
_shutdownPending = FALSE;
return self;
}

Expand Down Expand Up @@ -178,6 +182,11 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory
// Make sure our storage is all set up to work as early as possible,
// before we start doing anything else with the controller.
_uniqueIdentifier = uniqueIdentifier;

// Setup assertion counters
_keepRunningAssertionCounter = 0;
_shutdownPending = FALSE;

if (storageDelegate != nil) {
if (storageDelegateQueue == nil) {
MTR_LOG_ERROR("storageDelegate provided without storageDelegateQueue");
Expand Down Expand Up @@ -311,7 +320,53 @@ - (BOOL)isRunning
return _cppCommissioner != nullptr;
}

- (NSUInteger)shutdownPrecheck
{
__block NSUInteger assertionCount = 0;
dispatch_sync(_chipWorkQueue, ^{
self.shutdownPending = TRUE;
assertionCount = self.keepRunningAssertionCounter;
});
return assertionCount;
}

- (void)addRunAssertion
{
dispatch_sync(_chipWorkQueue, ^{
++self.keepRunningAssertionCounter;
MTR_LOG("%@ Adding keep running assertion, total %lu", self, self.keepRunningAssertionCounter);
});
}

- (void)removeRunAssertion;
{
__block BOOL shouldShutdown = FALSE;
dispatch_sync(_chipWorkQueue, ^{
if (self.keepRunningAssertionCounter > 0) {
--self.keepRunningAssertionCounter;
MTR_LOG("%@ Removing keep running assertion, total %lu", self, self.keepRunningAssertionCounter);
if (self.keepRunningAssertionCounter == 0 && self.shutdownPending) {
shouldShutdown = TRUE;
}
}
});
if (shouldShutdown) {
MTR_LOG("%@ All assertions removed and shutdown is pending, shutting down", self);
[self finalShutdown];
}
}

- (void)shutdown
{
NSUInteger assertionCount = [self shutdownPrecheck];
if (assertionCount != 0) {
MTR_LOG("%@ Pending shutdown since %lu assertions are present", self, assertionCount);
return;
}
[self finalShutdown];
}

- (void)finalShutdown
{
MTR_LOG("%@ shutdown called", self);
if (_cppCommissioner == nullptr) {
Expand Down Expand Up @@ -374,6 +429,7 @@ - (void)shutDownCppController
_operationalCredentialsDelegate->SetDeviceCommissioner(nullptr);
}
}
self.shutdownPending = FALSE;
}

- (void)deinitFromFactory
Expand Down
10 changes: 10 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,16 @@ - (BOOL)isRunning
}

- (void)shutdown
{
NSUInteger assertionCount = [self shutdownPrecheck];
if (assertionCount != 0) {
MTR_LOG("%@ Pending shutdown since %lu assertions are present", self, assertionCount);
return;
}
[self finalShutdown];
}

- (void)finalShutdown
{
MTR_LOG("%@ shutdown called", self);
if (_cppCommissioner == nullptr) {
Expand Down
25 changes: 25 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceController_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ NS_ASSUME_NONNULL_BEGIN
// (moved here so subclasses can initialize differently)
@property (readwrite, retain) dispatch_queue_t chipWorkQueue;

// Counters to track assertion status
@property (nonatomic, readwrite) NSUInteger keepRunningAssertionCounter;
@property (nonatomic, readwrite) BOOL shutdownPending;

- (instancetype)initForSubclasses;

#pragma mark - MTRDeviceControllerFactory methods
Expand Down Expand Up @@ -289,6 +293,27 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)directlyGetSessionForNode:(chip::NodeId)nodeID completion:(MTRInternalDeviceConnectionCallback)completion;

/**
* Takes an assertion to keep the controller running. If `-[MTRDeviceController shutdown]` is called while an assertion
* is held, the shutdown will be honored only after all assertions are released. Invoking this method multiple times increases
* the number of assertions and needs to be matched with equal amount of '-[MTRDeviceController removeRunAssertion]` to release
* the assertion.
*/
- (void)addRunAssertion;

/**
* Removes an assertion to allow the controller to shutdown once all assertions have been released.
* Invoking this method once all assertions have been released in a noop.
*/
- (void)removeRunAssertion;

/**
* This methods marks a request to shutdown.
* Returns the number of run assertions currently being held. If the value returned is not zero, it implies shutdown has to be delayed
* until all assertions have been removed.
*/
- (NSUInteger)shutdownPrecheck;

@end

/**
Expand Down

0 comments on commit 910c152

Please sign in to comment.