ObjFW  Check-in [df53f06922]

Overview
Comment:Run loops have a stream observer now.

This makes async I/O possible!

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: df53f069226659d92ba7f11d122ec41bea0e0070d5d3fa0fcaf2858a37793fb2
User & Date: js on 2012-09-12 06:11:46
Other Links: manifest | tags
Context
2012-09-12
06:41
OFRunLoop: Reduce the time the lock is held. check-in: 34e548c51d user: js tags: trunk
06:11
Run loops have a stream observer now. check-in: df53f06922 user: js tags: trunk
06:11
OFRunLoop: Remove timer before possible read. check-in: 55e7d380e4 user: js tags: trunk
Changes

Modified src/OFRunLoop.h from [8d3f82ba8f] to [00fc6ba68c].

13
14
15
16
17
18
19

20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"

@class OFSortedList;

@class OFTimer;

/**
 * \brief A class providing a run loop for the application and its processes.
 */
@interface OFRunLoop: OFObject
{
	OFSortedList *timersQueue;

}

/**
 * \brief Returns the main run loop.
 *
 * \return The main run loop
 */







>








>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"

@class OFSortedList;
@class OFStreamObserver;
@class OFTimer;

/**
 * \brief A class providing a run loop for the application and its processes.
 */
@interface OFRunLoop: OFObject
{
	OFSortedList *timersQueue;
	OFStreamObserver *streamObserver;
}

/**
 * \brief Returns the main run loop.
 *
 * \return The main run loop
 */

Modified src/OFRunLoop.m from [30c14bee93] to [af64aebbb7].

17
18
19
20
21
22
23

24
25
26
27
28
29
30
#include "config.h"

#import "OFRunLoop.h"
#import "OFThread.h"
#import "OFSortedList.h"
#import "OFTimer.h"
#import "OFDate.h"


static OFTLSKey *currentRunLoopKey;
static OFRunLoop *mainRunLoop;

@implementation OFRunLoop
+ (void)initialize
{







>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "config.h"

#import "OFRunLoop.h"
#import "OFThread.h"
#import "OFSortedList.h"
#import "OFTimer.h"
#import "OFDate.h"
#import "OFStreamObserver.h"

static OFTLSKey *currentRunLoopKey;
static OFRunLoop *mainRunLoop;

@implementation OFRunLoop
+ (void)initialize
{
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
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		timersQueue = [[[OFThread currentThread] _timersQueue] retain];


		[OFThread setObject: self
			  forTLSKey: currentRunLoopKey];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[timersQueue release];


	[super dealloc];
}

- (void)addTimer: (OFTimer*)timer
{
	@synchronized (timersQueue) {
		[timersQueue addObject: timer];
	}

}

- (void)run
{
	for (;;) {
		void *pool = objc_autoreleasePoolPush();
		OFDate *now = [OFDate date];







>
>















>









>







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
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		timersQueue = [[[OFThread currentThread] _timersQueue] retain];
		streamObserver = [[OFStreamObserver alloc] init];

		[OFThread setObject: self
			  forTLSKey: currentRunLoopKey];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[timersQueue release];
	[streamObserver release];

	[super dealloc];
}

- (void)addTimer: (OFTimer*)timer
{
	@synchronized (timersQueue) {
		[timersQueue addObject: timer];
	}
	[streamObserver cancel];
}

- (void)run
{
	for (;;) {
		void *pool = objc_autoreleasePoolPush();
		OFDate *now = [OFDate date];
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
				[timersQueue removeListObject: iter];

				[timer fire];

				objc_autoreleasePoolPop(pool2);
			}

			/* Sleep until we reach the next timer */
			if (iter != NULL)
				[OFThread sleepUntilDate:
				    [iter->object fireDate]];


			else {
				/*
				 * FIXME:
				 * Theoretically, another thread could add
				 * something to the run loop. This means we
				 * would need a way to block the thread until
				 * another event is added. The most easy way to
				 * achieve that would be if a run loop also
				 * handles streams: An OFStreamObserver could
				 * be called instead of sleepUntilDate above
				 * and get a timeout. If no timers are left,
				 * it could be called without a timeout and
				 * would automatically stop blocking once a new
				 * stream is added. This could also be used to
				 * stop blocking once a new timer is added.

				 */
				[OFThread sleepForTimeInterval: 24 * 3600];

			}
		}

		objc_autoreleasePoolPop(pool);
	}
}
@end







|
|
<
|
>
>
|

<
<
<
<
<
<
<
<
|
<
<
<
|
>

<
>







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
				[timersQueue removeListObject: iter];

				[timer fire];

				objc_autoreleasePoolPop(pool2);
			}

			/* Watch for stream events till the next timer is due */
			if (iter != NULL) {

				double timeout = [[iter->object fireDate]
				    timeIntervalSinceNow];
				[streamObserver observeWithTimeout: timeout];
			} else {
				/*








				 * No more timers: Just watch for streams until



				 * we get an event. If a timer is added by
				 * another thread, it cancels the observe.
				 */

				[streamObserver observe];
			}
		}

		objc_autoreleasePoolPop(pool);
	}
}
@end