@@ -33,20 +33,6 @@ typedef NS_ENUM(NSInteger, MTRAsyncWorkItemState) {
33
33
MTRAsyncWorkItemRetryCountBase = MTRAsyncWorkItemRunning, // values >= MTRAsyncWorkItemRunning encode retryCount
34
34
};
35
35
36
- // A helper struct that facilitates access to _context while
37
- // - only reading the _context weak reference once and retaining a strong
38
- // reference for the duration of a particular queue method call
39
- // - avoiding calls to `[context description]` under our lock
40
- struct ContextSnapshot {
41
- id _Nullable reference;
42
- NSString * _Nullable description;
43
- ContextSnapshot (id _Nullable context)
44
- {
45
- reference = context;
46
- description = [context description ];
47
- }
48
- };
49
-
50
36
MTR_DIRECT_MEMBERS
51
37
@implementation MTRAsyncWorkItem {
52
38
dispatch_queue_t _queue;
@@ -214,6 +200,21 @@ @implementation MTRAsyncWorkQueue {
214
200
NSInteger _runningWorkItemCount;
215
201
}
216
202
203
+ // A helper struct that facilitates access to _context while
204
+ // - only reading the _context weak reference once and retaining a strong
205
+ // reference for the duration of a particular queue method call
206
+ // - avoiding calls to `[context description]` under our lock
207
+ struct ContextSnapshot {
208
+ id _Nullable reference;
209
+ NSString * _Nullable description;
210
+ ContextSnapshot (MTRAsyncWorkQueue * queue)
211
+ {
212
+ os_unfair_lock_assert_not_owner (&queue->_lock );
213
+ reference = queue->_context ;
214
+ description = [reference description ];
215
+ }
216
+ };
217
+
217
218
- (instancetype )initWithContext : (id )context
218
219
{
219
220
NSParameterAssert (context);
@@ -224,13 +225,18 @@ - (instancetype)initWithContext:(id)context
224
225
return self;
225
226
}
226
227
228
+ - (NSString *)_lockedSelfDescription : (const ContextSnapshot &)context
229
+ {
230
+ os_unfair_lock_assert_owner (&_lock);
231
+
232
+ return [NSString stringWithFormat: @" %@ , items count: %tu " , context.description, _items.count];
233
+ }
234
+
227
235
- (NSString *)description
228
236
{
229
- NSUInteger itemsCount;
230
- os_unfair_lock_lock (&_lock);
231
- itemsCount = _items.count ;
232
- os_unfair_lock_unlock (&_lock);
233
- return [NSString stringWithFormat: @" <%@ context: %@ items count: %tu >" , self .class , _context, itemsCount];
237
+ ContextSnapshot context (self);
238
+ std::lock_guard lock (_lock);
239
+ return [NSString stringWithFormat: @" <%@ context: %@ >" , self .class , [self _lockedSelfDescription: context]];
234
240
}
235
241
236
242
- (void )enqueueWorkItem : (MTRAsyncWorkItem *)item
@@ -251,29 +257,28 @@ - (void)enqueueWorkItem:(MTRAsyncWorkItem *)item
251
257
description : (nullable NSString *)description
252
258
{
253
259
NSParameterAssert (item);
254
- ContextSnapshot context (_context ); // outside of lock
260
+ ContextSnapshot context (self ); // outside of lock
255
261
NSAssert (context.reference, @" context has been lost" );
256
262
257
- os_unfair_lock_lock (& _lock);
263
+ std::lock_guard lock ( _lock);
258
264
[item markEnqueued ];
259
265
[_items addObject: item];
260
266
261
267
if (description) {
262
268
// Logging the description once is enough because other log messages
263
269
// related to the work item (execution, completion etc) can easily be
264
270
// correlated using the unique id.
265
- MTR_LOG_DEFAULT (" MTRAsyncWorkQueue<%@> enqueued work item [%llu]: %@" , context. description , item.uniqueID , description);
271
+ MTR_LOG_DEFAULT (" MTRAsyncWorkQueue<%@> enqueued work item [%llu]: %@" , [ self _lockedSelfDescription: context] , item.uniqueID , description);
266
272
} else {
267
- MTR_LOG_DEFAULT (" MTRAsyncWorkQueue<%@> enqueued work item [%llu]" , context. description , item.uniqueID );
273
+ MTR_LOG_DEFAULT (" MTRAsyncWorkQueue<%@> enqueued work item [%llu]" , [ self _lockedSelfDescription: context] , item.uniqueID );
268
274
}
269
275
270
276
[self _callNextReadyWorkItemWithContext: context];
271
- os_unfair_lock_unlock (&_lock);
272
277
}
273
278
274
279
- (void )invalidate
275
280
{
276
- ContextSnapshot context (_context ); // outside of lock
281
+ ContextSnapshot context (self ); // outside of lock
277
282
std::lock_guard lock (_lock);
278
283
MTR_LOG_INFO (" MTRAsyncWorkQueue<%@> invalidate %tu items" , context.description , _items.count );
279
284
for (MTRAsyncWorkItem * item in _items) {
@@ -299,7 +304,7 @@ - (void)_postProcessWorkItem:(MTRAsyncWorkItem *)workItem
299
304
} else {
300
305
[workItem markComplete ];
301
306
[_items removeObjectAtIndex: 0 ];
302
- MTR_LOG_DEFAULT (" MTRAsyncWorkQueue<%@> completed work item [%llu]" , context. description , workItem.uniqueID );
307
+ MTR_LOG_DEFAULT (" MTRAsyncWorkQueue<%@> completed work item [%llu]" , [ self _lockedSelfDescription: context] , workItem.uniqueID );
303
308
}
304
309
305
310
// when "concurrency width" is implemented this will be decremented instead
@@ -362,13 +367,12 @@ - (void)_callNextReadyWorkItemWithContext:(ContextSnapshot const &)context
362
367
mtr_strongify (self);
363
368
BOOL handled = NO ;
364
369
if (self) {
365
- ContextSnapshot context (self-> _context ); // re-acquire a new snapshot
366
- os_unfair_lock_lock (& self->_lock );
370
+ ContextSnapshot context (self); // re-acquire a new snapshot
371
+ std::lock_guard lock ( self->_lock );
367
372
if (!workItem.isComplete ) {
368
373
[self _postProcessWorkItem: workItem context: context retry: (outcome == MTRAsyncWorkNeedsRetry)];
369
374
handled = YES ;
370
375
}
371
- os_unfair_lock_unlock (&self->_lock );
372
376
}
373
377
return handled;
374
378
}];
0 commit comments