ObjFW  Diff

Differences From Artifact [152777f944]:

To Artifact [9d07df10aa]:


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
124
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
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
124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156







-
+

-
+











-
+




-
+


-
+


-
+



-
+




-
+



-
-
+
+




-
+

-
+







-
+

-
+









-
-
+
+

-
+



-
-
+
+


-
+

-
-
+
+




-
+



-
-
+
+












-
+








-
+







-
+







#import "OFArray.h"

#import "OFInitializationFailedException.h"
#import "OFNotImplementedException.h"

#ifdef OF_THREADS
# import "threading.h"
static of_tlskey_t first_key, last_key;
static of_tlskey_t firstKey, lastKey;
#else
static OFAutoreleasePool *first = nil, *last = nil;
static OFAutoreleasePool *firstPool = nil, *lastPool = nil;
#endif

#define GROW_SIZE 16

@implementation OFAutoreleasePool
#ifdef OF_THREADS
+ (void)initialize
{
	if (self != [OFAutoreleasePool class])
		return;

	if (!of_tlskey_new(&first_key) || !of_tlskey_new(&last_key))
	if (!of_tlskey_new(&firstKey) || !of_tlskey_new(&lastKey))
		@throw [OFInitializationFailedException newWithClass: self];
}
#endif

+ (void)addObject: (id)obj
+ (void)addObject: (id)object
{
#ifdef OF_THREADS
	id last = of_tlskey_get(last_key);
	id lastPool = of_tlskey_get(lastKey);
#endif

	if (last == nil) {
	if (lastPool == nil) {
		@try {
			[[self alloc] init];
		} @catch (id e) {
			[obj release];
			[object release];
			@throw e;
		}

#ifdef OF_THREADS
		last = of_tlskey_get(last_key);
		lastPool = of_tlskey_get(lastKey);
#endif
	}

	if (last == nil) {
		[obj release];
	if (lastPool == nil) {
		[object release];
		@throw [OFInitializationFailedException newWithClass: self];
	}

	@try {
		[last addObject: obj];
		[lastPool addObject: object];
	} @catch (id e) {
		[obj release];
		[object release];
		@throw e;
	}
}

+ (void)releaseAll
{
#ifdef OF_THREADS
	[of_tlskey_get(first_key) release];
	[of_tlskey_get(firstKey) release];
#else
	[first release];
	[firstPool release];
#endif
}

- init
{
	self = [super init];

	@try {
#ifdef OF_THREADS
		id first = of_tlskey_get(first_key);
		prev = of_tlskey_get(last_key);
		id firstPool = of_tlskey_get(firstKey);
		previousPool = of_tlskey_get(lastKey);

		if (!of_tlskey_set(last_key, self))
		if (!of_tlskey_set(lastKey, self))
			@throw [OFInitializationFailedException
			    newWithClass: isa];
#else
		prev = last;
		last = self;
		previousPool = lastPool;
		lastPool = self;
#endif

		if (first == nil) {
		if (firstPool == nil) {
#ifdef OF_THREADS
			if (!of_tlskey_set(first_key, self)) {
				of_tlskey_set(last_key, prev);
			if (!of_tlskey_set(firstKey, self)) {
				of_tlskey_set(lastKey, previousPool);
				@throw [OFInitializationFailedException
				    newWithClass: isa];
			}
#else
			first = self;
			firstPool = self;
#endif
		}

		if (prev != nil)
			prev->next = self;
		if (previousPool != nil)
			previousPool->nextPool = self;

		size = GROW_SIZE;
		objects = [self allocMemoryForNItems: GROW_SIZE
					    withSize: sizeof(id)];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)addObject: (id)obj
- (void)addObject: (id)object
{
	if (count + 1 > size) {
		objects = [self resizeMemory: objects
				    toNItems: size + GROW_SIZE
				    withSize: sizeof(id)];
		size += GROW_SIZE;
	}

	objects[count] = obj;
	objects[count] = object;
	count++;
}

- (void)releaseObjects
{
	size_t i;

	[next releaseObjects];
	[nextPool releaseObjects];

	for (i = 0; i < count; i++)
		[objects[i] release];

	count = 0;
}

164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180
181
182
183
184
185

186
187
188

189
190
191
192


193
194
195
196
197
198
199
200


201
202
203
204


205
206
207
208
209
210
211
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184

185
186
187

188
189
190


191
192
193
194
195
196
197
198


199
200
201
202


203
204
205
206
207
208
209
210
211







-
+













-
+


-
+


-
-
+
+






-
-
+
+


-
-
+
+







	[self dealloc];
}

- (void)dealloc
{
	size_t i;

	[next dealloc];
	[nextPool dealloc];

	for (i = 0; i < count; i++)
		[objects[i] release];

	/*
	 * If of_tlskey_set fails, this is a real problem. The best we can do
	 * is to not change the pool below the current pool and stop
	 * deallocation. This way, new objects will be added to the current
	 * pool, but released when the pool below gets released - and maybe
	 * the pool itself will be released as well then, because maybe
	 * of_tlskey_set will work this time.
	 */
#ifdef OF_THREADS
	if (!of_tlskey_set(last_key, prev))
	if (!of_tlskey_set(lastKey, previousPool))
		return;
#else
	last = prev;
	lastPool = previousPool;
#endif

	if (prev != nil)
		prev->next = nil;
	if (previousPool != nil)
		previousPool->nextPool = nil;

	/*
	 * If of_tlskey_set fails here, this is even worse, as this will
	 * definitely be a memory leak. But this should never happen anyway.
	 */
#ifdef OF_THREADS
	if (of_tlskey_get(first_key) == self)
		if (!of_tlskey_set(first_key, nil))
	if (of_tlskey_get(firstKey) == self)
		if (!of_tlskey_set(firstKey, nil))
			return;
#else
	if (first == self)
		first = nil;
	if (firstPool == self)
		firstPool = nil;
#endif

	[super dealloc];
}

- retain
{