ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/NNThread.m
Revision: 1.1
Committed: 2002-03-16T04:00:26Z (22 years, 7 months ago) by nigel
Branch: MAIN
CVS Tags: nigel-build-10
Log Message:
Initial revision of Mac OS X port code. Uses Objective-C++. Needs Mac OS 10.1

File Contents

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