~ubuntu-branches/ubuntu/edgy/sope/edgy

« back to all changes in this revision

Viewing changes to sope-appserver/NGObjWeb/WORunLoop.m

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Ley
  • Date: 2005-08-19 16:53:31 UTC
  • Revision ID: james.westby@ubuntu.com-20050819165331-hs683wz1osm708pw
Tags: upstream-4.4rc.2
ImportĀ upstreamĀ versionĀ 4.4rc.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2000-2005 SKYRIX Software AG
 
3
 
 
4
  This file is part of SOPE.
 
5
 
 
6
  SOPE is free software; you can redistribute it and/or modify it under
 
7
  the terms of the GNU Lesser General Public License as published by the
 
8
  Free Software Foundation; either version 2, or (at your option) any
 
9
  later version.
 
10
 
 
11
  SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
 
12
  WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
13
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
14
  License for more details.
 
15
 
 
16
  You should have received a copy of the GNU Lesser General Public
 
17
  License along with SOPE; see the file COPYING.  If not, write to the
 
18
  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
19
  02111-1307, USA.
 
20
*/
 
21
 
 
22
#include "WORunLoop.h"
 
23
#include "common.h"
 
24
 
 
25
#if 0
 
26
#if !LIB_FOUNDATION_LIBRARY && !APPLE_Foundation_LIBRARY && !NeXT_Foundation_LIBRARY
 
27
 
 
28
#ifndef CREATE_AUTORELEASE_POOL
 
29
#  define CREATE_AUTORELEASE_POOL(pool) \
 
30
            id pool = [[NSAutoreleasePool alloc] init]
 
31
#endif
 
32
 
 
33
#include <sys/types.h>
 
34
#include <sys/errno.h>
 
35
#include <errno.h>
 
36
 
 
37
#include <sys/time.h>   /* for struct timeval */
 
38
#include <string.h>
 
39
#include <memory.h>
 
40
#include <libc.h>
 
41
#include <unistd.h>
 
42
#include <sys/select.h>
 
43
 
 
44
#include "WORunLoop.h"
 
45
#import <Foundation/Foundation.h>
 
46
 
 
47
#if NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY
 
48
#  include <FoundationExt/objc-runtime.h>
 
49
#else
 
50
#  include <extensions/objc-runtime.h>
 
51
#endif
 
52
 
 
53
#if 0
 
54
#warning breaks AppKit, should *extend* NSRunLoop on MacOSX
 
55
@implementation NSRunLoop(Override)
 
56
+ (NSRunLoop *)currentRunLoop {
 
57
  return [WORunLoop currentRunLoop];
 
58
}
 
59
@end
 
60
#endif
 
61
 
 
62
#if 0
 
63
typedef enum {
 
64
    NSPosixNoActivity = 0,
 
65
    NSPosixReadableActivity = 1,
 
66
    NSPosixWritableActivity = 2,
 
67
    NSPosixExceptionalActivity = 4
 
68
} NSPosixFileActivities;
 
69
#endif
 
70
 
 
71
NSString* NSFileObjectBecameActiveNotificationName =
 
72
  @"NSFileObjectBecameActiveNotificationName";
 
73
 
 
74
static char *activityDesc[8] = {
 
75
    "---", // 0
 
76
    "--R", // 1
 
77
    "-W-", // 2
 
78
    "-WR", // 3
 
79
    "E--", // 4
 
80
    "E-R", // 5
 
81
    "EW-", // 6
 
82
    "EWR"  // 7
 
83
};
 
84
 
 
85
@interface WORunLoopFileObjectInfo : NSObject
 
86
{
 
87
    id                    fileObject;
 
88
    NSPosixFileActivities watchedActivities;
 
89
    BOOL                  canCheckAlive;
 
90
}
 
91
 
 
92
- (id)initWithFileObject:(id)_fileObject
 
93
  activities:(NSPosixFileActivities)_activities;
 
94
 
 
95
- (BOOL)isAlive;
 
96
- (int)fileDescriptor;
 
97
- (NSPosixFileActivities)watchedActivities;
 
98
 
 
99
- (void)activity:(NSPosixFileActivities)_activity onDescriptor:(int)_fd;
 
100
 
 
101
@end
 
102
 
 
103
@implementation WORunLoopFileObjectInfo
 
104
 
 
105
- (id)initWithFileObject:(id)_fileObject
 
