18
18
#import < dispatch/dispatch.h>
19
19
#import < os/lock.h>
20
20
21
- #import " MTRAsyncCallbackWorkQueue_Internal .h"
21
+ #import " MTRAsyncCallbackWorkQueue .h"
22
22
#import " MTRLogging.h"
23
23
24
24
#pragma mark - Class extensions
25
25
26
26
@interface MTRAsyncCallbackWorkQueue ()
27
+ // The lock protects the internal state of the work queue so that these may be called from any queue or thread:
28
+ // -enqueueWorkItem:
29
+ // -invalidate
30
+ // -endWork:
31
+ // -retryWork:
27
32
@property (nonatomic , readonly ) os_unfair_lock lock;
28
33
@property (nonatomic , strong , readonly ) id context;
29
34
@property (nonatomic , strong , readonly ) dispatch_queue_t queue;
@@ -81,7 +86,8 @@ - (void)invalidate
81
86
[invalidateItems removeAllObjects ];
82
87
}
83
88
84
- - (void )endWork : (MTRAsyncCallbackQueueWorkItem *)workItem
89
+ // called after executing a work item
90
+ - (void )_postProcessWorkItem : (MTRAsyncCallbackQueueWorkItem *)workItem retry : (BOOL )retry
85
91
{
86
92
os_unfair_lock_lock (&_lock);
87
93
// sanity check if running
@@ -102,41 +108,25 @@ - (void)endWork:(MTRAsyncCallbackQueueWorkItem *)workItem
102
108
return ;
103
109
}
104
110
105
- // since work is done, remove from queue and call ready on the next item
106
- [self .items removeObjectAtIndex: 0 ];
111
+ // if work item is done (no need to retry), remove from queue and call ready on the next item
112
+ if (!retry) {
113
+ [self .items removeObjectAtIndex: 0 ];
114
+ }
107
115
108
116
// when "concurrency width" is implemented this will be decremented instead
109
117
self.runningWorkItemCount = 0 ;
110
118
[self _callNextReadyWorkItem ];
111
119
os_unfair_lock_unlock (&_lock);
112
120
}
113
121
114
- - (void )retryWork : (MTRAsyncCallbackQueueWorkItem *)workItem
122
+ - (void )endWork : (MTRAsyncCallbackQueueWorkItem *)workItem
115
123
{
116
- // reset BOOL and call again
117
- os_unfair_lock_lock (&_lock);
118
- // sanity check if running
119
- if (!self.runningWorkItemCount ) {
120
- // something is wrong with state - nothing is currently running
121
- os_unfair_lock_unlock (&_lock);
122
- MTR_LOG_ERROR (" retryWork: no work is running on work queue" );
123
- return ;
124
- }
125
-
126
- // sanity check the same work item is running
127
- // when "concurrency width" is implemented need to check first N items
128
- MTRAsyncCallbackQueueWorkItem * firstWorkItem = self.items .firstObject ;
129
- if (firstWorkItem != workItem) {
130
- // something is wrong with this work item - should not be currently running
131
- os_unfair_lock_unlock (&_lock);
132
- MTR_LOG_ERROR (" retryWork: work item is not first on work queue" );
133
- return ;
134
- }
124
+ [self _postProcessWorkItem: workItem retry: NO ];
125
+ }
135
126
136
- // when "concurrency width" is implemented this will be decremented instead
137
- self.runningWorkItemCount = 0 ;
138
- [self _callNextReadyWorkItem ];
139
- os_unfair_lock_unlock (&_lock);
127
+ - (void )retryWork : (MTRAsyncCallbackQueueWorkItem *)workItem
128
+ {
129
+ [self _postProcessWorkItem: workItem retry: YES ];
140
130
}
141
131
142
132
// assume lock is held while calling this
@@ -166,13 +156,11 @@ - (instancetype)initWithQueue:(dispatch_queue_t)queue
166
156
return self;
167
157
}
168
158
169
- // Called by Cluster object's after async work is done
170
159
- (void )endWork
171
160
{
172
161
[self .workQueue endWork: self ];
173
162
}
174
163
175
- // Called by Cluster object's after async work is done
176
164
- (void )retryWork
177
165
{
178
166
[self .workQueue retryWork: self ];
0 commit comments