ObjFW  Check-in [e5bcc6a3be]

Overview
Comment:Preliminary OFThread implementation.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e5bcc6a3be5524ff785b087ed21b7929fe38c83638408ac2cbeb8be013e14416
User & Date: js on 2009-05-01 20:24:33
Other Links: manifest | tags
Context
2009-05-01
22:28
Work around a compiler bug that occurs on OS X. check-in: 06ad922132 user: js tags: trunk
20:24
Preliminary OFThread implementation. check-in: e5bcc6a3be user: js tags: trunk
19:38
Some tests were still using #import for C headers. Fixed. check-in: f198059455 user: js tags: trunk
Changes

Modified src/Makefile from [e9f81ad1c1] to [369dbcb763].

14
15
16
17
18
19
20

21
22
23
24
25
26
27
       OFIterator.m		\
       OFList.m			\
       OFNumber.m		\
       OFObject.m		\
       ${OFPLUGIN_M}		\
       OFString.m		\
       OFTCPSocket.m		\

       OFXMLFactory.m		\
       ${ASPRINTF_C}

INCLUDESTMP = ${SRCS:.c=.h}
INCLUDES = ${INCLUDESTMP:.m=.h}	\
	   OFMacros.h		\
	   OFStream.h







>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
       OFIterator.m		\
       OFList.m			\
       OFNumber.m		\
       OFObject.m		\
       ${OFPLUGIN_M}		\
       OFString.m		\
       OFTCPSocket.m		\
       OFThread.m		\
       OFXMLFactory.m		\
       ${ASPRINTF_C}

INCLUDESTMP = ${SRCS:.c=.h}
INCLUDES = ${INCLUDESTMP:.m=.h}	\
	   OFMacros.h		\
	   OFStream.h

Modified src/OFExceptions.h from [a0a41c0e56] to [a500d93cbc].

579
580
581
582
583
584
585












}

/**
 * \return The errno from when the exception was created
 */
- (int)errNo;
@end



















>
>
>
>
>
>
>
>
>
>
>
>
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
}

/**
 * \return The errno from when the exception was created
 */
- (int)errNo;
@end

/**
 * An OFException indicating that joining the thread failed.
 */
@interface OFThreadJoinFailedException: OFException {}
@end

/**
 * An OFException indicating that the thread has been canceled.
 */
@interface OFThreadCanceledException: OFException {}
@end

Modified src/OFExceptions.m from [0456aef792] to [da2de5e5ed].

760
761
762
763
764
765
766



























}

- (int)errNo
{
	return err;
}
@end


































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
}

- (int)errNo
{
	return err;
}
@end

@implementation OFThreadJoinFailedException
- (const char*)cString
{
	if (string != NULL)
		return string;

	asprintf(&string, "Joining a thread of class %s failed! Most likely, "
	    "another thread already waits for the thread to join.",
	    [class name]);

	return string;
}
@end

@implementation OFThreadCanceledException
- (const char*)cString
{
	if (string != NULL)
		return string;

	asprintf(&string, "The requested action cannot be performed because "
	    "the thread of class %s was canceled!", [class name]);

	return string;
}
@end

Added src/OFThread.h version [1ac78297bf].







































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2009
 *   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.
 */

#ifndef _WIN32
#include <pthread.h>
#else
#include <windows.h>
#endif

#import "OFObject.h"

/**
 * The OFThread class provides portable threads.
 *
 * To use it, you should create a new class derived from it and reimplement
 * main.
 */
@interface OFThread: OFObject
{
	id object;
#ifndef _WIN32
	pthread_t thread;
#else
	HANDLE thread;

@public
	id retval;
#endif
}

/**
 * \param obj An object that is passed to the main method
 * \return A new, autoreleased thread
 */
+ threadWithObject: (id)obj;

/**
 * \param obj An object that is passed to the main method
 * \return An initialized OFThread.
 */
- initWithObject: (id)obj;

/**
 * The main routine of the thread. You need to reimplement this!
 *
 * It can access the object passed to the threadWithObject or initWithObject
 * method using the instance variable named object.
 *
 * \return The object the join method should return when called for this thread
 */
