eventmachine 0.12.8-x86-mswin32-60 → 0.12.10-x86-mswin32-60
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +14 -13
- data/Rakefile +374 -264
- data/eventmachine.gemspec +4 -5
- data/ext/binder.cpp +125 -126
- data/ext/binder.h +46 -48
- data/ext/cmain.cpp +184 -42
- data/ext/cplusplus.cpp +202 -202
- data/ext/ed.cpp +242 -81
- data/ext/ed.h +39 -22
- data/ext/em.cpp +127 -108
- data/ext/em.h +27 -18
- data/ext/emwin.cpp +3 -3
- data/ext/eventmachine.h +49 -38
- data/ext/eventmachine_cpp.h +96 -96
- data/ext/extconf.rb +147 -132
- data/ext/fastfilereader/extconf.rb +82 -76
- data/ext/project.h +151 -140
- data/ext/rubymain.cpp +222 -103
- data/ext/ssl.cpp +460 -460
- data/ext/ssl.h +94 -94
- data/java/src/com/rubyeventmachine/EmReactor.java +570 -423
- data/java/src/com/rubyeventmachine/EventableChannel.java +69 -57
- data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +189 -171
- data/java/src/com/rubyeventmachine/EventableSocketChannel.java +364 -244
- data/java/src/com/rubyeventmachine/{Application.java → application/Application.java} +194 -200
- data/java/src/com/rubyeventmachine/{Connection.java → application/Connection.java} +74 -74
- data/java/src/com/rubyeventmachine/{ConnectionFactory.java → application/ConnectionFactory.java} +36 -36
- data/java/src/com/rubyeventmachine/{DefaultConnectionFactory.java → application/DefaultConnectionFactory.java} +46 -46
- data/java/src/com/rubyeventmachine/{PeriodicTimer.java → application/PeriodicTimer.java} +38 -38
- data/java/src/com/rubyeventmachine/{Timer.java → application/Timer.java} +54 -54
- data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +109 -108
- data/java/src/com/rubyeventmachine/tests/ConnectTest.java +148 -146
- data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +53 -53
- data/java/src/com/rubyeventmachine/tests/TestServers.java +75 -74
- data/java/src/com/rubyeventmachine/tests/TestTimers.java +90 -89
- data/lib/em/connection.rb +71 -12
- data/lib/em/deferrable.rb +191 -186
- data/lib/em/protocols.rb +36 -35
- data/lib/em/protocols/httpclient2.rb +590 -582
- data/lib/em/protocols/line_and_text.rb +125 -126
- data/lib/em/protocols/linetext2.rb +161 -160
- data/lib/em/protocols/object_protocol.rb +45 -39
- data/lib/em/protocols/smtpclient.rb +357 -331
- data/lib/em/protocols/socks4.rb +66 -0
- data/lib/em/queue.rb +60 -60
- data/lib/em/timers.rb +56 -55
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +125 -169
- data/lib/jeventmachine.rb +257 -142
- data/tasks/{cpp.rake → cpp.rake_example} +76 -76
- data/tests/test_attach.rb +125 -100
- data/tests/test_basic.rb +1 -2
- data/tests/test_connection_count.rb +34 -44
- data/tests/test_epoll.rb +0 -2
- data/tests/test_get_sock_opt.rb +30 -0
- data/tests/test_httpclient2.rb +3 -3
- data/tests/test_inactivity_timeout.rb +21 -1
- data/tests/test_ltp.rb +182 -188
- data/tests/test_next_tick.rb +0 -2
- data/tests/test_pause.rb +70 -0
- data/tests/test_pending_connect_timeout.rb +48 -0
- data/tests/test_ssl_args.rb +78 -67
- data/tests/test_timers.rb +162 -141
- metadata +13 -11
- data/tasks/project.rake +0 -79
- data/tasks/tests.rake +0 -193
@@ -1,89 +1,90 @@
|
|
1
|
-
/**
|
2
|
-
* $Id$
|
3
|
-
*
|
4
|
-
* Author:: Francis Cianfrocca (gmail: blackhedd)
|
5
|
-
* Homepage:: http://rubyeventmachine.com
|
6
|
-
* Date:: 15 Jul 2007
|
7
|
-
*
|
8
|
-
* See EventMachine and EventMachine::Connection for documentation and
|
9
|
-
* usage examples.
|
10
|
-
*
|
11
|
-
*
|
12
|
-
*----------------------------------------------------------------------------
|
13
|
-
*
|
14
|
-
* Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
15
|
-
* Gmail: blackhedd
|
16
|
-
*
|
17
|
-
* This program is free software; you can redistribute it and/or modify
|
18
|
-
* it under the terms of either: 1) the GNU General Public License
|
19
|
-
* as published by the Free Software Foundation; either version 2 of the
|
20
|
-
* License, or (at your option) any later version; or 2) Ruby's License.
|
21
|
-
*
|
22
|
-
* See the file COPYING for complete licensing information.
|
23
|
-
*
|
24
|
-
*---------------------------------------------------------------------------
|
25
|
-
*
|
26
|
-
*
|
27
|
-
*/
|
28
|
-
|
29
|
-
|
30
|
-
package com.rubyeventmachine.tests;
|
31
|
-
|
32
|
-
import com.rubyeventmachine.*;
|
33
|
-
import
|
34
|
-
|
35
|
-
|
36
|
-
import org.junit.
|
37
|
-
import org.junit.
|
38
|
-
import org.junit.
|
39
|
-
import org.junit.
|
40
|
-
import org.junit.
|
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
|
-
a
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
a
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
}
|
1
|
+
/**
|
2
|
+
* $Id$
|
3
|
+
*
|
4
|
+
* Author:: Francis Cianfrocca (gmail: blackhedd)
|
5
|
+
* Homepage:: http://rubyeventmachine.com
|
6
|
+
* Date:: 15 Jul 2007
|
7
|
+
*
|
8
|
+
* See EventMachine and EventMachine::Connection for documentation and
|
9
|
+
* usage examples.
|
10
|
+
*
|
11
|
+
*
|
12
|
+
*----------------------------------------------------------------------------
|
13
|
+
*
|
14
|
+
* Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
15
|
+
* Gmail: blackhedd
|
16
|
+
*
|
17
|
+
* This program is free software; you can redistribute it and/or modify
|
18
|
+
* it under the terms of either: 1) the GNU General Public License
|
19
|
+
* as published by the Free Software Foundation; either version 2 of the
|
20
|
+
* License, or (at your option) any later version; or 2) Ruby's License.
|
21
|
+
*
|
22
|
+
* See the file COPYING for complete licensing information.
|
23
|
+
*
|
24
|
+
*---------------------------------------------------------------------------
|
25
|
+
*
|
26
|
+
*
|
27
|
+
*/
|
28
|
+
|
29
|
+
|
30
|
+
package com.rubyeventmachine.tests;
|
31
|
+
|
32
|
+
import com.rubyeventmachine.*;
|
33
|
+
import com.rubyeventmachine.application.*;
|
34
|
+
import java.io.*;
|
35
|
+
|
36
|
+
import org.junit.Assert;
|
37
|
+
import org.junit.After;
|
38
|
+
import org.junit.AfterClass;
|
39
|
+
import org.junit.Before;
|
40
|
+
import org.junit.BeforeClass;
|
41
|
+
import org.junit.Test;
|
42
|
+
|
43
|
+
|
44
|
+
public class TestTimers {
|
45
|
+
|
46
|
+
@BeforeClass
|
47
|
+
public static void setUpBeforeClass() throws Exception {
|
48
|
+
}
|
49
|
+
|
50
|
+
@AfterClass
|
51
|
+
public static void tearDownAfterClass() throws Exception {
|
52
|
+
}
|
53
|
+
|
54
|
+
@Before
|
55
|
+
public void setUp() throws Exception {
|
56
|
+
}
|
57
|
+
|
58
|
+
@After
|
59
|
+
public void tearDown() throws Exception {
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
@Test
|
65
|
+
public final void test2() throws IOException {
|
66
|
+
Application a = new Application();
|
67
|
+
a.addTimer(0, new Timer() {
|
68
|
+
public void fire() {
|
69
|
+
application.stop();
|
70
|
+
}
|
71
|
+
});
|
72
|
+
a.run();
|
73
|
+
Assert.assertEquals (1, 1); // just to make sure the reactor halts.
|
74
|
+
}
|
75
|
+
|
76
|
+
@Test
|
77
|
+
public final void test3() throws IOException {
|
78
|
+
Application a = new Application();
|
79
|
+
a.addTimer (0.1, new PeriodicTimer() {
|
80
|
+
int n = 0;
|
81
|
+
public void fire() {
|
82
|
+
n++;
|
83
|
+
if (n == 5)
|
84
|
+
application.stop();
|
85
|
+
}
|
86
|
+
});
|
87
|
+
a.run();
|
88
|
+
Assert.assertEquals(1, 1);
|
89
|
+
}
|
90
|
+
}
|
data/lib/em/connection.rb
CHANGED
@@ -34,12 +34,14 @@ module EventMachine
|
|
34
34
|
#
|
35
35
|
def self.new(sig, *args) #:nodoc:
|
36
36
|
allocate.instance_eval do
|
37
|
+
# Store signature
|
38
|
+
@signature = sig
|
39
|
+
associate_callback_target sig
|
40
|
+
|
37
41
|
# Call a superclass's #initialize if it has one
|
38
42
|
initialize(*args)
|
39
43
|
|
40
|
-
#
|
41
|
-
@signature = sig
|
42
|
-
associate_callback_target sig
|
44
|
+
# post initialize callback
|
43
45
|
post_init
|
44
46
|
|
45
47
|
self
|
@@ -51,9 +53,9 @@ module EventMachine
|
|
51
53
|
def initialize(*args) #:nodoc:
|
52
54
|
end
|
53
55
|
|
54
|
-
def associate_callback_target(sig) #:nodoc:
|
55
|
-
|
56
|
-
end
|
56
|
+
# def associate_callback_target(sig) #:nodoc:
|
57
|
+
# # no-op for the time being, to match similar no-op in rubymain.cpp
|
58
|
+
# end
|
57
59
|
|
58
60
|
# EventMachine::Connection#post_init is called by the event loop
|
59
61
|
# immediately after the network connection has been established,
|
@@ -136,8 +138,8 @@ module EventMachine
|
|
136
138
|
# a low-level proxy relay for all data inbound for this connection, to the connection given
|
137
139
|
# as the argument. This is essentially just a helper method for enable_proxy.
|
138
140
|
# See EventMachine::enable_proxy documentation for details.
|
139
|
-
def proxy_incoming_to(conn)
|
140
|
-
EventMachine::enable_proxy(self, conn)
|
141
|
+
def proxy_incoming_to(conn,bufsize=0)
|
142
|
+
EventMachine::enable_proxy(self, conn, bufsize)
|
141
143
|
end
|
142
144
|
|
143
145
|
# Helper method for EventMachine::disable_proxy(self)
|
@@ -173,6 +175,10 @@ module EventMachine
|
|
173
175
|
EventMachine::detach_fd @signature
|
174
176
|
end
|
175
177
|
|
178
|
+
def get_sock_opt level, option
|
179
|
+
EventMachine::get_sock_opt @signature, level, option
|
180
|
+
end
|
181
|
+
|
176
182
|
# EventMachine::Connection#close_connection_after_writing is a variant of close_connection.
|
177
183
|
# All of the descriptive comments given for close_connection also apply to
|
178
184
|
# close_connection_after_writing, <i>with one exception:</i> If the connection has
|
@@ -451,7 +457,7 @@ module EventMachine
|
|
451
457
|
|
452
458
|
# Alias for #set_comm_inactivity_timeout.
|
453
459
|
def comm_inactivity_timeout= value
|
454
|
-
self.
|
460
|
+
self.set_comm_inactivity_timeout value
|
455
461
|
end
|
456
462
|
|
457
463
|
# comm_inactivity_timeout= allows you to set the inactivity-timeout property for
|
@@ -464,10 +470,26 @@ module EventMachine
|
|
464
470
|
EventMachine::set_comm_inactivity_timeout @signature, value.to_f
|
465
471
|
end
|
466
472
|
|
473
|
+
# pending_connect_timeout is the duration after which a TCP connection in the connecting
|
474
|
+
# state will fail. It is important to distinguish this value from comm_inactivity_timeout,
|
475
|
+
# which looks at how long since data was passed on an already established connection.
|
476
|
+
# The value is a float in seconds.
|
477
|
+
def pending_connect_timeout
|
478
|
+
EventMachine::get_pending_connect_timeout @signature
|
479
|
+
end
|
480
|
+
|
481
|
+
# Alias for #set_pending_connect_timeout.
|
482
|
+
def pending_connect_timeout= value
|
483
|
+
self.set_pending_connect_timeout value
|
484
|
+
end
|
485
|
+
|
486
|
+
# set_pending_connect_timeout sets the duration after which a TCP connection in a
|
487
|
+
# connecting state will fail. Takes a float in seconds.
|
488
|
+
def set_pending_connect_timeout value
|
489
|
+
EventMachine::set_pending_connect_timeout @signature, value.to_f
|
490
|
+
end
|
491
|
+
|
467
492
|
# Reconnect to a given host/port with the current EventMachine::Connection instance
|
468
|
-
#--
|
469
|
-
# EXPERIMENTAL. DO NOT RELY ON THIS METHOD TO REMAIN SUPPORTED.
|
470
|
-
# (03Nov06)
|
471
493
|
def reconnect server, port
|
472
494
|
EventMachine::reconnect server, port, self
|
473
495
|
end
|
@@ -501,5 +523,42 @@ module EventMachine
|
|
501
523
|
def stream_file_data filename, args={}
|
502
524
|
EventMachine::FileStreamer.new( self, filename, args )
|
503
525
|
end
|
526
|
+
|
527
|
+
# Enable notify_readable callbacks on this connection. Only possible if the connection was created
|
528
|
+
# using EM.attach and had notify_readable/notify_writable defined on the handler.
|
529
|
+
def notify_readable= mode
|
530
|
+
EventMachine::set_notify_readable @signature, mode
|
531
|
+
end
|
532
|
+
|
533
|
+
# Returns true if the connection is being watched for readability.
|
534
|
+
def notify_readable?
|
535
|
+
EventMachine::is_notify_readable @signature
|
536
|
+
end
|
537
|
+
|
538
|
+
# Enable notify_writable callbacks on this connection. Only possible if the connection was created
|
539
|
+
# using EM.attach and had notify_readable/notify_writable defined on the handler.
|
540
|
+
def notify_writable= mode
|
541
|
+
EventMachine::set_notify_writable @signature, mode
|
542
|
+
end
|
543
|
+
|
544
|
+
# Returns true if the connection is being watched for writability.
|
545
|
+
def notify_writable?
|
546
|
+
EventMachine::is_notify_writable @signature
|
547
|
+
end
|
548
|
+
|
549
|
+
# Pause a connection so that #send_data and #receive_data events are not fired until #resume is called.
|
550
|
+
def pause
|
551
|
+
EventMachine::pause_connection @signature
|
552
|
+
end
|
553
|
+
|
554
|
+
# Resume a connection's #send_data and #receive_data events.
|
555
|
+
def resume
|
556
|
+
EventMachine::resume_connection @signature
|
557
|
+
end
|
558
|
+
|
559
|
+
# True if the connect was paused using #pause.
|
560
|
+
def paused?
|
561
|
+
EventMachine::connection_paused? @signature
|
562
|
+
end
|
504
563
|
end
|
505
564
|
end
|
data/lib/em/deferrable.rb
CHANGED
@@ -1,187 +1,192 @@
|
|
1
|
-
#--
|
2
|
-
#
|
3
|
-
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
|
-
# Homepage:: http://rubyeventmachine.com
|
5
|
-
# Date:: 16 Jul 2006
|
6
|
-
#
|
7
|
-
# See EventMachine and EventMachine::Connection for documentation and
|
8
|
-
# usage examples.
|
9
|
-
#
|
10
|
-
#----------------------------------------------------------------------------
|
11
|
-
#
|
12
|
-
# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
13
|
-
# Gmail: blackhedd
|
14
|
-
#
|
15
|
-
# This program is free software; you can redistribute it and/or modify
|
16
|
-
# it under the terms of either: 1) the GNU General Public License
|
17
|
-
# as published by the Free Software Foundation; either version 2 of the
|
18
|
-
# License, or (at your option) any later version; or 2) Ruby's License.
|
19
|
-
#
|
20
|
-
# See the file COPYING for complete licensing information.
|
21
|
-
#
|
22
|
-
#---------------------------------------------------------------------------
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
26
|
-
module EventMachine
|
27
|
-
module Deferrable
|
28
|
-
|
29
|
-
# Specify a block to be executed if and when the Deferrable object receives
|
30
|
-
# a status of :succeeded. See #set_deferred_status for more information.
|
31
|
-
#
|
32
|
-
# Calling this method on a Deferrable object whose status is not yet known
|
33
|
-
# will cause the callback block to be stored on an internal list.
|
34
|
-
# If you call this method on a Deferrable whose status is :succeeded, the
|
35
|
-
# block will be executed immediately, receiving the parameters given to the
|
36
|
-
# prior #set_deferred_status call.
|
37
|
-
#
|
38
|
-
#--
|
39
|
-
# If there is no status, add a callback to an internal list.
|
40
|
-
# If status is succeeded, execute the callback immediately.
|
41
|
-
# If status is failed, do nothing.
|
42
|
-
#
|
43
|
-
def callback &block
|
44
|
-
return unless block
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@callbacks
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
# a
|
55
|
-
|
56
|
-
|
57
|
-
# If
|
58
|
-
# If status is
|
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
|
-
# passed to the object using #
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
# passed to the object using #
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
|
101
|
-
#
|
102
|
-
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
# to
|
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
|
-
|
1
|
+
#--
|
2
|
+
#
|
3
|
+
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
|
+
# Homepage:: http://rubyeventmachine.com
|
5
|
+
# Date:: 16 Jul 2006
|
6
|
+
#
|
7
|
+
# See EventMachine and EventMachine::Connection for documentation and
|
8
|
+
# usage examples.
|
9
|
+
#
|
10
|
+
#----------------------------------------------------------------------------
|
11
|
+
#
|
12
|
+
# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
13
|
+
# Gmail: blackhedd
|
14
|
+
#
|
15
|
+
# This program is free software; you can redistribute it and/or modify
|
16
|
+
# it under the terms of either: 1) the GNU General Public License
|
17
|
+
# as published by the Free Software Foundation; either version 2 of the
|
18
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
19
|
+
#
|
20
|
+
# See the file COPYING for complete licensing information.
|
21
|
+
#
|
22
|
+
#---------------------------------------------------------------------------
|
23
|
+
#
|
24
|
+
#
|
25
|
+
|
26
|
+
module EventMachine
|
27
|
+
module Deferrable
|
28
|
+
|
29
|
+
# Specify a block to be executed if and when the Deferrable object receives
|
30
|
+
# a status of :succeeded. See #set_deferred_status for more information.
|
31
|
+
#
|
32
|
+
# Calling this method on a Deferrable object whose status is not yet known
|
33
|
+
# will cause the callback block to be stored on an internal list.
|
34
|
+
# If you call this method on a Deferrable whose status is :succeeded, the
|
35
|
+
# block will be executed immediately, receiving the parameters given to the
|
36
|
+
# prior #set_deferred_status call.
|
37
|
+
#
|
38
|
+
#--
|
39
|
+
# If there is no status, add a callback to an internal list.
|
40
|
+
# If status is succeeded, execute the callback immediately.
|
41
|
+
# If status is failed, do nothing.
|
42
|
+
#
|
43
|
+
def callback &block
|
44
|
+
return unless block
|
45
|
+
@deferred_status ||= :unknown
|
46
|
+
if @deferred_status == :succeeded
|
47
|
+
block.call(*@deferred_args)
|
48
|
+
elsif @deferred_status != :failed
|
49
|
+
@callbacks ||= []
|
50
|
+
@callbacks.unshift block # << block
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Specify a block to be executed if and when the Deferrable object receives
|
55
|
+
# a status of :failed. See #set_deferred_status for more information.
|
56
|
+
#--
|
57
|
+
# If there is no status, add an errback to an internal list.
|
58
|
+
# If status is failed, execute the errback immediately.
|
59
|
+
# If status is succeeded, do nothing.
|
60
|
+
#
|
61
|
+
def errback &block
|
62
|
+
return unless block
|
63
|
+
@deferred_status ||= :unknown
|
64
|
+
if @deferred_status == :failed
|
65
|
+
block.call(*@deferred_args)
|
66
|
+
elsif @deferred_status != :succeeded
|
67
|
+
@errbacks ||= []
|
68
|
+
@errbacks.unshift block # << block
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Sets the "disposition" (status) of the Deferrable object. See also the large set of
|
73
|
+
# sugarings for this method.
|
74
|
+
# Note that if you call this method without arguments,
|
75
|
+
# no arguments will be passed to the callback/errback.
|
76
|
+
# If the user has coded these with arguments, then the
|
77
|
+
# user code will throw an argument exception.
|
78
|
+
# Implementors of deferrable classes <b>must</b>
|
79
|
+
# document the arguments they will supply to user callbacks.
|
80
|
+
#
|
81
|
+
# OBSERVE SOMETHING VERY SPECIAL here: you may call this method even
|
82
|
+
# on the INSIDE of a callback. This is very useful when a previously-registered
|
83
|
+
# callback wants to change the parameters that will be passed to subsequently-registered
|
84
|
+
# ones.
|
85
|
+
#
|
86
|
+
# You may give either :succeeded or :failed as the status argument.
|
87
|
+
#
|
88
|
+
# If you pass :succeeded, then all of the blocks passed to the object using the #callback
|
89
|
+
# method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
|
90
|
+
# passed to the object using #errback will be discarded.
|
91
|
+
#
|
92
|
+
# If you pass :failed, then all of the blocks passed to the object using the #errback
|
93
|
+
# method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
|
94
|
+
# passed to the object using # callback will be discarded.
|
95
|
+
#
|
96
|
+
# If you pass any arguments to #set_deferred_status in addition to the status argument,
|
97
|
+
# they will be passed as arguments to any callbacks or errbacks that are executed.
|
98
|
+
# It's your responsibility to ensure that the argument lists specified in your callbacks and
|
99
|
+
# errbacks match the arguments given in calls to #set_deferred_status, otherwise Ruby will raise
|
100
|
+
# an ArgumentError.
|
101
|
+
#
|
102
|
+
#--
|
103
|
+
# We're shifting callbacks off and discarding them as we execute them.
|
104
|
+
# This is valid because by definition callbacks are executed no more than
|
105
|
+
# once. It also has the magic effect of permitting recursive calls, which
|
106
|
+
# means that a callback can call #set_deferred_status and change the parameters
|
107
|
+
# that will be sent to subsequent callbacks down the chain.
|
108
|
+
#
|
109
|
+
# Changed @callbacks and @errbacks from push/shift to unshift/pop, per suggestion
|
110
|
+
# by Kirk Haines, to work around the memory leak bug that still exists in many Ruby
|
111
|
+
# versions.
|
112
|
+
#
|
113
|
+
# Changed 15Sep07: after processing callbacks or errbacks, CLEAR the other set of
|
114
|
+
# handlers. This gets us a little closer to the behavior of Twisted's "deferred,"
|
115
|
+
# which only allows status to be set once. Prior to making this change, it was possible
|
116
|
+
# to "succeed" a Deferrable (triggering its callbacks), and then immediately "fail" it,
|
117
|
+
# triggering its errbacks! That is clearly undesirable, but it's just as undesirable
|
118
|
+
# to raise an exception is status is set more than once on a Deferrable. The latter
|
119
|
+
# behavior would invalidate the idiom of resetting arguments by setting status from
|
120
|
+
# within a callback or errback, but more seriously it would cause spurious errors
|
121
|
+
# if a Deferrable was timed out and then an attempt was made to succeed it. See the
|
122
|
+
# comments under the new method #timeout.
|
123
|
+
#
|
124
|
+
def set_deferred_status status, *args
|
125
|
+
cancel_timeout
|
126
|
+
@errbacks ||= nil
|
127
|
+
@callbacks ||= nil
|
128
|
+
@deferred_status = status
|
129
|
+
@deferred_args = args
|
130
|
+
case @deferred_status
|
131
|
+
when :succeeded
|
132
|
+
if @callbacks
|
133
|
+
while cb = @callbacks.pop
|
134
|
+
cb.call(*@deferred_args)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
@errbacks.clear if @errbacks
|
138
|
+
when :failed
|
139
|
+
if @errbacks
|
140
|
+
while eb = @errbacks.pop
|
141
|
+
eb.call(*@deferred_args)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
@callbacks.clear if @callbacks
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
# Setting a timeout on a Deferrable causes it to go into the failed state after
|
150
|
+
# the Timeout expires (passing no arguments to the object's errbacks).
|
151
|
+
# Setting the status at any time prior to a call to the expiration of the timeout
|
152
|
+
# will cause the timer to be cancelled.
|
153
|
+
def timeout seconds
|
154
|
+
cancel_timeout
|
155
|
+
me = self
|
156
|
+
@deferred_timeout = EventMachine::Timer.new(seconds) {me.fail}
|
157
|
+
end
|
158
|
+
|
159
|
+
# Cancels an outstanding timeout if any. Undoes the action of #timeout.
|
160
|
+
#
|
161
|
+
def cancel_timeout
|
162
|
+
@deferred_timeout ||= nil
|
163
|
+
if @deferred_timeout
|
164
|
+
@deferred_timeout.cancel
|
165
|
+
@deferred_timeout = nil
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
# Sugar for set_deferred_status(:succeeded, ...)
|
171
|
+
#
|
172
|
+
def succeed *args
|
173
|
+
set_deferred_status :succeeded, *args
|
174
|
+
end
|
175
|
+
alias set_deferred_success succeed
|
176
|
+
|
177
|
+
# Sugar for set_deferred_status(:failed, ...)
|
178
|
+
#
|
179
|
+
def fail *args
|
180
|
+
set_deferred_status :failed, *args
|
181
|
+
end
|
182
|
+
alias set_deferred_failure fail
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
# DefaultDeferrable is an otherwise empty class that includes Deferrable.
|
187
|
+
# This is very useful when you just need to return a Deferrable object
|
188
|
+
# as a way of communicating deferred status to some other part of a program.
|
189
|
+
class DefaultDeferrable
|
190
|
+
include Deferrable
|
191
|
+
end
|
187
192
|
end
|