ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/NNThread.m
Revision: 1.3
Committed: 2002-12-18T11:54:17Z (21 years, 7 months ago) by nigel
Branch: MAIN
CVS Tags: nigel-build-12, nigel-build-13, nigel-build-16, nigel-build-15
Changes since 1.2: +2 -2 lines
Log Message:
[[blah alloc] init] -> [blah new]

File Contents

# Content
1 //
2 // NNThread.m -Not Nextstep Thread?
3 // Nigel's Nice Thread?
4 //
5 // Revision 1.3, Tuesday Oct 8 2002
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 - (void) changeIntervalTo: (int)number
185 units: (NNTimeUnits)units
186 {
187 switch ( units )
188 {
189 case NNnanoSeconds:
190 delay.tv_nsec = number;
191 delay.tv_sec = 0;
192 break;
193 case NNmicroSeconds:
194 delay.tv_nsec = number * 1000;
195 delay.tv_sec = 0;
196 break;
197 case NNmilliSeconds:
198 delay.tv_nsec = number * 1000000;
199 delay.tv_sec = 0;
200 break;
201 case NNseconds:
202 delay.tv_nsec = 0;
203 delay.tv_sec = number;
204 break;
205 default:
206 NSLog (@"%s illegal units(%d)", __PRETTY_FUNCTION__, units);
207 }
208 }
209
210 - (void) invalidate
211 {
212 repeating = NO;
213 }
214
215 - (void) timerLoop
216 {
217 // For some strange reason, Mac OS X does not have this prototype
218 extern int nanosleep (const struct timespec *rqtp, struct timespec *rmtp);
219
220 while ( repeating )
221 {
222 nanosleep(&delay, NULL);
223 completed = NO;
224 // This caused a few warnings:
225 // [timerObject timerSel];
226 // so I do it a non-obvious way:
227 objc_msgSend (timerObject, timerSel);
228 completed = YES;
229 }
230 }
231
232 - (void) perform: (SEL)action of: (id)receiver
233 after: (int)number units: (NNTimeUnits)units
234 {
235 object = self, sel = @selector(timerLoop),
236 timerObject = receiver, timerSel = action, repeating = NO;
237 [self changeIntervalTo: number units: units];
238 }
239
240 - (void) repeat: (SEL)action of: (id)receiver
241 every: (int)number units: (NNTimeUnits)units
242 {
243 object = self, sel = @selector(timerLoop),
244 timerObject = receiver, timerSel = action, repeating = YES;
245 [self changeIntervalTo: number units: units];
246 }
247
248 @end