]> Dogcows Code - chaz/thecheat/blob - ThreadedTask.h
The Cheat 1.2.1
[chaz/thecheat] / ThreadedTask.h
1
2 //
3 // ThreadedTask 0.3
4 // Perform a long task without blocking the main thread.
5 //
6 // Copyright (c) 2004-2005, Chaz McGarvey
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without modification, are
10 // permitted provided that the following conditions are met:
11 //
12 // 1. Redistributions of source code must retain the above copyright notice, this list
13 // of conditions and the following disclaimer.
14 //
15 // 2. Redistributions in binary form must reproduce the above copyright notice, this
16 // list of conditions and the following disclaimer in the documentation and/or other
17 // materials provided with the distribution.
18 //
19 // 3. Neither the name of the BrokenZipper nor the names of its contributors may be
20 // used to endorse or promote products derived from this software without specific
21 // prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
24 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
26 // SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 // DAMAGE.
33 //
34 // Web: http://www.brokenzipper.com/
35 // Email: chaz@brokenzipper.com
36 //
37
38 #import <Cocoa/Cocoa.h>
39
40
41 @interface ThreadedTask : NSObject
42 {
43 // task objects
44 id _target;
45 SEL _selector;
46 int (*_function)(id, unsigned);
47 id _context;
48 // keeping track of things...
49 BOOL _isTaskThreadRunning;
50 BOOL _doCancelTask;
51 // the delegate object
52 id _delegate;
53 NSRunLoop *_runloop;
54 NSArray *_modes;
55 // locks
56 NSLock *_taskLock;
57 }
58
59 // #############################################################################
60 #pragma mark Initialization
61 // #############################################################################
62
63 /* See accessor methods for a description of the parameters. */
64 - (id)initWithTarget:(id)target selector:(SEL)selector delegate:(id)delegate;
65 - (id)initWithTarget:(id)target selector:(SEL)selector context:(id)context delegate:(id)delegate;
66 - (id)initWithFunction:(int (*)(ThreadedTask *, unsigned))function delegate:(id)delegate;
67 - (id)initWithFunction:(int (*)(ThreadedTask *, unsigned))function context:(id)context delegate:(id)delegate;
68
69
70 // #############################################################################
71 #pragma mark Accessor Methods
72 // #############################################################################
73
74 /*
75 * As a protection, it is not possible to change the iteration method or function,
76 * or the context while the task is running.
77 */
78
79 /*
80 * The target is the object (or class) that the selector is used on. Target is
81 * not retained.
82 *
83 * The selector which should be used should be in this form:
84 *
85 * - (int)task:(ThreadedTask *)task iteration:(unsigned)iteration;
86 *
87 * The task parameter is the ThreadedTask object belonging to the task.
88 * The iteration parameter increases by one for each iteration that passes.
89 *
90 * The return value is the important part. It's what tells task object
91 * whether to continue or stop or report a failure. Here are the values:
92 *
93 * Returning 1 means the task is not finished, and the iteration method
94 * or function will be called again.
95 * Returning 0 means the task is finished, and to end it.
96 * Returning _anything_ else and the task will assume it is an error code;
97 * the task would then abort and report the error code to the delegate.
98 *
99 * The target and selector will be set to nil if either are not valid.
100 */
101 - (id)target;
102 - (SEL)selector;
103 - (void)setTarget:(id)target selector:(SEL)selector;
104
105 /*
106 * A function can be used instead of a target and selector. The function
107 * should be in the following form:
108 *
109 * int MyTask( ThreadedTask *task, unsigned iteration );
110 *
111 * The parameters and return value are the same as for the selector. The
112 * task uses the function if setFunction: was called after setTarget:, or
113 * if setTarget: was never called.
114 */
115
116 - (int (*)(id, unsigned))function;
117 - (void)setFunction:(int (*)(id, unsigned))function;
118
119 /*
120 * The context of the threaded task can be any object. It is set before
121 * the task is run. The iteration method/function can retrieve this
122 * context from the task and use it to safely store results from the
123 * task. The context can also be nil if the iteration doesn't need it.
124 */
125 - (id)context;
126 - (void)setContext:(id)context;
127
128 /*
129 * Delegation is how information is received from the task. Setting a
130 * delegate isn't required, but it's pointless not to do so. Unlike
131 * the above accessors, the delegate can be changed while a task is running.
132 * A runloop can also be specified which is used to send the delegate
133 * methods using the given modes. If no runloop is specified, the current
134 * runloop for the thread which runs the threaded task is used. Neither
135 * the delegate or the runloop are retained, but the modes are. If a
136 * runloop is not specified and there is no current runloop, then no delegate
137 * methods will be sent. Pass nil for modes to use the mode of the current
138 * runloop.
139 */
140 - (id)delegate;
141 - (void)setDelegate:(id)delegate;
142 - (void)setDelegateRunLoop:(NSRunLoop *)runloop modes:(NSArray *)modes;
143
144 /*
145 * Returns YES if the thread is detached and the task is being performed.
146 */
147 - (BOOL)isRunning;
148
149
150 // #############################################################################
151 #pragma mark Control Methods
152 // #############################################################################
153
154 /*
155 * Begin execution of the task. This method returns immediately.
156 * The delegate will recieve threadedTaskFinished: when the task has completed
157 * its purpose. This method will return YES if the task was successfully
158 * started, and NO if the task could not be run, which usually occurs if the
159 * iteration method/selector or function is not valid.
160 */
161 - (BOOL)run;
162
163 /*
164 * General information about cancelling: If you release the ThreadedTask object
165 * while a task is running, the task will be cancelled for you automatically
166 * and this is generally safe to do, but the release may block the main thread
167 * for a short amount of time while the task cancels. This can be avoided by
168 * using a cancel method below which doesn't block.
169 */
170
171 /*
172 * Signal the task to cancel prematurely. This method will block until the
173 * task actually does cancel. It is safe to release the ThreadedTask object
174 * any time after this call without blocking. If the iteration method or
175 * function is blocking for some reason, you should used a different cancel
176 * method which doesn't block, otherwise a deadlock could occur.
177 */
178 - (void)cancel;
179
180 /*
181 * Signal the task to cancel prematurely. This method returns immediately, but
182 * you should not release the ThreadedTask object until the delegate receives
183 * a conclusion method.
184 */
185 - (void)cancelWithoutWaiting;
186
187 /*
188 * Signal the task to cancel prematurely. This is a convenience method that
189 * sets the delegate to nil and cancels the task without blocking at the same
190 * time. This is useful if the delegate is going to be released while the task
191 * is running. You should not release the ThreadedTask object immediately
192 * after this call, but you will also not receive any notification that it is
193 * safe to do so. You will know when receiver can be released without blocking
194 * when the isRunning method returns NO.
195 */
196 - (void)cancelAndRemoveDelegate;
197
198
199 // #############################################################################
200 #pragma mark Iteration Methods
201 // #############################################################################
202
203 /*
204 * Report progress of the task back to the main thread. This method should only
205 * be called from the iteration method or function. It takes a single integer
206 * parameter which can be anything the receiver of the progress report will
207 * understand (perhaps 0 thru 100, like as a percentage).
208 */
209 - (void)reportProgress:(int)progress;
210
211 @end
212
213
214 @interface NSObject ( ThreadedTaskDelegate )
215
216 // #############################################################################
217 #pragma mark Delegate Methods
218 // #############################################################################
219
220 /*
221 * These delegate methods are sent on the thread running the delegate runloop,
222 * or the main runloop if none is specified. It is typically safe to update
223 * the user interface from these methods.
224 */
225
226 /*
227 * Sent to the delegate upon completion of the task.
228 */
229 - (void)threadedTaskFinished:(ThreadedTask *)theTask;
230
231 /*
232 * Sent to the delegate when the task has finished cancelling.
233 */
234 - (void)threadedTaskCancelled:(ThreadedTask *)theTask;
235
236 /*
237 * Sent to the delegate when the iteration returned an error.
238 */
239 - (void)threadedTask:(ThreadedTask *)theTask failedWithErrorCode:(int)errorCode;
240
241 /*
242 * Sent to the delegate to report the progress of the task. This is a direct
243 * result of the reportProgress: method being called from the iteration.
244 */
245 - (void)threadedTask:(ThreadedTask *)theTask reportedProgress:(int)theProgress;
246
247 @end
248
This page took 0.038276 seconds and 4 git commands to generate.