ObjFW  Check-in [b412845664]

Overview
Comment:Initial OFAutoreleasePool - still needs a *lot* of testing.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: b4128456645b46aa3381abd66342393af790c68df4e16b6cc2b1543b0a22bc74
User & Date: js on 2009-01-05 00:56:17
Other Links: manifest | tags
Context
2009-01-05
00:59
Update copyright. check-in: f1b749d113 user: js tags: trunk
00:56
Initial OFAutoreleasePool - still needs a *lot* of testing. check-in: b412845664 user: js tags: trunk
2009-01-04
02:46
Work around a bug in gcc 4.0.1 (or is it Apple gcc only?). check-in: 95992fdc0e user: js tags: trunk
Changes

Modified TODO from [45e4e88464] to [b1093a5a98].



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


Serialization
Tests for OFFile.
Tests for OFNumber.

OFBase64

OFDirectory
OFDictionary
OFSortedArray
OFThread
OFAutoreleasePool

OFStack
OFQueue

OFPlugin
OFXMLParser

OFSortedQueue

OFTLSSocket
OFXMPPClient
>
>










<











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

13
14
15
16
17
18
19
20
21
22
23
Test if autorelease pool releases everything correctly when thread is ended

Serialization
Tests for OFFile.
Tests for OFNumber.

OFBase64

OFDirectory
OFDictionary
OFSortedArray
OFThread


OFStack
OFQueue

OFPlugin
OFXMLParser

OFSortedQueue

OFTLSSocket
OFXMPPClient

Modified configure.ac from [436dc29761] to [788327973c].

63
64
65
66
67
68
69






70
71
72
73
74


75
76
77
78
79
80
81
		ac_cv_snprintf_useful_ret="no",
		ac_cv_snprintf_useful_ret="no")])
AC_MSG_RESULT($ac_cv_snprintf_useful_ret)

test x"$have_asprintf" != x"yes" -a x"$ac_cv_snprintf_useful_ret" != x"yes" && \
	AC_MSG_ERROR(No asprintf and no snprintf returning required space!)







ACX_PTHREAD([
	CPPLAGS="$CPPFLAGS $PTHREAD_CFLAGS"
	LIBS="$LIBS $PTHREAD_LIBS"
	], [
	AC_MSG_ERROR(You need pthreads!)])



AC_CHECK_LIB(ws2_32, main, LIBS="$LIBS -lws2_32")

AC_MSG_CHECKING(whether we have IPv6 support)
AC_CACHE_VAL(ac_cv_have_ipv6, [
	AC_TRY_RUN([
		#include <sys/types.h>







>
>
>
>
>
>
|
|
|
|
|
>
>







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
		ac_cv_snprintf_useful_ret="no",
		ac_cv_snprintf_useful_ret="no")])
AC_MSG_RESULT($ac_cv_snprintf_useful_ret)

test x"$have_asprintf" != x"yes" -a x"$ac_cv_snprintf_useful_ret" != x"yes" && \
	AC_MSG_ERROR(No asprintf and no snprintf returning required space!)

case "$target" in
	*-*-mingw*)
		AC_MSG_CHECKING(for threads)
		AC_MSG_RESULT(win32)
		;;
	*)
		ACX_PTHREAD([
			CPPLAGS="$CPPFLAGS $PTHREAD_CFLAGS"
			LIBS="$LIBS $PTHREAD_LIBS"
			], [
			AC_MSG_ERROR(No pthreads or other supported threads!)])
		;;
esac

AC_CHECK_LIB(ws2_32, main, LIBS="$LIBS -lws2_32")