106
  activities:(NSPosixFileActivities)_activities
 
107
{
 
108
  self->fileObject        = RETAIN(_fileObject);
 
109
  self->watchedActivities = _activities;
 
110
  self->canCheckAlive     = [_fileObject respondsToSelector:@selector(isAlive)];
 
111
  return self;
 
112
}
 
113
- (id)init
 
114
{
 
115
      NSLog(@"ERROR: do not use init with WORunLoopFileObjectInfo ..");
 
116
      AUTORELEASE(self);
 
117
      return nil;
 
118
}
 
119
 
 
120
- (void)dealloc
 
121
{
 
122
    RELEASE(self->fileObject); self->fileObject = nil;
 
123
    [super dealloc];
 
124
}
 
125
 
 
126
- (BOOL)isEqual:(WORunLoopFileObjectInfo*)otherInfo
 
127
{
 
128
    return [self->fileObject isEqual:otherInfo->fileObject];
 
129
}
 
130
 
 
131
- (BOOL)isAlive {
 
132
    return (self->canCheckAlive) ? [self->fileObject isAlive] : YES;
 
133
}
 
134
- (int)fileDescriptor
 
135
{
 
136
    return [self->fileObject fileDescriptor];
 
137
}
 
138
 
 
139
- (NSPosixFileActivities)watchedActivities
 
140
{
 
141
    return self->watchedActivities;
 
142
}
 
143
 
 
144
- (void)activity:(NSPosixFileActivities)_activity onDescriptor:(int)_fd
 
145
{
 
146
    //NSLog(@"FileObject %@ was active ..", self->fileObject);
 
147
    
 
148
    [[NSNotificationCenter defaultCenter]
 
149
                           postNotificationName:
 
150
                             NSFileObjectBecameActiveNotificationName
 
151
                           object:self->fileObject];
 
152
}
 
153
 
 
154
- (NSString *)description
 
155
{
 
156
    return [NSString stringWithFormat:
 
157
                       @"<%@[0x%08X]: object=%@ actitivity=%s>",
 
158
                       NSStringFromClass([self class]), self,
 
159
                       self->fileObject,
 
160
                       activityDesc[self->watchedActivities]
 
161
                     ];
 
162
}
 
163
 
 
164
@end
 
165
 
 
166
@interface WORunLoopTimerInfo : NSObject
 
167
{
 
168
    NSTimer* timer;
 
169
    NSDate* fireDate;
 
170
}
 
171
 
 
172
+ (WORunLoopTimerInfo*)infoWithTimer:(NSTimer*)timer;
 
173
- (void)recomputeFireDate;
 
174
- (NSComparisonResult)compare:(WORunLoopTimerInfo*)anObject;
 
175
- (NSTimer*)timer;
 
176
- (NSDate*)fireDate;
 
177
@end
 
178
 
 
179
@implementation WORunLoopTimerInfo
 
180
 
 
181
+ (WORunLoopTimerInfo*)infoWithTimer:(NSTimer*)aTimer
 
182
{
 
183
    WORunLoopTimerInfo* info = [self new];
 
184
 
 
185
    info->timer    = RETAIN(aTimer);
 
186
    info->fireDate = RETAIN([aTimer fireDate]);
 
187
    return AUTORELEASE(info);
 
188
}
 
189
 
 
190
- (void)dealloc
 
191
{
 
192
    RELEASE(timer);
 
193
    RELEASE(fireDate);
 
194
    [super dealloc];
 
195
}
 
196
 
 
197
- (void)recomputeFireDate
 
198
{
 
199
  if ([timer isValid]) {
 
200
    id tmp = [timer fireDate];
 
201
    ASSIGN(fireDate, tmp);
 
202
  }
 
203
}
 
204
 
 
205
- (NSComparisonResult)compare:(WORunLoopTimerInfo*)anObject
 
206
{
 
207
    return [fireDate compare:anObject->fireDate];
 
208
}
 
209
 
 
210
- (NSTimer*)timer                       { return timer; }
 
211
- (NSDate*)fireDate                     { return fireDate; }
 
212
 
 
213
@end
 
214
 
 
215
@interface WORunLoopActionHolder : NSObject
 
216
{
 
217
    id target;
 
218
    id argument;
 
219
    SEL action;
 
220
    int order;
 
221
}
 
