Objectively
Object oriented framework for C.
Loading...
Searching...
No Matches
OperationQueue.c File Reference
#include <assert.h>
#include "OperationQueue.h"

Go to the source code of this file.

Macros

#define _Class   _OperationQueue
 

Functions

Class_OperationQueue (void)
 
static void addOperation (OperationQueue *self, Operation *operation)
 
static OperationaddOperationWithFunction (OperationQueue *self, OperationFunction function, ident data)
 
static void cancelAllOperations (OperationQueue *self)
 
static Objectcopy (const Object *self)
 
static OperationQueuecurrentQueue (void)
 
static void dealloc (Object *self)
 
static OperationQueueinit (OperationQueue *self)
 
static void initialize (Class *clazz)
 
static OperationQueueinitWithMaxConcurrentOperations (OperationQueue *self, size_t maxConcurrentOperations)
 
static bool isOperationReady (const ident obj, ident data)
 Predicate matching the next Operation eligible to start.
 
static size_t operationCount (const OperationQueue *self)
 
static Arrayoperations (const OperationQueue *self)
 
static void removeOperation (OperationQueue *self, Operation *operation)
 
static void resume (OperationQueue *self)
 
static ident run (Thread *thread)
 ThreadFunction for the OperationQueue Threads.
 
static void suspend (OperationQueue *self)
 
static void waitUntilAllOperationsAreFinished (OperationQueue *self)
 

Variables

static __thread OperationQueue_currentQueue
 

Macro Definition Documentation

◆ _Class

#define _Class   _OperationQueue

Definition at line 28 of file OperationQueue.c.

Function Documentation

◆ _OperationQueue()

Class * _OperationQueue ( void  )

Definition at line 349 of file OperationQueue.c.

349 {
350 static Class *clazz;
351 static Once once;
352
353 do_once(&once, {
354 clazz = _initialize(&(const ClassDef) {
355 .name = "OperationQueue",
356 .superclass = _Object(),
357 .instanceSize = sizeof(OperationQueue),
358 .interfaceOffset = offsetof(OperationQueue, interface),
359 .interfaceSize = sizeof(OperationQueueInterface),
361 });
362 });
363
364 return clazz;
365}
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition Class.c:129
Class * _Object(void)
Definition Object.c:136
static void initialize(Class *clazz)
long Once
The Once type.
Definition Once.h:37
#define do_once(once, block)
Executes the given block at most one time.
Definition Once.h:43
ClassDefs are passed to _initialize via an archetype to initialize a Class.
Definition Class.h:41
The runtime representation of a Class.
Definition Class.h:95
OperationQueues provide threads of execution for Operations.

◆ addOperation()

static void addOperation ( OperationQueue self,
Operation operation 
)
static

Definition at line 74 of file OperationQueue.c.

74 {
75
76 assert(operation);
77 assert(operation->isCancelled == false);
78 assert(operation->isExecuting == false);
79 assert(operation->isFinished == false);
80
81 synchronized(self->locals.condition, {
82 operation->locals.queue = self;
83 $(self->locals.operations, addObject, operation);
84 $(self->locals.condition, signal);
85 });
86}
static void addObject(Array *self, const ident obj)
Definition Array.c:181
bool isCancelled
true when this Operation has been cancelled, false otherwise.
Definition Operation.h:108
bool isFinished
true when this Operation is finished, false otherwise.
Definition Operation.h:124
OperationQueue * queue
The OperationQueue this Operation was added to, if any.
Definition Operation.h:86
bool isExecuting
true when this Operation is executing, false otherwise.
Definition Operation.h:119
Array * operations
The Operations.
Condition * condition
A condition signaled on addOperation and removeOperation.

◆ addOperationWithFunction()

static Operation * addOperationWithFunction ( OperationQueue self,
OperationFunction  function,
ident  data 
)
static

Definition at line 92 of file OperationQueue.c.

92 {
93
94 assert(function);
95
96 Operation *operation = $(alloc(Operation), initWithFunction, function, data);
97
98 $(self, addOperation, operation);
99
100 return operation;
101}
#define alloc(type)
Allocate and initialize and instance of type.
Definition Class.h:222
static Data * data(void)
Definition Data.c:286
static Operation * initWithFunction(Operation *self, OperationFunction function, ident data)
Definition Operation.c:125
static void addOperation(OperationQueue *self, Operation *operation)
An abstraction for discrete units of work, or tasks.
Definition Operation.h:53

◆ cancelAllOperations()

static void cancelAllOperations ( OperationQueue self)
static

Definition at line 107 of file OperationQueue.c.

107 {
108
109 Array *operations = $(self, operations);
110
111 for (size_t i = 0; i < operations->count; i++) {
113 }
114
116}
static ident objectAtIndex(const Array *self, size_t index)
Definition Array.c:578
ident release(ident obj)
Atomically decrement the given Object's reference count. If the resulting reference count is 0,...
Definition Class.c:335
static void cancel(Operation *self)
Definition Operation.c:73
static Array * operations(const OperationQueue *self)
Arrays.
Definition Array.h:56
size_t count
The count of elements.
Definition Array.h:72