AC_MSG_CHECKING(whether we have IPv6 support)
AC_CACHE_VAL(ac_cv_have_ipv6, [
	AC_TRY_RUN([
		#include <sys/types.h>

Modified src/Makefile from [28f4f78243] to [a070773c11].

1
2
3
4
5
6
7

8
9
10
11
12
13
14
include ../extra.mk

LIB = ${LIB_PREFIX}objfw${LIB_SUFFIX}
LIB_MAJOR = 1
LIB_MINOR = 0

SRCS = OFArray.m		\

       OFExceptions.m		\
       OFHashes.m		\
       OFFile.m			\
       OFList.m			\
       OFListObject.m		\
       OFNumber.m		\
       OFObject.m		\







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
include ../extra.mk

LIB = ${LIB_PREFIX}objfw${LIB_SUFFIX}
LIB_MAJOR = 1
LIB_MINOR = 0

SRCS = OFArray.m		\
       OFAutoreleasePool.m	\
       OFExceptions.m		\
       OFHashes.m		\
       OFFile.m			\
       OFList.m			\
       OFListObject.m		\
       OFNumber.m		\
       OFObject.m		\

Added src/OFAutoreleasePool.h version [cc7ef60296].





































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of libobjfw. 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 "OFObject.h"

/**
 * The OFAutoreleasePool class provides a class that keeps track of objects
 * that will be released when the autorelease pool is released.
 * Every thread has its own stack of autorelease pools.
 */
@interface OFAutoreleasePool: OFObject
{
	OFObject **objects;
	size_t	 size;
}

/**
 * Adds an object to the autorelease pool at the top of the thread-specific
 * stack.
 *
 * \param obj The object to add to the autorelease pool
 */
+ (void)addToPool: (OFObject*)obj;

/**
 * Adds an object to the specific autorelease pool.
 * stack.
 *
 * \param obj The object to add to the autorelease pool
 */
- addToPool: (OFObject*)obj;

/**
 * Releases all objects in the autorelease pool.
 */
- release;

/**
 * \returns All objects in the autorelease pool
 */
- (OFObject**)objects;
@end

Added src/OFAutoreleasePool.m version [801231f42a].

























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
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
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 * Copyright (c) 2008
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of libobjfw. 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 <stdlib.h>

#ifndef _WIN32
#import <pthread.h>
#endif

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

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

#ifndef _WIN32
static pthread_key_t pool_stack_key;
static pthread_key_t pool_index_key;
#else
static DWORD pool_stack_key;
static DWORD pool_index_key;
#endif

#ifndef _WIN32
static void
free_each(void *ptr)
{
	OFAutoreleasePool **p;
	OFObject **o;

	for (p = (OFAutoreleasePool**)ptr; *p != nil; p++) {
		for (o = [*p objects]; *o != nil; o++)
			[*o release];
		[*p free];
	}
}
#endif

@implementation OFAutoreleasePool
+ (void)initialize
{
#ifndef _WIN32
	if (pthread_key_create(&pool_stack_key, free_each))
		@throw [OFInitializationFailedException newWithClass: self];
	if (pthread_key_create(&pool_index_key, free)) {
		pthread_key_delete(pool_stack_key);
		@throw [OFInitializationFailedException newWithClass: self];
	}
#else
	/* FIXME: Free stuff when thread is terminated! */
	if ((pool_stack_key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
		@throw [OFInitializationFailedException newWithClass: self];
	if ((pool_index_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) {
		TlsFree(pool_stack_key);
		@throw [OFInitializationFailedException newWithClass: self];
	}

#endif
}

+ (void)addToPool: (OFObject*)obj
{
	OFAutoreleasePool **pool_stack;
	int *pool_index;

#ifndef _WIN32
	pool_stack = pthread_getspecific(pool_stack_key);
	pool_index = pthread_getspecific(pool_index_key);
#else
	pool_stack = TlsGetValue(pool_stack_key);
	pool_index = TlsGetValue(pool_index_key);
#endif

	if (pool_stack == NULL || pool_index == NULL) {
		[[self alloc] init];

#ifndef _WIN32
		pool_stack = pthread_getspecific(pool_stack_key);
		pool_index = pthread_getspecific(pool_index_key);
#else
		pool_stack = TlsGetValue(pool_stack_key);
		pool_index = TlsGetValue(pool_index_key);
#endif
	}

	if (*pool_stack == nil || *pool_index == -1)
		@throw [OFInitializationFailedException newWithClass: self];

	[pool_stack[*pool_index] addToPool: obj];
}

- init
{
	OFAutoreleasePool **pool_stack, **pool_stack2;
	int *pool_index;
	Class c;

	if ((self = [super init])) {
		objects = NULL;
		size = 0;

#ifndef _WIN32
		pool_stack = pthread_getspecific(pool_stack_key);
		pool_index = pthread_getspecific(pool_index_key);
#else
		pool_stack = TlsGetValue(pool_stack_key);
		pool_index = TlsGetValue(pool_index_key);
#endif

		if (pool_index == NULL) {
			if ((pool_index = malloc(sizeof(int))) == NULL) {
				c = [self class];
				[super free];
				@throw [OFNoMemException newWithClass: c];
			}

			*pool_index = -1;
#ifndef _WIN32
			pthread_setspecific(pool_index_key, pool_index);
#else
			TlsSetValue(pool_index_key, pool_index);
#endif
		}

		if ((pool_stack2 = realloc(pool_stack,
		    (*pool_index + 3) * sizeof(OFAutoreleasePool*))) == NULL) {
			c = [self class];
			[super free];
			@throw [OFNoMemException newWithClass: c];
		}
		pool_stack = pool_stack2;
#ifndef _WIN32
		pthread_setspecific(pool_stack_key, pool_stack);
#else
		TlsSetValue(pool_stack_key, pool_stack);
#endif
		(*pool_index)++;

		pool_stack[*pool_index] = self;
		pool_stack[*pool_index + 1] = nil;
	}

	return self;
}

- free
{
	[self release];

	return [super free];
}

- addToPool: (OFObject*)obj
{
	OFObject **objects2;
	size_t size2;

	size2 = size + 1;

	if (SIZE_MAX - size < 1 || size2 > SIZE_MAX / sizeof(OFObject*))
		@throw [OFOutOfRangeException newWithClass: [self class]];

	if ((objects2 = realloc(objects, size2 * sizeof(OFObject*))) == NULL)
		@throw [OFNoMemException newWithClass: [self class]
					      andSize: size2];

	objects = objects2;
	objects[size] = obj;
	size = size2;

	return self;
}

- release
{
	size_t i;

	if (objects != NULL) {
		for (i = 0; size < i; i++)
			[objects[i] release];

		free(objects);
	}

	objects = NULL;
	size = 0;

	return self;
}

- (OFObject**)objects
{
	return objects;
}
@end

Modified src/OFObject.h from [9f93088fa9] to [e8bad88823].

16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32















33
34
35
36
37
38
39
/**
 * The OFObject class is the base class for all other classes inside ObjFW.
 */
@interface OFObject: Object
{
	void   **__memchunks;
	size_t __memchunks_size;

}

/**
 * Initialize the already allocated object.
 * Also sets up the memory pool for the object.
 *
 * \return An initialized object
 */
- init;
















/**
 * Adds a pointer to the memory pool.
 * This is useful to add memory allocated by functions such as asprintf to the
 * pool so it gets freed automatically when the object is freed.
 *
 * \param ptr A pointer to add to the memory pool
 */







>










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
/**
 * The OFObject class is the base class for all other classes inside ObjFW.
 */
@interface OFObject: Object
{
	void   **__memchunks;
	size_t __memchunks_size;
	size_t __retain_count;
}

/**
 * Initialize the already allocated object.
 * Also sets up the memory pool for the object.
 *
 * \return An initialized object
 */
- init;

/**
 * Increases the retain count.
 */
- retain;

/**
 * Decreases the retain cound and frees the object if it reaches 0.
 */
- release;

/**
 * Adds the object to the autorelease pool that is on top of the thread's stack.
 */
- autorelease;

/**
 * Adds a pointer to the memory pool.
 * This is useful to add memory allocated by functions such as asprintf to the
 * pool so it gets freed automatically when the object is freed.
 *
 * \param ptr A pointer to add to the memory pool
 */

Modified src/OFObject.m from [027dbab7f0] to [7210a76063].

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
#import "config.h"

#import <stdlib.h>
#import <string.h>
#import <limits.h>

#import "OFObject.h"

#import "OFExceptions.h"
#import "OFMacros.h"

@implementation OFObject
- init
{
	if ((self = [super init]) != nil) {
		__memchunks = NULL;
		__memchunks_size = 0;

	}

	return self;
}

- free
{
	void **iter = __memchunks + __memchunks_size;

	while (iter-- > __memchunks)
		free(*iter);

	if (__memchunks != NULL)
		free(__memchunks);

	return [super free];
}























- addToMemoryPool: (void*)ptr
{
	void **memchunks;
	size_t memchunks_size;

	memchunks_size = __memchunks_size + 1;

	if (SIZE_MAX - __memchunks_size == 0 ||
	    memchunks_size > SIZE_MAX / sizeof(void*))
		@throw [OFOutOfRangeException newWithClass: [self class]];

	if ((memchunks = realloc(__memchunks,
	    memchunks_size * sizeof(void*))) == NULL)
		@throw [OFNoMemException newWithClass: [self class]
					      andSize: memchunks_size];

	__memchunks = memchunks;
	__memchunks[__memchunks_size] = ptr;
	__memchunks_size = memchunks_size;

	return ptr;
}

- (void*)getMemWithSize: (size_t)size
{
	void *ptr, **memchunks;
	size_t memchunks_size;








>









>

>















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|












|







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
#import "config.h"

#import <stdlib.h>
#import <string.h>
#import <limits.h>

#import "OFObject.h"
#import "OFAutoreleasePool.h"
#import "OFExceptions.h"
#import "OFMacros.h"

@implementation OFObject
- init
{
	if ((self = [super init]) != nil) {
		__memchunks = NULL;
		__memchunks_size = 0;
		__retain_count = 1;
	}

	return self;
}

- free
{
	void **iter = __memchunks + __memchunks_size;

	while (iter-- > __memchunks)
		free(*iter);

	if (__memchunks != NULL)
		free(__memchunks);

	return [super free];
}

- retain
{
	__retain_count++;

	return self;
}

- release
{
	if (!--__retain_count)
		return [self free];

	return self;
}

- autorelease
{
	[OFAutoreleasePool addToPool: self];

	return self;
}

- addToMemoryPool: (void*)ptr
{
	void **memchunks;
	size_t memchunks_size;

	memchunks_size = __memchunks_size + 1;

	if (SIZE_MAX - __memchunks_size < 1 ||
	    memchunks_size > SIZE_MAX / sizeof(void*))
		@throw [OFOutOfRangeException newWithClass: [self class]];

	if ((memchunks = realloc(__memchunks,
	    memchunks_size * sizeof(void*))) == NULL)
		@throw [OFNoMemException newWithClass: [self class]
					      andSize: memchunks_size];

	__memchunks = memchunks;
	__memchunks[__memchunks_size] = ptr;
	__memchunks_size = memchunks_size;

	return self;
}

- (void*)getMemWithSize: (size_t)size
{
	void *ptr, **memchunks;
	size_t memchunks_size;

Modified tests/Makefile from [49f488ca75] to [66bc2d57ef].

1

2
3
4
5
6
7
8
9
SUBDIRS = OFObject	\

	  OFArray	\
	  OFHashes	\
	  OFString	\
	  OFTCPSocket	\
	  OFList	\
	  OFXMLFactory

include ../buildsys.mk
|
>
|
|
|
|
|



1
2
3
4
5
6
7
8
9
10
SUBDIRS = OFObject		\
	  OFAutoreleasePool	\
	  OFArray		\
	  OFHashes		\
	  OFString		\
	  OFTCPSocket		\
	  OFList		\
	  OFXMLFactory

include ../buildsys.mk

Added tests/OFAutoreleasePool/Makefile version [da36f1308a].















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PROG_NOINST = ofautoreleasepool${PROG_SUFFIX}
SRCS = OFAutoreleasePool.m

include ../../buildsys.mk
include ../../extra.mk

CPPFLAGS += -I../../src -I../..
LIBS := -L../../src -lobjfw ${LIBS}

.PHONY: run

all: run
run: ${PROG_NOINST}
	rm -f libobjfw.so.1 libobjfw.so.1.0 libobjfw.dylib
	ln -s ../../src/libobjfw.so libobjfw.so.1
	ln -s ../../src/libobjfw.so libobjfw.so.1.0
	ln -s ../../src/libobjfw.dll libobjfw.dll
	ln -s ../../src/libobjfw.dylib libobjfw.dylib
	LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \
	DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \
	${TEST_LAUNCHER} ./${PROG_NOINST}; EXIT=$$?; \
	rm -f libobjfw.so.1 libobjfw.so.1.0 libobjfw.dll libobjfw.dylib; \
	exit $$EXIT

Added tests/OFAutoreleasePool/OFAutoreleasePool.m version [5e9905f854].















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of libobjfw. 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 "config.h"

#import "OFAutoreleasePool.h"

/* FIXME: Just crashtests */

int
main()
{
	OFObject *o1, *o2, *o3;
	OFAutoreleasePool *pool1, *pool2;

	o1 = [[OFObject new] autorelease];

	pool1 = [OFAutoreleasePool new];
	o2 = [[OFObject new] autorelease];
	[pool1 release];

	o2 = [[OFObject new] autorelease];

	pool2 = [OFAutoreleasePool new];
	o3 = [[OFObject new] autorelease];

	[pool1 release];
	[o3 free];

	return 0;
}