222
+ objectWithTarget:(id)target
 
223
  argument:(id)argument
 
224
  selector:(SEL)action
 
225
  order:(int)order;
 
226
- (BOOL)isEqual:(id)anotherHolder;
 
227
- (void)execute;
 
228
@end
 
229
 
 
230
@implementation WORunLoopActionHolder
 
231
 
 
232
+ objectWithTarget:(id)_target
 
233
  argument:(id)_argument
 
234
  selector:(SEL)_action
 
235
  order:(int)_order
 
236
{
 
237
    WORunLoopActionHolder* holder = AUTORELEASE([self alloc]);
 
238
 
 
239
    holder->target = RETAIN(_target);
 
240
    holder->argument = RETAIN(_argument);
 
241
    holder->action = _action;
 
242
    holder->order = _order;
 
243
 
 
244
    return holder;
 
245
}
 
246
 
 
247
- (unsigned)hash
 
248
{
 
249
  return [(NSObject*)target hash];
 
250
}
 
251
 
 
252
- (BOOL)isEqual:(WORunLoopActionHolder*)anotherHolder
 
253
{
 
254
    return [target isEqual:anotherHolder->target]
 
255
            && [argument isEqual:anotherHolder->argument]
 
256
            && SEL_EQ(action, anotherHolder->action);
 
257
}
 
258
 
 
259
- (void)execute
 
260
{
 
261
    [target performSelector:action withObject:argument];
 
262
}
 
263
 
 
264
- (NSComparisonResult)compare:(WORunLoopActionHolder*)anotherHolder
 
265
{
 
266
    return order - anotherHolder->order;
 
267
}
 
268
 
 
269
@end
 
270
 
 
271
 
 
272
@interface WORunLoopInputManager : NSObject
 
273
{
 
274
    NSMutableArray* fileObjects;
 
275
    NSMutableArray* timers;
 
276
    NSMutableArray* otherOperations;
 
277
}
 
278
 
 
279
- (void)addFileObject:(id)_fileObject
 
280
  activities:(NSPosixFileActivities)_activities;
 
281
- (void)removeFileObject:(id)_fileObject;
 
282
 
 
283
- (void)addTimer:(NSTimer*)aTimer;
 
284
 
 
285
- (NSMutableArray*)fileObjects;
 
286
- (NSMutableArray*)timers;
 
287
 
 
288
- (void)addOperation:(WORunLoopActionHolder*)holder;
 
289
- (void)removeOperation:(WORunLoopActionHolder*)holder;
 
290
- (void)performAdditionalOperations;
 
291
@end
 
292
 
 
293
 
 
294
@implementation WORunLoopInputManager
 
295
 
 
296
- init
 
297
{
 
298
    fileObjects     = [NSMutableArray new];
 
299
    timers          = [NSMutableArray new];
 
300
    otherOperations = [NSMutableArray new];
 
301
    return [super init];
 
302
}
 
303
 
 
304
- (void)dealloc
 
305
{
 
306
    RELEASE(fileObjects);
 
307
    RELEASE(timers);
 
308
    RELEASE(otherOperations);
 
309
    [super dealloc];
 
310
}
 
311
 
 
312
- (void)addFileObject:(id)_fileObject
 
313
  activities:(NSPosixFileActivities)_activities
 
314
{
 
315
    WORunLoopFileObjectInfo *info = nil;
 
316
    //NSAssert(_activities, @"no activity to watch ?!");
 
317
    info = [[WORunLoopFileObjectInfo allocWithZone:[self zone]]
 
318
                                     initWithFileObject:_fileObject
 
319
                                     activities:_activities];
 
320
    [self->fileObjects addObject:info];
 
321
    //NSLog(@"file objects now: %@", self->fileObjects);
 
322
    RELEASE(info); info = nil;
 
323
}
 
324
- (void)removeFileObject:(id)_fileObject
 
325
{
 
326
    WORunLoopFileObjectInfo *info = nil;
 
327
    info = [[WORunLoopFileObjectInfo allocWithZone:[self zone]]
 
328
                                     initWithFileObject:_fileObject
 
329
                                     activities:0];
 
330
    [self->fileObjects removeObject:info];
 
331
    //NSLog(@"file objects now: %@", self->fileObjects);
 
332
    RELEASE(info); info = nil;
 
333
}
 
