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

# User Rev Content
1 nigel 1.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