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, 6 months 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

# User Rev Content
1 nigel 1.1 //
2     // NNThread.m -Not Nextstep Thread?
3     // Nigel's Nice Thread?
4     //
5 nigel 1.4 // Revision 1.4, Tuesday May 25 2004
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 nigel 1.4 - (NNTimer *) initWithAutoRelPool
185     {
186     self = [super init];
187     allocPool = YES;
188     repeating = YES;
189     return self;
190     }
191    
192    
193 nigel 1.1 - (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