334
 
 
335
- (void)addTimer:(NSTimer*)aTimer
 
336
{
 
337
    [timers addObject:[WORunLoopTimerInfo infoWithTimer:aTimer]];
 
338
}
 
339
 
 
340
- (void)addOperation:(WORunLoopActionHolder*)holder
 
341
{
 
342
    [otherOperations addObject:holder];
 
343
    [otherOperations sortUsingSelector:@selector(compare:)];
 
344
}
 
345
 
 
346
- (void)removeOperation:(WORunLoopActionHolder*)holder
 
347
{
 
348
    [otherOperations removeObject:holder];
 
349
}
 
350
 
 
351
- (void)performAdditionalOperations
 
352
{
 
353
    [otherOperations makeObjectsPerformSelector:@selector(execute)];
 
354
}
 
355
 
 
356
- (NSMutableArray*)fileObjects { return fileObjects; }
 
357
- (NSMutableArray*)timers      { return timers; }
 
358
 
 
359
@end /* WORunLoopInputManager */
 
360
 
 
361
@implementation WORunLoop
 
362
 
 
363
/* Class variable */
 
364
static WORunLoop *currentRunLoop = nil;
 
365
static BOOL      taskIsMultithreaded = NO;
 
366
 
 
367
+ (void)error:(id)_o {
 
368
  NSLog(@"ERROR:");
 
369
  NSLog(@"  %@", _o);
 
370
}
 
371
 
 
372
+ (NSRunLoop *)currentRunLoop
 
373
{
 
374
    if (taskIsMultithreaded) {
 
375
        NSLog(@"WORunLoop does not work multithreaded, exit ..");
 
376
        return nil;
 
377
    }
 
378
    else {
 
379
        if (!currentRunLoop)
 
380
            currentRunLoop = [[self alloc] init];
 
381
        return currentRunLoop;
 
382
    }
 
383
}
 
384
 
 
385
- (id)init {
 
386
  self->inputsForMode = [[NSMutableDictionary allocWithZone:[self zone]] init];
 
387
  self->mode = RETAIN(NSDefaultRunLoopMode);
 
388
  return self;
 
389
}
 
390
 
 
391
- (void)dealloc {
 
392
  RELEASE(self->inputsForMode);
 
393
  RELEASE(self->mode);
 
394
  [super dealloc];
 
395
}
 
396
 
 
397
- (NSString *)currentMode {
 
398
    return self->mode;
 
399
}
 
400
 
 
401
static inline WORunLoopInputManager*
 
402
_getInputManager(WORunLoop *self, NSString *_mode)
 
403
{
 
404
  WORunLoopInputManager* inputManager;
 
405
 
 
406
  inputManager = [self->inputsForMode objectForKey:_mode];
 
407
  if (inputManager == nil) {
 
408
    inputManager = [WORunLoopInputManager new];
 
409
    [self->inputsForMode setObject:inputManager forKey:_mode];
 
410
    RELEASE(inputManager);
 
411
  }
 
412
  return inputManager;
 
413
}
 
414
 
 
415
static int compare_fire_dates(id timer1, id timer2, void* userData)
 
416
{
 
417
  return [[timer1 fireDate] compare:[timer2 fireDate]];
 
418
}
 
419
 
 
420
- (NSDate*)limitDateForMode:(NSString*)aMode
 
