ObjFW  Check-in [88c920bd62]

Overview
Comment:Make ObjFW work again without threads and without atomic ops.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 88c920bd62a3aa37e204fcc92dfba0362101a2a33f4ec1c45171b49e3a8fd6c8
User & Date: js on 2010-12-28 22:18:34
Other Links: manifest | tags
Context
2010-12-29
12:49
Allow hexadecimal values with h suffix in -[hexadecimalValue]. check-in: eb328c80df user: js tags: trunk
2010-12-28
22:18
Make ObjFW work again without threads and without atomic ops. check-in: 88c920bd62 user: js tags: trunk
21:21
Add -[stringWithFormat:] to OFDate. check-in: f9d3f89aff user: js tags: trunk
Changes

Modified src/OFAutoreleasePool.m from [2e10041b61] to [201a88918f].

15
16
17
18
19
20
21
22
23
24
25
26
27
28


29
30
31
32
33
34
35
15
16
17
18
19
20
21



22
23
24
25
26
27
28
29
30
31
32
33
34







-
-
-




+
+








#import "OFAutoreleasePool.h"
#import "OFArray.h"
#import "OFExceptions.h"

#ifdef OF_THREADS
# import "threading.h"

#define GROW_SIZE 16

static of_tlskey_t first_key, last_key;
#else
static OFAutoreleasePool *first = nil, *last = nil;
#endif

#define GROW_SIZE 16

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

Modified src/OFBlock.m from [49b08c57ae] to [60baf332a9].

10
11
12
13
14
15
16


17
18
19
20
21
22
23

24





25
26
27
28
29
30
31
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







+
+







+
-
+
+
+
+
+







 */

#include "config.h"

#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include <assert.h>

#if defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__)
# import <objc/runtime.h>
#endif

#import "OFBlock.h"
#import "OFExceptions.h"
#ifdef OF_ATOMIC_OPS
#import "atomic.h"
# import "atomic.h"
#endif
#ifdef OF_THREADS
# import "threading.h"
#endif

@protocol RetainRelease
- retain;
- (void)release;
@end

#if defined(OF_OBJFW_RUNTIME) || defined(OF_GNU_RUNTIME) || \
131
132
133
134
135
136
137






138
139
140
141
142
143
144
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157







+
+
+
+
+
+







extern void *_NSConcreteMallocBlock;
#endif

static struct {
	Class isa;
} alloc_failed_exception;

#if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS)
# define NUM_SPINLOCKS 8	/* needs to be a power of 2 */
# define SPINLOCK_HASH(p) ((uintptr_t)p >> 4) & (NUM_SPINLOCKS - 1)
static of_spinlock_t spinlocks[NUM_SPINLOCKS];
#endif

void*
_Block_copy(const void *block_)
{
	of_block_literal_t *block = (of_block_literal_t*)block_;

	if (block->isa == (Class)&_NSConcreteStackBlock) {
		of_block_literal_t *copy;
155
156
157
158
159
160
161
162


163














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
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239







-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+












+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








		if (block->flags & OF_BLOCK_HAS_COPY_DISPOSE)
			block->descriptor->copy_helper(copy, block);

		return copy;
	}

	if (block->isa == (Class)&_NSConcreteMallocBlock)
	if (block->isa == (Class)&_NSConcreteMallocBlock) {
#if defined(OF_ATOMIC_OPS)
		of_atomic_inc_int(&block->flags);
#else
# ifdef OF_THREADS
		unsigned hash = SPINLOCK_HASH(block);

		assert(of_spinlock_lock(&spinlocks[hash]));
# endif

		block->flags++;

# ifdef OF_THREADS
		assert(of_spinlock_unlock(&spinlocks[hash]));
# endif
#endif
	}

	return block;
}

void
_Block_release(const void *block_)
{
	of_block_literal_t *block = (of_block_literal_t*)block_;

	if (block->isa != (Class)&_NSConcreteMallocBlock)
		return;

#ifdef OF_ATOMIC_OPS
	if ((of_atomic_dec_int(&block->flags) & OF_BLOCK_REFCOUNT_MASK) == 0) {
		if (block->flags & OF_BLOCK_HAS_COPY_DISPOSE)
			block->descriptor->dispose_helper(block);

		free(block);
	}
#else
# ifdef OF_THREADS
	unsigned hash = SPINLOCK_HASH(block);

	assert(of_spinlock_lock(&spinlocks[hash]));
# endif

	if ((--block->flags & OF_BLOCK_REFCOUNT_MASK) == 0) {
# ifdef OF_THREADS
		assert(of_spinlock_unlock(&spinlocks[hash]));
# endif

		if (block->flags & OF_BLOCK_HAS_COPY_DISPOSE)
			block->descriptor->dispose_helper(block);

		free(block);
	}

# ifdef OF_THREADS
	assert(of_spinlock_unlock(&spinlocks[hash]));
# endif
#endif
}

