File: config.initialize.m

package info (click to toggle)
gnustep-base 1.26.0-4
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 27,260 kB
  • sloc: objc: 204,878; ansic: 32,160; sh: 157; makefile: 128; cpp: 122; xml: 32
file content (110 lines) | stat: -rw-r--r-- 1,961 bytes parent folder | download | duplicates (6)
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
/* Test whether Objective-C runtime +initialize support is thread-safe
 */

#include "objc-common.g"
#include <pthread.h>
#include <stdio.h>

#if defined(_WIN32)
# define	mySleep(X)	usleep(1000*(X))
#else
# define	mySleep(X)	sleep(X)
#endif

/* Use volatile variables so compiler optimisation won't prevent one thread
 * from seeing changes made by another.
 */
static volatile unsigned	initialize_entered = 0;
static volatile unsigned	initialize_exited = 0;
static volatile unsigned	class_entered = 0;
static volatile BOOL		may_proceed = NO;

@interface	MyClass : NSObject
@end

@implementation	MyClass

+ (void) initialize
{
  initialize_entered++;
  while (NO == may_proceed)
    ;
  initialize_exited++;
}

+ (Class) class
{
  class_entered++;
  return self;
}

@end

static void *
test(void *arg)
{
  [MyClass class];
  return 0;
}

int
main()
{
  pthread_t t1;
  pthread_t t2;
  unsigned  counter;

  if (0 == pthread_create(&t1, 0, test, 0))
    {
      for (counter = 0; 0 == initialize_entered && counter < 5; counter++)
	{
	  mySleep(1);
	}

      if (0 == initialize_entered)
	{
	  fprintf(stderr, "Failed to initialize\n");
	  return 1;
	}

      if (0 == pthread_create(&t2, 0, test, 0))
        {
          /* Wait long enough for t2 to  try calling +class
	   */
	  mySleep(1);

	  if (class_entered > 0)
	    {
	      fprintf(stderr, "class entered prematurely\n");
	      return 1;
	    }

	  /* Let t1 proceed and wait long enough for it to complete
	   * +initialize and for both threads to call +class
	   */
	  may_proceed = YES;
          for (counter = 0; 2 > class_entered && counter < 5; counter++)
	    {
	      mySleep(1);
	    }

	  if (2 == class_entered)
	    {
	      return 0; // OK
	    }
	  fprintf(stderr, "problem with initialize\n");
          return 1;
	}
      else
	{
	  fprintf(stderr, "failed to create t2\n");
	  return 1;
	}
    }
  else
    {
      fprintf(stderr, "failed to create t1\n");
      return 1;
    }
}