421
{
 
422
    NSString       *format = @"%s: Caught exception %@ with reason %@ ";
 
423
    NSMutableArray *timers = [[inputsForMode objectForKey:aMode] timers];
 
424
    volatile int   i, count;
 
425
    NSMutableArray *copyOfTimers;
 
426
 
 
427
    ASSIGN(mode, aMode);
 
428
 
 
429
    /* Remove invalid timers */
 
430
    for(count = [timers count], i = count - 1; i >= 0; i--)
 
431
        if(![[[timers objectAtIndex:i] timer] isValid]) {
 
432
            [timers removeObjectAtIndex:i];
 
433
            count--;
 
434
        }
 
435
 
 
436
    /* Currently only timers have limit dates associated with them */
 
437
    if(!count)
 
438
        return nil;
 
439
 
 
440
    copyOfTimers = [timers mutableCopy];
 
441
 
 
442
    /* Sort the timers based on their fire date */
 
443
    [copyOfTimers sortUsingFunction:compare_fire_dates context:NULL];
 
444
 
 
445
    /* Fire all the timers with their fire date expired */
 
446
    for(i = 0; i < count; i++) {
 
447
        WORunLoopTimerInfo* timerInfo = [copyOfTimers objectAtIndex:i];
 
448
        NSDate* fireDate = [timerInfo fireDate];
 
449
        NSDate* currentDate = [NSDate date];
 
450
 
 
451
        if([fireDate earlierDate:currentDate] == fireDate
 
452
           || [fireDate isEqualToDate:currentDate]) {
 
453
            NSTimer* timer = [timerInfo timer];
 
454
            NS_DURING
 
455
              [timer fire];
 
456
            NS_HANDLER
 
457
              NSLog(format, __PRETTY_FUNCTION__,
 
458
                    [localException name], [localException reason]);
 
459
            NS_ENDHANDLER;
 
460
 
 
461
#if 0
 
462
#warning no repeated timers !
 
463
            if(![timer repeats])
 
464
#endif
 
465
                [timer invalidate];
 
466
        }
 
467
    }
 
468
 
 
469
    RELEASE(copyOfTimers);
 
470
 
 
471
    /* Recompute the fire dates for this cycle */
 
472
    [timers makeObjectsPerformSelector:@selector(recomputeFireDate)];
 
473
 
 
474
    /* Sort the timers based on their fire date */
 
475
    [timers sortUsingFunction:compare_fire_dates context:NULL];
 
476
 
 
477
    return [timers count] ? [[timers objectAtIndex:0] fireDate] : nil;
 
478
}
 
479
 
 
480
- (void)addTimer:(NSTimer*)aTimer
 
481
        forMode:(NSString*)aMode
 
482
{
 
483
    [_getInputManager(self, aMode) addTimer:aTimer];
 
484
}
 
485
 
 
486
- (BOOL)runMode:(NSString*)aMode
 
487
        beforeDate:(NSDate*)limitDate
 
488
{
 
489
    id inputManager, fileObjects;
 
490
    NSArray* timers;
 
491
    NSDate* date;
 
492
 
 
493
    /* Retain the limitDate so it doesn't get released by limitDateForMode:
 
494
        if it fires a timer that has as fireDate the limitDate.
 
495
        (bug report from Benhur Stein <Benhur-de-Oliveira.Stein@imag.fr>)
 
496
      */
 
497
    (void)RETAIN(limitDate);
 
498
 
 
499
    inputManager = [inputsForMode objectForKey:aMode];
 
500
    timers       = [inputManager timers];
 
501
    fileObjects  = [inputManager fileObjects];
 
502
 
 
503
    if (([timers count] != 0) || ([fileObjects count] != 0)) {
 
504
        CREATE_AUTORELEASE_POOL(pool);
 
505
 
 
506
        date = [self limitDateForMode:aMode];
 
507
        date = date ? [date earlierDate:limitDate] : limitDate;
 
508
        [self acceptInputForMode:aMode beforeDate:date];
 
509
        RELEASE(pool);
 
510
        RELEASE(limitDate);
 
511
        return YES;
 
512
    }
 
513
 
 
514
    RELEASE(limitDate);
 
515
    return NO;
 
516
}
 
517
 
 
518
/*  Runs the loop until limitDate or until the earliest limit date for input
 
519
    sources in the specified mode. */
 
520
- (void)acceptInputForMode:(NSString*)aMode
 
521
        beforeDate:(NSDate*)limitDate
 