void
_Block_object_assign(void *dst_, const void *src_, const int flags_)
{
	int flags = flags_ & (OF_BLOCK_FIELD_IS_BLOCK |
	    OF_BLOCK_FIELD_IS_OBJECT | OF_BLOCK_FIELD_IS_BYREF);
274
275
276
277
278
279
280












281
282
283
284
285
286
287
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350







+
+
+
+
+
+
+
+
+
+
+
+







	if ((tmp = objc_allocateClassPair(self, "OFMallocBlock", 0)) == NULL)
		@throw [OFInitializationFailedException newWithClass: self];
	memcpy(&_NSConcreteMallocBlock, tmp, sizeof(_NSConcreteMallocBlock));
	free(tmp);
	objc_registerClassPair((Class)&_NSConcreteMallocBlock);
}
#endif

#if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS)
+ (void)initialize
{
	size_t i;

	for (i = 0; i < NUM_SPINLOCKS; i++)
		if (!of_spinlock_new(&spinlocks[i]))
			@throw [OFInitializationFailedException
			    newWithClass: self];
}
#endif

+ alloc
{
	@throw [OFNotImplementedException newWithClass: self
					      selector: _cmd];
}

Modified src/OFFile.m from [0713e735b4] to [b9fdcbe5c3].

24
25
26
27
28
29
30

31


32
33
34
35
36
37
38
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40







+
-
+
+







# include <pwd.h>
# include <grp.h>
#endif

#import "OFFile.h"
#import "OFString.h"
#import "OFArray.h"
#ifdef OF_THREADS
#import "OFThread.h"
# import "OFThread.h"
#endif
#import "OFDate.h"
#import "OFAutoreleasePool.h"
#import "OFExceptions.h"
#import "macros.h"

#ifdef _WIN32
# import <windows.h>
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74







-
+







#define DEFAULT_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
#define DIR_MODE DEFAULT_MODE | S_IXUSR | S_IXGRP | S_IXOTH

OFFile *of_stdin = nil;
OFFile *of_stdout = nil;
OFFile *of_stderr = nil;

#ifndef _WIN32
#if defined(OF_THREADS) && !defined(_WIN32)
static OFMutex *mutex;
#endif

static int parse_mode(const char *mode)
{
	if (!strcmp(mode, "r"))
		return O_RDONLY;
106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122







-
+







		return;

	of_stdin = [[OFFileSingleton alloc] initWithFileDescriptor: 0];
	of_stdout = [[OFFileSingleton alloc] initWithFileDescriptor: 1];
	of_stderr = [[OFFileSingleton alloc] initWithFileDescriptor: 2];
}

#ifndef _WIN32
#if defined(OF_THREADS) && !defined(_WIN32)
+ (void)initialize
{
	if (self == [OFFile class])
		mutex = [[OFMutex alloc] init];
}
#endif

416
417
418
419
420
421
422

423
424
425

426
427
428
429
430
431
432
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436







+



+







	uid_t uid = -1;
	gid_t gid = -1;

	if (owner == nil && group == nil)
		@throw [OFInvalidArgumentException newWithClass: self
						       selector: _cmd];

# ifdef OF_THREADS
	[mutex lock];

	@try {
# endif
		if (owner != nil) {
			struct passwd *pw;

			if ((pw = getpwnam([owner cString])) == NULL)
				@throw [OFChangeFileOwnerFailedException
				    newWithClass: self
					    path: path
444
445
446
447
448
449
450

451
452
453

454
455
456
457
458
459
460
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466







+



+







				    newWithClass: self
					    path: path
					   owner: owner
					   group: group];

			gid = gr->gr_gid;
		}
# ifdef OF_THREADS
	} @finally {
		[mutex unlock];
	}
# endif

	if (chown([path cString], uid, gid))
		@throw [OFChangeFileOwnerFailedException newWithClass: self
								 path: path
								owner: owner
								group: group];
}