- (id)main;

/**
 * Joins a thread.
 *
 * \return The object returned by the main method of the thread.
 */
- join;
@end

Added src/OFThread.m version [170f123979].







































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2009
 *   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 "OFThread.h"
#import "OFExceptions.h"

#ifndef _WIN32
static void*
call_main(void *obj)
{
	return [(OFThread*)obj main];
}
#else
static DWORD WINAPI
call_main(LPVOID obj)
{
	/* Windows does not support returning a pointer. Nasty workaround. */
	((OFThread*)obj)->retval = [(OFThread*)obj main];

	return 0;
}
#endif

@implementation OFThread
+ threadWithObject: (id)obj
{
	/*
	 * This is one of the rare cases where the convenience method should
	 * use self instead of the class.
	 *
	 * The reason is that you derive from OFThread and reimplement main.
	 * If OFThread instead of self would be used here, the reimplemented
	 * main would never be called.
	 */
	return [[[self alloc] initWithObject: obj] autorelease];
}

- initWithObject: (id)obj
{
	Class c;

	self = [super init];
	object = obj;

#ifndef _WIN32
	if (pthread_create(&thread, NULL, call_main, self)) {
#else
	if ((thread =
	    CreateThread(NULL, 0, call_main, self, 0, NULL)) == NULL) {
#endif
		c = isa;
		[super free];
		@throw [OFInitializationFailedException newWithClass: c];
	}

	return self;
}

- main
{
	return nil;
}

- join
{
#ifndef _WIN32
	void *ret;

	if (pthread_join(thread, &ret))
		@throw [OFThreadJoinFailedException newWithClass: isa];

	if (ret == PTHREAD_CANCELED)
		@throw [OFThreadCanceledException newWithClass: isa];

	return (id)ret;
#else
	if (WaitForSingleObject(thread, INFINITE))
		@throw [OFThreadJoinFailedException newWithClass: isa];

	CloseHandle(thread);
	thread = INVALID_HANDLE_VALUE;

	return retval;
#endif
}

- free
{
	/*
	 * No need to handle errors - if canceling the thread fails, we can't
	 * do anything anyway. Most likely, it finished already or was already
	 * canceled.
	 */
#ifndef _WIN32
	pthread_cancel(thread);
#else
	if (thread != INVALID_HANDLE_VALUE) {
		TerminateThread(thread, 1);
		CloseHandle(thread);
	}
#endif

	return [super free];
}
@end

Modified tests/Makefile from [da80e99a87] to [ad2c2c7519].

1
2
3
4
5
6
7
8
9
10

11
12
13
14
include ../extra.mk

SUBDIRS = OFObject		\
	  OFAutoreleasePool	\
	  OFArray		\
	  OFDictionary		\
	  OFHashes		\
	  ${OFPLUGIN}		\
	  OFString		\
	  OFTCPSocket		\

	  OFList		\
	  OFXMLFactory

include ../buildsys.mk










>




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

SUBDIRS = OFObject		\
	  OFAutoreleasePool	\
	  OFArray		\
	  OFDictionary		\
	  OFHashes		\
	  ${OFPLUGIN}		\
	  OFString		\
	  OFTCPSocket		\
	  OFThread		\
	  OFList		\
	  OFXMLFactory

include ../buildsys.mk

Added tests/OFThread/Makefile version [59a4c3438c].















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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 = ofthread${PROG_SUFFIX}
SRCS = OFThread.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.dll 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/OFThread/OFThread.m version [dfe628bf94].

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2009
 *   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"

#include <stdio.h>

#import "OFThread.h"
#import "OFConstString.h"

@interface MyThread: OFThread
@end

@implementation MyThread
- main
{
	if ([object isEqual: @"foo"])
		return @"successful";

	return @"failed";
}
@end

int
main()
{
	MyThread *t = [MyThread threadWithObject: @"foo"];

	if (![[t join] isEqual: @"successful"]) {
		puts("Test failed!");
		return 1;
	}

	puts("Test successful!");
	return 0;
}