ObjFW  Check-in [fbe84dc674]

Overview
Comment:Optimize retain / release on AmigaOS
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: fbe84dc674fa62bed904eff3a8d4ffcdebaa5c754d6f6b1da53f4405f271632b
User & Date: js on 2019-08-18 22:22:34
Other Links: manifest | tags
Context
2019-08-22
09:48
OFFileManager: Improved dir creation in sandbox check-in: 9d23c7e1f9 user: js tags: trunk
2019-08-18
22:22
Optimize retain / release on AmigaOS check-in: fbe84dc674 user: js tags: trunk
21:32
configure: Enable threads on AmigaOS and MorphOS check-in: beb77aaea1 user: js tags: trunk
Changes

Modified configure.ac from [960c7cb4a7] to [a77d2e4413].

949
950
951
952
953
954
955

956
957
958
959
960
961
962
	AS_HELP_STRING([--disable-threads], [disable thread support]))
AS_IF([test x"$enable_threads" != x"no"], [
	AC_MSG_CHECKING(for threads)

	case "$host_os" in
	amigaos* | morphos*)
		AC_MSG_RESULT(Amiga)

		;;
	mingw*)
		AC_MSG_RESULT(WinAPI)
		;;
	*)
		AC_MSG_RESULT(POSIX)








>







949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
	AS_HELP_STRING([--disable-threads], [disable thread support]))
AS_IF([test x"$enable_threads" != x"no"], [
	AC_MSG_CHECKING(for threads)

	case "$host_os" in
	amigaos* | morphos*)
		AC_MSG_RESULT(Amiga)
		have_amiga_threads="yes"
		;;
	mingw*)
		AC_MSG_RESULT(WinAPI)
		;;
	*)
		AC_MSG_RESULT(POSIX)

1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
	echo "Clang >= 3.2"
	printf "  ** (or the latest Clang release to be able to use all "
	echo "features)."
	echo
])

AS_IF([test x"$enable_threads" != x"no" -a x"$atomic_ops" = x"none" \
    -a x"$have_spinlocks" != x"yes"], [
	echo
	printf "  ** Warning: You have enabled threads, but neither atomic "
	echo "operations nor"
	printf "  ** spinlocks are available. Expect *very* poor performance, "
	echo "as a mutex will"
	printf "  ** be locked for every retain and release! If you don't "
	echo "need threads, try"
	echo "  ** --disable-threads to work around this problem."
	echo
])







|










1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
	echo "Clang >= 3.2"
	printf "  ** (or the latest Clang release to be able to use all "
	echo "features)."
	echo
])

AS_IF([test x"$enable_threads" != x"no" -a x"$atomic_ops" = x"none" \
    -a x"$have_spinlocks" != x"yes" -a x"$have_amiga_threads" != x"yes"], [
	echo
	printf "  ** Warning: You have enabled threads, but neither atomic "
	echo "operations nor"
	printf "  ** spinlocks are available. Expect *very* poor performance, "
	echo "as a mutex will"
	printf "  ** be locked for every retain and release! If you don't "
	echo "need threads, try"
	echo "  ** --disable-threads to work around this problem."
	echo
])

Modified src/OFObject.m from [ea3b6b261c] to [c440638f52].

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
#elif defined(OF_OBJFW_RUNTIME)
# import "ObjFWRT.h"
#endif

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





#import "OFString.h"

#import "instance.h"
#if defined(OF_HAVE_ATOMIC_OPS)
# import "atomic.h"
#elif defined(OF_HAVE_THREADS)
# import "mutex.h"
#endif

#if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR)
extern id of_forward(id, SEL, ...);
extern struct stret of_forward_stret(id, SEL, ...);
#else
# define of_forward of_method_not_found
# define of_forward_stret of_method_not_found_stret
#endif

struct pre_ivar {
	int retainCount;
#if !defined(OF_HAVE_ATOMIC_OPS) && defined(OF_HAVE_THREADS)
	of_spinlock_t retainCountSpinlock;
#endif
	struct pre_mem *firstMem, *lastMem;
};

struct pre_mem {
	struct pre_mem *prev, *next;







>
>
>
>




















|







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
#elif defined(OF_OBJFW_RUNTIME)
# import "ObjFWRT.h"
#endif

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

#ifdef OF_AMIGAOS
# include <proto/exec.h>
#endif

#import "OFString.h"

#import "instance.h"
#if defined(OF_HAVE_ATOMIC_OPS)
# import "atomic.h"
#elif defined(OF_HAVE_THREADS)
# import "mutex.h"
#endif

#if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR)
extern id of_forward(id, SEL, ...);
extern struct stret of_forward_stret(id, SEL, ...);
#else
# define of_forward of_method_not_found
# define of_forward_stret of_method_not_found_stret
#endif

struct pre_ivar {
	int retainCount;
#if !defined(OF_HAVE_ATOMIC_OPS) && !defined(OF_AMIGAOS)
	of_spinlock_t retainCountSpinlock;
#endif
	struct pre_mem *firstMem, *lastMem;
};

struct pre_mem {
	struct pre_mem *prev, *next;
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
	if OF_UNLIKELY (instance == nil) {
		allocFailedException.isa = [OFAllocFailedException class];
		@throw (id)&allocFailedException;
	}

