1/*
2TEST_BUILD
3    $C{COMPILE} $DIR/concurrentcat.m -o concurrentcat.out -framework Foundation
4
5    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc1 -o cc1.dylib
6    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc2 -o cc2.dylib
7    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc3 -o cc3.dylib
8    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc4 -o cc4.dylib
9    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc5 -o cc5.dylib
10    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc6 -o cc6.dylib
11    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc7 -o cc7.dylib
12    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc8 -o cc8.dylib
13    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc9 -o cc9.dylib
14    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc10 -o cc10.dylib
15    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc11 -o cc11.dylib
16    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc12 -o cc12.dylib
17    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc13 -o cc13.dylib
18    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc14 -o cc14.dylib
19    $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/concurrentcat_category.m -DTN=cc15 -o cc15.dylib
20END
21*/
22
23#include "test.h"
24#include <objc/runtime.h>
25#include <objc/objc-auto.h>
26#include <dlfcn.h>
27#include <unistd.h>
28#include <pthread.h>
29#include <Foundation/Foundation.h>
30
31@interface TargetClass : NSObject
32@end
33
34@interface TargetClass(LoadedMethods)
35- (void) m0;
36- (void) m1;
37- (void) m2;
38- (void) m3;
39- (void) m4;
40- (void) m5;
41- (void) m6;
42- (void) m7;
43- (void) m8;
44- (void) m9;
45- (void) m10;
46- (void) m11;
47- (void) m12;
48- (void) m13;
49- (void) m14;
50- (void) m15;
51@end
52
53@implementation TargetClass
54- (void) m0 { fail("shoulda been loaded!"); }
55- (void) m1 { fail("shoulda been loaded!"); }
56- (void) m2 { fail("shoulda been loaded!"); }
57- (void) m3 { fail("shoulda been loaded!"); }
58- (void) m4 { fail("shoulda been loaded!"); }
59- (void) m5 { fail("shoulda been loaded!"); }
60- (void) m6 { fail("shoulda been loaded!"); }
61@end
62
63void *threadFun(void *aTargetClassName) {
64    const char *className = (const char *)aTargetClassName;
65
66    objc_registerThreadWithCollector();
67
68    PUSH_POOL {
69
70        Class targetSubclass = objc_getClass(className);
71        testassert(targetSubclass);
72
73        id target = [targetSubclass new];
74        testassert(target);
75
76        while(1) {
77            [target m0];
78            RETAIN(target);
79            [target addObserver: target forKeyPath: @"m3" options: 0 context: NULL];
80            [target addObserver: target forKeyPath: @"m4" options: 0 context: NULL];
81            [target m1];
82            RELEASE_VALUE(target);
83            [target m2];
84            AUTORELEASE(target);
85            [target m3];
86            RETAIN(target);
87            [target removeObserver: target forKeyPath: @"m4"];
88            [target addObserver: target forKeyPath: @"m5" options: 0 context: NULL];
89            [target m4];
90            RETAIN(target);
91            [target m5];
92            AUTORELEASE(target);
93            [target m6];
94            [target m7];
95            [target m8];
96            [target m9];
97            [target m10];
98            [target m11];
99            [target m12];
100            [target m13];
101            [target m14];
102            [target m15];
103            [target removeObserver: target forKeyPath: @"m3"];
104            [target removeObserver: target forKeyPath: @"m5"];
105        }
106    } POP_POOL;
107    return NULL;
108}
109
110int main()
111{
112    int i;
113
114    void *dylib;
115
116    for(i=1; i<16; i++) {
117	pthread_t t;
118	char dlName[100];
119	sprintf(dlName, "cc%d.dylib", i);
120	dylib = dlopen(dlName, RTLD_LAZY);
121	char className[100];
122	sprintf(className, "cc%d", i);
123	pthread_create(&t, NULL, threadFun, strdup(className));
124	testassert(dylib);
125    }
126    sleep(1);
127
128    succeed(__FILE__);
129}
130