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, 8 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

# User Rev Content
1 nigel 1.1 //
2     // NNThread.m -Not Nextstep Thread?
3     // Nigel's Nice Thread?
4     //
5 nigel 1.2 // Revision 1.3, Tuesday Oct 8 2002
6 nigel 1.1 //
7     // Created by Nigel Pearson on Tue Nov 28 2000.
8     // Public Domain. No rights reserved.
9     //
10    
11     #import "NNThread.h"
12 nigel 1.2 #import <objc/objc-runtime.h> // For objc_msgSend() prototype
13 nigel 1.1
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 nigel 1.3 pool = [NSAutoreleasePool new];
28 nigel 1.1
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 nigel 1.3 args -> pool = [NSAutoreleasePool new];
47 nigel 1.1
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