◆ copy()

static Object * copy ( const Object self)
static
See also
Object::copy(const Object *)

Definition at line 35 of file OperationQueue.c.

35 {
36
37 return NULL;
38}

◆ currentQueue()

static OperationQueue * currentQueue ( void  )
static

Definition at line 124 of file OperationQueue.c.

124 {
125 return _currentQueue;
126}
static __thread OperationQueue * _currentQueue

◆ dealloc()

static void dealloc ( Object self)
static
See also
Object::dealloc(Object *)

Definition at line 43 of file OperationQueue.c.

43 {
44
45 OperationQueue *this = (OperationQueue *) self;
46
47 const Array *threads = (Array *) this->locals.threads;
48
49 for (size_t i = 0; i < threads->count; i++) {
50 $((Thread *) $(threads, objectAtIndex, i), cancel);
51 }
52
53 synchronized(this->locals.condition, {
54 $(this->locals.condition, broadcast);
55 });
56
57 for (size_t i = 0; i < threads->count; i++) {
58 $((Thread *) $(threads, objectAtIndex, i), join, NULL);
59 }
60
61 release(this->locals.threads);
62 release(this->locals.condition);
63 release(this->locals.operations);
64
65 super(Object, self, dealloc);
66}
#define super(type, obj, method,...)
static void broadcast(Condition *self)
Definition Condition.c:57
static void dealloc(Object *self)
static void join(Thread *self, ident *status)
Definition Thread.c:131
Object is the root Class of The Objectively Class hierarchy.
Definition Object.h:46
POSIX Threads.
Definition Thread.h:53

◆ init()

static OperationQueue * init ( OperationQueue self)
static

Definition at line 182 of file OperationQueue.c.

182 {
183 return $(self, initWithMaxConcurrentOperations, 1);
184}
static OperationQueue * initWithMaxConcurrentOperations(OperationQueue *self, size_t maxConcurrentOperations)

◆ initialize()

static void initialize ( Class clazz)
static
See also
Class::initialize(Class *)

Definition at line 326 of file OperationQueue.c.

326 {
327
328 ((ObjectInterface *) clazz->interface)->copy = copy;
329 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
330
331 ((OperationQueueInterface *) clazz->interface)->addOperation = addOperation;
332 ((OperationQueueInterface *) clazz->interface)->addOperationWithFunction = addOperationWithFunction;
333 ((OperationQueueInterface *) clazz->interface)->cancelAllOperations = cancelAllOperations;
334 ((OperationQueueInterface *) clazz->interface)->currentQueue = currentQueue;
335 ((OperationQueueInterface *) clazz->interface)->init = init;
336 ((OperationQueueInterface *) clazz->interface)->initWithMaxConcurrentOperations = initWithMaxConcurrentOperations;
337 ((OperationQueueInterface *) clazz->interface)->operationCount = operationCount;
338 ((OperationQueueInterface *) clazz->interface)->operations = operations;
339 ((OperationQueueInterface *) clazz->interface)->removeOperation = removeOperation;
340 ((OperationQueueInterface *) clazz->interface)->resume = resume;
341 ((OperationQueueInterface *) clazz->interface)->suspend = suspend;
342 ((OperationQueueInterface *) clazz->interface)->waitUntilAllOperationsAreFinished = waitUntilAllOperationsAreFinished;
343}
static void resume(OperationQueue *self)
static void removeOperation(OperationQueue *self, Operation *operation)
static size_t operationCount(const OperationQueue *self)
static OperationQueue * currentQueue(void)
static void waitUntilAllOperationsAreFinished(OperationQueue *self)
static void suspend(OperationQueue *self)
static Operation * addOperationWithFunction(OperationQueue *self, OperationFunction function, ident data)
static void cancelAllOperations(OperationQueue *self)
static OperationQueue * init(OperationQueue *self)
static Object * copy(const Object *self)
ident interface
The interface of the Class.
Definition Class.h:105
void dealloc(Object *self)
Frees all resources held by this Object.
Definition Array.c:99
size_t operationCount(const OperationQueue *self)
OperationQueue * initWithMaxConcurrentOperations(OperationQueue *self, size_t maxConcurrentOperations)
Initializes this OperationQueue with the given concurrency.
OperationQueue * init(OperationQueue *self)
Initializes this OperationQueue as a serial queue.

◆ initWithMaxConcurrentOperations()

static OperationQueue * initWithMaxConcurrentOperations ( OperationQueue self,
size_t  maxConcurrentOperations 
)
static

Definition at line 190 of file OperationQueue.c.

