File: dispatch.m

package info (click to toggle)
gnustep-base 1.31.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 26,580 kB
  • sloc: objc: 239,446; ansic: 36,519; cpp: 122; sh: 112; makefile: 100; xml: 32
file content (123 lines) | stat: -rw-r--r-- 2,931 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#import "ObjectTesting.h"

#import "Foundation/NSAutoreleasePool.h"
#import "Foundation/NSThread.h"
#import "Foundation/NSTimer.h"
#import "Foundation/NSRunLoop.h"
#import "GNUstepBase/GSConfig.h"

const NSTimeInterval kDelay = 0.01;

#if GS_USE_LIBDISPATCH_RUNLOOP && __has_feature(blocks)
#  define DISPATCH_RL_INTEGRATION 1
#  if __has_include(<dispatch.h>)
#    include <dispatch.h>
#  else
#    include <dispatch/dispatch.h>
#  endif
#endif

/**
 * This is a simple counter object that gets incremented from a different
 * thread, but by using dispatch_async() to put the actual increment operation
 * onto the main queue.
 */
@interface Counter : NSObject
{
  NSUInteger counter;
}
- (void)increment;
- (NSUInteger)counter;
@end

/**
 * This is the object running in the other thread. It's purpose is to dispatch
 * five increments to the main queue and then exit.
 */
@interface Queuer : NSObject
- (void)worker: (Counter*)counter;
- (void)run;
- (void)timeout: (NSTimer*)t;
@end

@implementation Counter
- (void)increment
{
  counter++;
}

- (NSUInteger)counter
{
  return counter;
}
@end

@implementation Queuer

- (void)worker: (Counter*)counter
{
  NSUInteger i = 0;
  NSAutoreleasePool     *pool = [NSAutoreleasePool new];
  for (i  = 0; i < 5; i++)
  {
#   ifdef DISPATCH_RL_INTEGRATION
      dispatch_async(dispatch_get_main_queue(), ^ {
        [counter increment];
      });
#   endif
    NSDate *d  = [NSDate dateWithTimeIntervalSinceNow: kDelay];
    while ([d timeIntervalSinceNow] > 0)
      {
        [[NSRunLoop currentRunLoop] runUntilDate: d];
      }
  }
  [pool release];
}


- (void)timeout: (NSTimer*)t
{
  PASS(NO, "Timeout while trying to run blocks on main thread");
}

- (void) run
{
  NSDate *until = [NSDate dateWithTimeIntervalSinceNow: 1.0];
  Counter *c = AUTORELEASE([Counter new]);
  [NSTimer scheduledTimerWithTimeInterval: 1.0
                                   target: self
                                 selector: @selector(timeout:)
                                 userInfo: nil
                                  repeats: YES];

  [NSThread detachNewThreadSelector: @selector(worker:)
                           toTarget: self
                         withObject: c];

  while ([until timeIntervalSinceNow] > 0)
    {
      NSDate  *tick = [NSDate dateWithTimeIntervalSinceNow: kDelay * 2];
      [[NSRunLoop currentRunLoop] runUntilDate: tick];
      if ([c counter] == 5)
        {
          break;
        }
    }
  PASS([c counter] == 5, "Dispatch blocks execute on main queue");
}

@end

int main(int argc, char *argv[])
{
  NSAutoreleasePool *pool = [NSAutoreleasePool new];
  START_SET("NSRunLoop libdispatch integration")
# ifndef DISPATCH_RL_INTEGRATION
  SKIP("No libdispatch, no blocks support or no runloop integration hooks in libdispatch")
# else
  [[[Queuer new] autorelease] run];
# endif
  END_SET("NSRunLoop libdispatch integration")
  [pool release];
  return 0;
}