ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/NNThread.m
Revision: 1.4
Committed: 2004-05-25T07:50:14Z (20 years, 1 month ago) by nigel
Branch: MAIN
CVS Tags: nigel-build-19, nigel-build-17, HEAD
Changes since 1.3: +10 -1 lines
Log Message:
New Autorelease pool stuff for NNTimer

File Contents

# Content
1 //
2 // NNThread.m -Not Nextstep Thread?
3 // Nigel's Nice Thread?
4 //
5 // Revision 1.4, Tuesday May 25 2004
6 //
7 // Created by Nigel Pearson on Tue Nov 28 2000.
8 // Public Domain. No rights reserved.
9 //
10
11 #import "NNThread.h"
12 #import <objc/objc-runtime.h> // For objc_msgSend() prototype
13
14 @implementation NNThread
15
16 // Define the wrapper first so that init knows about it without having to put it in the .h
17
18 #ifdef USE_NSTHREAD
19 - (void) wrapper
20 {
21 machThread = mach_thread_self();
22
23 if ( object == nil || sel == (SEL) nil || suspended )
24 thread_suspend (machThread); // Suspend myself
25
26 if ( allocPool )
27 pool = [NSAutoreleasePool new];
28
29 // [object sel] caused "cannot find method" warnings, so I do it a non-obvious way:
30 objc_msgSend (object, sel);
31
32 completed = YES;
33
34 if ( allocPool )
35 [pool release];
36 }
37 #endif
38
39 #ifdef USE_PTHREAD
40 void *
41 pthreadWrapper (void *arg)
42 {
43 struct pthreadArgs *args = arg;
44
45 if ( args -> allocPool )
46 args -> pool = [NSAutoreleasePool new];
47
48 objc_msgSend (*(args->object), *(args->sel));
49
50 *(args->completed) = YES;
51
52 if ( args -> allocPool )
53 [args -> pool release];
54
55 return NULL;
56 }
57
58 - (BOOL) wrapper
59 {
60 int error;
61
62 pthreadArgs.object = &object;
63 pthreadArgs.sel = &sel;
64 pthreadArgs.allocPool = allocPool;
65 pthreadArgs.completed = &completed;
66 pthreadArgs.pool = nil;
67
68 if ( object == nil || sel == (SEL) nil || suspended )
69 error = pthread_create_suspended_np (&pThread, NULL, &pthreadWrapper, &pthreadArgs);
70 else
71 error = pthread_create (&pThread, NULL, &pthreadWrapper, &pthreadArgs);
72
73 if ( error )
74 NSLog(@"%s - pthread_create failed");
75 else
76 machThread = pthread_mach_thread_np (pThread);
77
78 return ! error;
79 }
80 #endif
81
82 - (NNThread *) initSuspended: (BOOL) startSuspended
83 withAutoreleasePool: (BOOL) allocatePool
84 {
85 self = [super init];
86
87 allocPool = allocatePool;
88 completed = NO;
89 suspended = startSuspended;
90 object = nil;
91 sel = (SEL) nil;
92
93 #ifdef USE_NSTHREAD
94 [NSThread detachNewThreadSelector:@selector(wrapper)
95 toTarget:self
96 withObject:nil];
97 #endif
98
99 #ifdef USE_PTHREAD
100 if ( ! [self wrapper] ) // Wrapper does the thread creation
101 {
102 NSLog(@"%s - pthread wrapper failed", __PRETTY_FUNCTION__);
103 return nil;
104 }
105 #endif
106
107 return self;
108 }
109
110 - (NNThread *) init
111 {
112 return [self initSuspended: YES withAutoreleasePool: NO];
113 }
114
115 - (NNThread *) initWithAutoReleasePool
116 {
117 return [self initSuspended: YES withAutoreleasePool: YES];
118 }
119
120 - (BOOL) completed
121 {
122 return completed;
123 }
124
125 - (void) perform: (SEL)action of: (id)receiver
126 {
127 object = receiver, sel = action;
128 }
129
130 - (void) resume
131 {
132 if ( suspended )
133 [self start];
134 else
135 NSLog (@"%s - thread not suspended", __PRETTY_FUNCTION__);
136 }
137
138 - (BOOL) start
139 {
140 kern_return_t error;
141
142 if ( object == nil || sel == (SEL) nil )
143 {
144 NSLog (@"%s - cannot start thread, object or selector invalid", __PRETTY_FUNCTION__);
145 return NO;
146 }
147 if ( ( error = thread_resume (machThread) ) != KERN_SUCCESS )
148 NSLog (@"%s - thread_resume() failed, returned %d", __PRETTY_FUNCTION__, error);
149 suspended = NO;
150 return YES;
151 }
152
153 - (void) suspend
154 {
155 if ( ! suspended )
156 {
157 kern_return_t error;
158
159 if ( ( error = thread_suspend (machThread) ) != KERN_SUCCESS )
160 NSLog (@"%s - thread_resume() failed, returned %d", __PRETTY_FUNCTION__, error);
161 suspended = YES;
162 }
163 }
164
165 - (void) terminate
166 {
167 kern_return_t error;
168
169 if ( ( error = thread_terminate (machThread) ) != KERN_SUCCESS )
170 NSLog (@"%s - thread_terminate() failed, returned %d", __PRETTY_FUNCTION__, error);
171 }
172
173 @end
174
175 @implementation NNTimer
176
177 - (NNTimer *) init
178 {
179 self = [super init];
180 repeating = YES;
181 return self;
182 }
183
184 - (NNTimer *) initWithAutoRelPool
185 {
186 self = [super init];
187 allocPool = YES;
188 repeating = YES;
189 return self;
190 }
191
192
193 - (void) changeIntervalTo: (int)number
194 units: (NNTimeUnits)units
195 {
196 switch ( units )
197 {
198 case NNnanoSeconds:
199 delay.tv_nsec = number;
200 delay.tv_sec = 0;
201 break;
202 case NNmicroSeconds:
203 delay.tv_nsec = number * 1000;
204 delay.tv_sec = 0;
205 break;
206 case NNmilliSeconds:
207 delay.tv_nsec = number * 1000000;
208 delay.tv_sec = 0;
209 break;
210 case NNseconds:
211 delay.tv_nsec = 0;
212 delay.tv_sec = number;
213 break;
214 default:
215 NSLog (@"%s illegal units(%d)", __PRETTY_FUNCTION__, units);
216 }
217 }
218
219 - (void) invalidate
220 {
221 repeating = NO;
222 }
223
224 - (void) timerLoop
225 {
226 // For some strange reason, Mac OS X does not have this prototype
227 extern int nanosleep (const struct timespec *rqtp, struct timespec *rmtp);
228
229 while ( repeating )
230 {
231 nanosleep(&delay, NULL);
232 completed = NO;
233 // This caused a few warnings:
234 // [timerObject timerSel];
235 // so I do it a non-obvious way:
236 objc_msgSend (timerObject, timerSel);
237 completed = YES;
238 }
239 }
240
241 - (void) perform: (SEL)action of: (id)receiver
242 after: (int)number units: (NNTimeUnits)units
243 {
244 object = self, sel = @selector(timerLoop),
245 timerObject = receiver, timerSel = action, repeating = NO;
246 [self changeIntervalTo: number units: units];
247 }
248
249 - (void) repeat: (SEL)action of: (id)receiver
250 every: (int)number units: (NNTimeUnits)units
251 {
252 object = self, sel = @selector(timerLoop),
253 timerObject = receiver, timerSel = action, repeating = YES;
254 [self changeIntervalTo: number units: units];
255 }
256
257 @end