190 {
191
192 assert(maxConcurrentOperations);
193
194 self = (OperationQueue *) super(Object, self, init);
195 if (self) {
196
197 self->locals.condition = $(alloc(Condition), init);
198 assert(self->locals.condition);
199
200 self->locals.operations = $(alloc(Array), init);
201 assert(self->locals.operations);
202
203 self->locals.threads = $(alloc(Array), init);
204 assert(self->locals.threads);
205
206 for (size_t i = 0; i < maxConcurrentOperations; i++) {
207
208 Thread *thread = $(alloc(Thread), initWithFunction, run, self);
209 assert(thread);
210
211 $(self->locals.threads, addObject, thread);
212
213 release(thread);
214 }
215
216 const Array *threads = (Array *) self->locals.threads;
217 for (size_t i = 0; i < threads->count; i++) {
218 $((Thread *) $(threads, objectAtIndex, i), start);
219 }
220 }
221
222 return self;
223}
static void start(Operation *self)
Definition Operation.c:177
static ident run(Thread *thread)
ThreadFunction for the OperationQueue Threads.
POSIX Threads conditional variables.
Definition Condition.h:44
Array * threads
The backing Threads, one per concurrently executing Operation.

◆ isOperationReady()

static bool isOperationReady ( const ident  obj,
ident  data 
)
static

Predicate matching the next Operation eligible to start.

Definition at line 131 of file OperationQueue.c.

131 {
132 return $((Operation *) obj, isReady);
133}
#define obj
static bool isReady(const Operation *self)
Definition Operation.c:140

◆ operationCount()

static size_t operationCount ( const OperationQueue self)
static

Definition at line 229 of file OperationQueue.c.

229 {
230
231 size_t count;
232
233 synchronized(self->locals.condition, {
234 count = ((Array *) self->locals.operations)->count;
235 });
236
237 return count;
238}

◆ operations()

static Array * operations ( const OperationQueue self)
static

Definition at line 244 of file OperationQueue.c.

244 {
245
247
248 synchronized(self->locals.condition, {
249 operations = $((Object * ) self->locals.operations, copy);
250 });
251
252 return (Array *) operations;
253}
void * ident
The identity type, similar to Objective-C id.
Definition Types.h:49

◆ removeOperation()

static void removeOperation ( OperationQueue self,
Operation operation 
)
static

Definition at line 259 of file OperationQueue.c.

259 {
260
261 assert(operation);
262 assert(operation->isExecuting == false);
263
264 synchronized(self->locals.condition, {
265 operation->locals.queue = NULL;
266 $(self->locals.operations, removeObject, operation);
267 $(self->locals.condition, signal);
268 });
269}
static void removeObject(Array *self, const ident obj)
Definition Array.c:642

◆ resume()

static void resume ( OperationQueue self)
static

Definition at line 275 of file OperationQueue.c.

275 {
276
277 synchronized(self->locals.condition, {
278 self->isSuspended = false;
279 $(self->locals.condition, broadcast);
280 });
281}
bool isSuspended
When true, the queue will not start any new Operations.

◆ run()

static ident run ( Thread thread)
static

ThreadFunction for the OperationQueue Threads.

Definition at line 138 of file OperationQueue.c.

138 {
139
140 OperationQueue *self = _currentQueue = thread->data;
141
142 bool isCancelled = false;
143
144 while (!isCancelled) {
145
146 Operation *operation = NULL;
147
148 synchronized(self->locals.condition, {
149
150 isCancelled = thread->isCancelled;
151
152 if (!isCancelled && self->isSuspended == false) {
153
154 operation = $(self->locals.operations, find, isOperationReady, NULL);
155 if (operation) {
156 operation->isDispatched = true;
157 $(self->locals.condition, signal);
158 }
159 }
160
161 if (operation == NULL && !isCancelled) {
162 $(self->locals.condition, wait);
163 }
164 });
165
166 if (operation == NULL) {
167 continue;
168 }
169
170 $(operation, start);
171
172 $(self, removeOperation, operation);
173 }
174
175 return NULL;
176}
static ident find(const Array *self, Predicate predicate, ident data)
Definition Array.c:377
static bool isOperationReady(const ident obj, ident data)
Predicate matching the next Operation eligible to start.
bool isDispatched
True once an OperationQueue has dispatched this Operation to one of its Threads, so that no other Thr...
Definition Operation.h:114
ident data
The user data.
Definition Thread.h:69
bool isCancelled
true when this Thread has been cancelled, false otherwise.
Definition Thread.h:79

◆ suspend()

static void suspend ( OperationQueue self)
static

Definition at line 287 of file OperationQueue.c.

287 {
288
289 synchronized(self->locals.condition, {
290 self->isSuspended = true;
291 });
292}

◆ waitUntilAllOperationsAreFinished()

static void waitUntilAllOperationsAreFinished ( OperationQueue self)
static

Definition at line 298 of file OperationQueue.c.

298 {
299
300 while (true) {
301
302 Operation *operation = NULL;
303
304 synchronized(self->locals.condition, {
305 const Array *operations = (Array *) self->locals.operations;
306 if (operations->count) {
307 operation = retain($(operations, firstObject));
308 }
309 });
310
311 if (operation == NULL) {
312 break;
313 }
314
315 $(operation, waitUntilFinished);
316
317 release(operation);
318 }
319}
static ident firstObject(const Array *self)
Definition Array.c:394
ident retain(ident obj)
Atomically increment the given Object's reference count.
Definition Class.c:350
static void waitUntilFinished(const Operation *self)
Definition Operation.c:200

Variable Documentation

◆ _currentQueue

__thread OperationQueue* _currentQueue
static

Definition at line 118 of file OperationQueue.c.