Modified src/OFObject.m from [72f139fc0b] to [b33c6cd1e8].

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
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







-
+

-
+














-
+








#ifdef _WIN32
# include <windows.h>
#endif

#import "OFString.h"

#ifdef OF_ATOMIC_OPS
#if defined(OF_ATOMIC_OPS)
# import "atomic.h"
#else
#elif defined(OF_THREADS)
# import "threading.h"
#endif

/* A few macros to reduce #ifdefs */
#ifdef OF_OLD_GNU_RUNTIME
# define class_getInstanceSize class_get_instance_size
# define class_getName class_get_class_name
# define class_getSuperclass class_get_super_class
#endif

struct pre_ivar {
	void	      **memchunks;
	size_t	      memchunks_size;
	int32_t	      retain_count;
#ifndef OF_ATOMIC_OPS
#if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS)
	of_spinlock_t retain_spinlock;
#endif
};

/* Hopefully no arch needs more than 16 bytes padding */
#define PRE_IVAR_ALIGN ((sizeof(struct pre_ivar) + 15) & ~15)
#define PRE_IVAR ((struct pre_ivar*)((char*)self - PRE_IVAR_ALIGN))
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153







-
+







		@throw (OFAllocFailedException*)&alloc_failed_exception;
	}

	((struct pre_ivar*)instance)->memchunks = NULL;
	((struct pre_ivar*)instance)->memchunks_size = 0;
	((struct pre_ivar*)instance)->retain_count = 1;

#ifndef OF_ATOMIC_OPS
#if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS)
	if (!of_spinlock_new(&((struct pre_ivar*)instance)->retain_spinlock)) {
		free(instance);
		@throw [OFInitializationFailedException newWithClass: self];
	}
#endif

	instance = (OFObject*)((char*)instance + PRE_IVAR_ALIGN);
654
655
656
657
658
659
660
661

662
663

664
665
666


667
668
669
670
671
672
673
674
675
676
677
678
679
680

681
682
683

684
685
686
687
688
689
690
691



692
693
694
695
696
697
698
654
655
656
657
658
659
660

661
662

663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681

682
683
684

685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703







-
+

-
+



+
+













-
+


-
+








+
+
+








	@throw [OFMemoryNotPartOfObjectException newWithClass: isa
						      pointer: ptr];
}

- retain
{
#ifdef OF_ATOMIC_OPS
#if defined(OF_ATOMIC_OPS)
	of_atomic_inc_32(&PRE_IVAR->retain_count);
#else
#elif defined(OF_THREADS)
	assert(of_spinlock_lock(&PRE_IVAR->retain_spinlock));
	PRE_IVAR->retain_count++;
	assert(of_spinlock_unlock(&PRE_IVAR->retain_spinlock));
#else
	PRE_IVAR->retain_count++;
#endif

	return self;
}

- (size_t)retainCount
{
	assert(PRE_IVAR->retain_count >= 0);
	return (size_t)PRE_IVAR->retain_count;
}

- (void)release
{
#ifdef OF_ATOMIC_OPS
#if defined(OF_ATOMIC_OPS)
	if (of_atomic_dec_32(&PRE_IVAR->retain_count) <= 0)
		[self dealloc];
#else
#elif defined(OF_THREADS)
	size_t c;

	assert(of_spinlock_lock(&PRE_IVAR->retain_spinlock));
	c = --PRE_IVAR->retain_count;
	assert(of_spinlock_unlock(&PRE_IVAR->retain_spinlock));

	if (!c)
		[self dealloc];
#else
	if (--PRE_IVAR->retain_count <= 0)
		[self dealloc];
#endif
}

- autorelease
{
	/*
	 * Cache OFAutoreleasePool since class lookups are expensive with the

Modified src/threading.h from [707f139f43] to [024109a4fb].

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16


17
18
19
20
21
22
23
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











-
+




+
+







/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "atomic.h"
#import "objfw-defs.h"

#if !defined(OF_THREADS) || (!defined(OF_HAVE_PTHREADS) && !defined(_WIN32))
# error No threads available!
#endif

#import "macros.h"

#if defined(OF_HAVE_PTHREADS)
# include <pthread.h>
typedef pthread_t of_thread_t;
typedef pthread_mutex_t of_mutex_t;
typedef pthread_key_t of_tlskey_t;
#elif defined(_WIN32)