522
{
 
523
    id              inputManager, fileObjects;
 
524
    struct timeval  tp = { 0, 0 };
 
525
    struct timeval* timeout = NULL;
 
526
    NSTimeInterval  delay = 0;
 
527
    fd_set          readSet, writeSet, exceptionsSet;
 
528
    volatile int    i, r, count;
 
529
 
 
530
    ASSIGN(mode, aMode);
 
531
 
 
532
    if(limitDate == nil) // delay = 0
 
533
        limitDate = [NSDate distantFuture];
 
534
    else {
 
535
        delay = [limitDate timeIntervalSinceNow];
 
536
            /* delay > 0 means a future date */
 
537
 
 
538
        /* If limitDate is in the past return */
 
539
        if(delay < 0)
 
540
            return;
 
541
    }
 
542
 
 
543
    inputManager = [inputsForMode objectForKey:aMode];
 
544
    fileObjects  = [inputManager fileObjects];
 
545
 
 
546
    /* Compute the timeout for select */
 
547
    if([limitDate isEqual:[NSDate distantFuture]])
 
548
        timeout = NULL;
 
549
    else {
 
550
        tp.tv_sec = delay;
 
551
        tp.tv_usec = (delay - (NSTimeInterval)tp.tv_sec) * 1000000.0;
 
552
        timeout = &tp;
 
553
    }
 
554
 
 
555
    ASSIGN(mode, aMode);
 
556
 
 
557
    FD_ZERO(&readSet);
 
558
    FD_ZERO(&writeSet);
 
559
    FD_ZERO(&exceptionsSet);
 
560
 
 
561
    do {
 
562
        count = [fileObjects count];
 
563
        for (i = 0; i < count; i++) {
 
564
            WORunLoopFileObjectInfo *info;
 
565
            NSPosixFileActivities   fileActivity;
 
566
            int                     fd;
 
567
 
 
568
            info = [fileObjects objectAtIndex:i];
 
569
            if (![info isAlive])
 
570
                continue;
 
571
 
 
572
            fileActivity = [info watchedActivities];
 
573
            fd           = [info fileDescriptor];
 
574
            
 
575
            if (fd >= 0) {
 
576
#if !defined(__MINGW32__) /* on Windows descriptors can be BIG */
 
577
                if (fd >= FD_SETSIZE) {
 
578
                    NSLog(@"%s: fd %i of %@ exceeds select size %i",
 
579
                          __PRETTY_FUNCTION__,
 
580
                          fd, info, FD_SETSIZE);
 
581
                    continue;
 
582
                }
 
583
#endif /* !defined(__MINGW32__) */
 
584
 
 
585
                //NSLog(@"registering activity %s for fd %i ..",
 
586
                //      activityDesc[fileActivity], fd);
 
587
 
 
588
                if (fileActivity & NSPosixReadableActivity)
 
589
                    FD_SET(fd, &readSet);
 
590
                if (fileActivity & NSPosixWritableActivity)
 
591
                    FD_SET(fd, &writeSet);
 
592
                if (fileActivity & NSPosixExceptionalActivity)
 
593
                    FD_SET(fd, &exceptionsSet);
 
594
            }
 
595
        }
 
596
 
 
597
        // ???: errno = 0; What is this good for ?
 
598
        r = select(FD_SETSIZE, &readSet, &writeSet, &exceptionsSet, timeout);
 
599
        if (r == -1) {
 
600
            if (errno == EINTR) {
 
601
                /* Interrupt occured; break the loop to give a chance to
 
602
                   UnixSignalHandler to handle the signals. */
 
603
                errno = 0;
 
604
                break;
 
605
            }
 
606
            else {
 
607
                NSLog(@"%s: select() error: '%s'",
 
608
                      __PRETTY_FUNCTION__, strerror (errno));
 
609
                break;
 
610
            }
 
611
            errno = 0;
 
612
        }
 
613
    } while (r == -1);
 
614
 
 
615
    if(r > 0) {
 
616
        id fileObjectsCopy;
 
617
        NSString* format = @"%s: Caught exception %@ with reason %@ ";
 
618
 
 
619
        *(&fileObjectsCopy) = nil;
 
620
 
 
621
        NS_DURING {
 
622
            // made copy, so that modifications in the delegate don't
 
623
            // alter the loop
 
624
            fileObjectsCopy = [fileObjects copyWithZone:[self zone]];
 
625
            count           = [fileObjectsCopy count];
 
626
            
 
627
            for (i = 0; (i < count) && (r > 0); i++) {
 
628
                WORunLoopFileObjectInfo *info;
 
629
                NSPosixFileActivities   activity = 0;
 
630
                int fd;
 
631
 
 
632
                info = [fileObjectsCopy objectAtIndex:i];
 
633
                fd   = [info fileDescriptor];
 
634
 
 
635
                if (fd >= 0) {
 
636
                    //NSLog(@"checking activity for %i info %@ ..", fd, info);
 
637
                
 
638
                    if (FD_ISSET(fd, &readSet)) {
 
639
                        activity |= NSPosixReadableActivity;
 
640
                        r--;
 
641
                    }
 
642
                    if (FD_ISSET(fd, &writeSet)) {
 
643
                        activity |= NSPosixWritableActivity;
 
644
                        r--;
 
645
                    }
 
646
                    if (FD_ISSET(fd, &exceptionsSet)) {
 
647
                        activity |= NSPosixExceptionalActivity;
 
648
                        r--;
 
649
                    }
 
650
 
 
651
                    if (activity != 0)
 
652
                        [info activity:activity onDescriptor:fd];
 
653
                }
 
654
            }
 
655
            if (r > 0) {
 
656
                NSLog(@"WARNING: could not resolve all activities (%i) ..",
 
657
                      r);
 
658
            }
 
659
        }
 
660
        NS_HANDLER {
 
661
          NSLog(format, __PRETTY_FUNCTION__,
 
662
                [localException name], [localException reason]);
 
663
        }
 
664
        NS_ENDHANDLER;
 
665
 
 
666
        RELEASE(fileObjectsCopy); fileObjectsCopy = nil;
 
667
    }
 
668
 
 
669
    [inputManager performAdditionalOperations];
 
670
#if !NeXT_Foundation_LIBRARY
 
671
    [NSNotificationQueue runLoopASAP];
 
672
#endif
 
673
}
 