	((struct pre_ivar *)instance)->retainCount = 1;

#if !defined(OF_HAVE_ATOMIC_OPS) && defined(OF_HAVE_THREADS)
	if OF_UNLIKELY (!of_spinlock_new(
	    &((struct pre_ivar *)instance)->retainCountSpinlock)) {
		free(instance);
		@throw [OFInitializationFailedException
		    exceptionWithClass: class];
	}
#endif







|







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
	if OF_UNLIKELY (instance == nil) {
		allocFailedException.isa = [OFAllocFailedException class];
		@throw (id)&allocFailedException;
	}

	((struct pre_ivar *)instance)->retainCount = 1;

#if !defined(OF_HAVE_ATOMIC_OPS) && !defined(OF_AMIGAOS)
	if OF_UNLIKELY (!of_spinlock_new(
	    &((struct pre_ivar *)instance)->retainCountSpinlock)) {
		free(instance);
		@throw [OFInitializationFailedException
		    exceptionWithClass: class];
	}
#endif
1179
1180
1181
1182
1183
1184
1185













1186
1187
1188
1189
1190
1191
1192
							 object: self];
}

- (instancetype)retain
{
#if defined(OF_HAVE_ATOMIC_OPS)
	of_atomic_int_inc(&PRE_IVARS->retainCount);













#else
	OF_ENSURE(of_spinlock_lock(&PRE_IVARS->retainCountSpinlock));
	PRE_IVARS->retainCount++;
	OF_ENSURE(of_spinlock_unlock(&PRE_IVARS->retainCountSpinlock));
#endif

	return self;







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







1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
							 object: self];
}

- (instancetype)retain
{
#if defined(OF_HAVE_ATOMIC_OPS)
	of_atomic_int_inc(&PRE_IVARS->retainCount);
#elif defined(OF_AMIGAOS)
	/*
	 * On AmigaOS, we can only have one CPU. As increasing a variable is a
	 * single instruction on M68K, we don't need Forbid() / Permit() on
	 * M68K.
	 */
# ifndef OF_AMIGAOS_M68K
	Forbid();
# endif
	PRE_IVARS->retainCount++;
# ifndef OF_AMIGAOS_M68K
	Permit();
# endif
#else
	OF_ENSURE(of_spinlock_lock(&PRE_IVARS->retainCountSpinlock));
	PRE_IVARS->retainCount++;
	OF_ENSURE(of_spinlock_unlock(&PRE_IVARS->retainCountSpinlock));
#endif

	return self;
1204
1205
1206
1207
1208
1209
1210









1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
	of_memory_barrier_release();

	if (of_atomic_int_dec(&PRE_IVARS->retainCount) <= 0) {
		of_memory_barrier_acquire();

		[self dealloc];
	}









#else
	size_t c;

	OF_ENSURE(of_spinlock_lock(&PRE_IVARS->retainCountSpinlock));
	c = --PRE_IVARS->retainCount;
	OF_ENSURE(of_spinlock_unlock(&PRE_IVARS->retainCountSpinlock));

	if (c == 0)
		[self dealloc];
#endif
}

- (instancetype)autorelease
{
	return _objc_rootAutorelease(self);







>
>
>
>
>
>
>
>
>

|


|


|







1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
	of_memory_barrier_release();

	if (of_atomic_int_dec(&PRE_IVARS->retainCount) <= 0) {
		of_memory_barrier_acquire();

		[self dealloc];
	}
#elif defined(OF_AMIGAOS)
	int retainCount;

	Forbid();
	retainCount = --PRE_IVARS->retainCount;
	Permit();

	if (retainCount == 0)
		[self dealloc];
#else
	int retainCount;

	OF_ENSURE(of_spinlock_lock(&PRE_IVARS->retainCountSpinlock));
	retainCount = --PRE_IVARS->retainCount;
	OF_ENSURE(of_spinlock_unlock(&PRE_IVARS->retainCountSpinlock));

	if (retainCount == 0)
		[self dealloc];
#endif
}

- (instancetype)autorelease
{
	return _objc_rootAutorelease(self);