674
 
 
675
- (void)runUntilDate:(NSDate*)limitDate
 
676
{
 
677
    BOOL shouldContinue = YES;
 
678
 
 
679
    if(!limitDate)
 
680
        limitDate = [NSDate distantFuture];
 
681
    else {
 
682
        /* If limitDate is in the past return */
 
683
        if([limitDate timeIntervalSinceNow] < 0)
 
684
            return;
 
685
    }
 
686
 
 
687
    while (shouldContinue) {
 
688
        CREATE_AUTORELEASE_POOL(pool);
 
689
 
 
690
        if ([limitDate laterDate:[NSDate date]] == limitDate) {
 
691
            if([self runMode:NSDefaultRunLoopMode beforeDate:limitDate] == NO)
 
692
                shouldContinue = NO;
 
693
        }
 
694
        else
 
695
            shouldContinue = NO;
 
696
        RELEASE(pool);
 
697
    }
 
698
}
 
699
 
 
700
- (void)run
 
701
{
 
702
    [self runUntilDate:[NSDate distantFuture]];
 
703
}
 
704
 
 
705
- (void)performSelector:(SEL)aSelector
 
706
  target:(id)target
 
707
  argument:(id)anArgument
 
708
  order:(unsigned)order
 
709
  modes:(NSArray*)modes
 
710
{
 
711
    id holder = [WORunLoopActionHolder objectWithTarget:target
 
712
                                        argument:anArgument
 
713
                                        selector:aSelector
 
714
                                        order:order];
 
715
    int i, count = [modes count];
 
716
 
 
717
    for (i = 0; i < count; i++)
 
718
        [[inputsForMode objectForKey:[modes objectAtIndex:i]]
 
719
            addOperation:holder];
 
720
}
 
721
 
 
722
- (void)cancelPerformSelector:(SEL)aSelector
 
723
  target:(id)target
 
724
  argument:(id)anArgument
 
725
{
 
726
    id holder = [WORunLoopActionHolder objectWithTarget:target
 
727
                                        argument:anArgument
 
728
                                        selector:aSelector
 
729
                                        order:0];
 
730
    id enumerator = [inputsForMode keyEnumerator];
 
731
    id aMode;
 
732
 
 
733
    while ((aMode = [enumerator nextObject]))
 
734
        [[inputsForMode objectForKey:aMode] removeOperation:holder];
 
735
}
 
736
 
 
737
/* Monitoring file objects */
 
738
 
 
739
- (void)addFileObject:(id)_fileObject
 
740
  activities:(NSPosixFileActivities)_activities
 
741
  forMode:(NSString *)_mode
 
742
{
 
743
    [_getInputManager(self, _mode) addFileObject:_fileObject
 
744
                                   activities:_activities];
 
745
}
 
746
 
 
747
- (void)removeFileObject:(id)_fileObject
 
748
  forMode:(NSString *)_mode
 
749
{
 
750
    [_getInputManager(self, _mode) removeFileObject:_fileObject];
 
751
}
 
752
 
 
753
@end /* WORunLoop */
 
754
 
 
755
#endif /* !LIB_FOUNDATION_LIBRARY */
 
756
#endif // 0