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.
Files changed (66) hide show
  1. data/.gitignore +14 -13
  2. data/Rakefile +374 -264
  3. data/eventmachine.gemspec +4 -5
  4. data/ext/binder.cpp +125 -126
  5. data/ext/binder.h +46 -48
  6. data/ext/cmain.cpp +184 -42
  7. data/ext/cplusplus.cpp +202 -202
  8. data/ext/ed.cpp +242 -81
  9. data/ext/ed.h +39 -22
  10. data/ext/em.cpp +127 -108
  11. data/ext/em.h +27 -18
  12. data/ext/emwin.cpp +3 -3
  13. data/ext/eventmachine.h +49 -38
  14. data/ext/eventmachine_cpp.h +96 -96
  15. data/ext/extconf.rb +147 -132
  16. data/ext/fastfilereader/extconf.rb +82 -76
  17. data/ext/project.h +151 -140
  18. data/ext/rubymain.cpp +222 -103
  19. data/ext/ssl.cpp +460 -460
  20. data/ext/ssl.h +94 -94
  21. data/java/src/com/rubyeventmachine/EmReactor.java +570 -423
  22. data/java/src/com/rubyeventmachine/EventableChannel.java +69 -57
  23. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +189 -171
  24. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +364 -244
  25. data/java/src/com/rubyeventmachine/{Application.java → application/Application.java} +194 -200
  26. data/java/src/com/rubyeventmachine/{Connection.java → application/Connection.java} +74 -74
  27. data/java/src/com/rubyeventmachine/{ConnectionFactory.java → application/ConnectionFactory.java} +36 -36
  28. data/java/src/com/rubyeventmachine/{DefaultConnectionFactory.java → application/DefaultConnectionFactory.java} +46 -46
  29. data/java/src/com/rubyeventmachine/{PeriodicTimer.java → application/PeriodicTimer.java} +38 -38
  30. data/java/src/com/rubyeventmachine/{Timer.java → application/Timer.java} +54 -54
  31. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +109 -108
  32. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +148 -146
  33. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +53 -53
  34. data/java/src/com/rubyeventmachine/tests/TestServers.java +75 -74
  35. data/java/src/com/rubyeventmachine/tests/TestTimers.java +90 -89
  36. data/lib/em/connection.rb +71 -12
  37. data/lib/em/deferrable.rb +191 -186
  38. data/lib/em/protocols.rb +36 -35
  39. data/lib/em/protocols/httpclient2.rb +590 -582
  40. data/lib/em/protocols/line_and_text.rb +125 -126
  41. data/lib/em/protocols/linetext2.rb +161 -160
  42. data/lib/em/protocols/object_protocol.rb +45 -39
  43. data/lib/em/protocols/smtpclient.rb +357 -331
  44. data/lib/em/protocols/socks4.rb +66 -0
  45. data/lib/em/queue.rb +60 -60
  46. data/lib/em/timers.rb +56 -55
  47. data/lib/em/version.rb +1 -1
  48. data/lib/eventmachine.rb +125 -169
  49. data/lib/jeventmachine.rb +257 -142
  50. data/tasks/{cpp.rake → cpp.rake_example} +76 -76
  51. data/tests/test_attach.rb +125 -100
  52. data/tests/test_basic.rb +1 -2
  53. data/tests/test_connection_count.rb +34 -44
  54. data/tests/test_epoll.rb +0 -2
  55. data/tests/test_get_sock_opt.rb +30 -0
  56. data/tests/test_httpclient2.rb +3 -3
  57. data/tests/test_inactivity_timeout.rb +21 -1
  58. data/tests/test_ltp.rb +182 -188
  59. data/tests/test_next_tick.rb +0 -2
  60. data/tests/test_pause.rb +70 -0
  61. data/tests/test_pending_connect_timeout.rb +48 -0
  62. data/tests/test_ssl_args.rb +78 -67
  63. data/tests/test_timers.rb +162 -141
  64. metadata +13 -11
  65. data/tasks/project.rake +0 -79
  66. 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 java.io.*;
34
-
35
- import org.junit.Assert;
36
- import org.junit.After;
37
- import org.junit.AfterClass;
38
- import org.junit.Before;
39
- import org.junit.BeforeClass;
40
- import org.junit.Test;
41
-
42
-
43
- public class TestTimers {
44
-
45
- @BeforeClass
46
- public static void setUpBeforeClass() throws Exception {
47
- }
48
-
49
- @AfterClass
50
- public static void tearDownAfterClass() throws Exception {
51
- }
52
-
53
- @Before
54
- public void setUp() throws Exception {
55
- }
56
-
57
- @After
58
- public void tearDown() throws Exception {
59
- }
60
-
61
-
62
-
63
- @Test
64
- public final void test2() throws IOException {
65
- Application a = new Application();
66
- a.addTimer(0, new Timer() {
67
- public void fire() {
68
- application.stop();
69
- }
70
- });
71
- a.run();
72
- Assert.assertEquals (1, 1); // just to make sure the reactor halts.
73
- }
74
-
75
- @Test
76
- public final void test3() throws IOException {
77
- Application a = new Application();
78
- a.addTimer (0.1, new PeriodicTimer() {
79
- int n = 0;
80
- public void fire() {
81
- n++;
82
- if (n == 5)
83
- application.stop();
84
- }
85
- });
86
- a.run();
87
- Assert.assertEquals(1, 1);
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
+ }
@@ -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
- # Store signature and run #post_init
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
- # no-op for the time being, to match similar no-op in rubymain.cpp
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.send :set_comm_inactivity_timeout, value
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
@@ -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
- if @deferred_status == :succeeded
46
- block.call(*@deferred_args)
47
- elsif @deferred_status != :failed
48
- @callbacks ||= []
49
- @callbacks.unshift block # << block
50
- end
51
- end
52
-
53
- # Specify a block to be executed if and when the Deferrable object receives
54
- # a status of :failed. See #set_deferred_status for more information.
55
- #--
56
- # If there is no status, add an errback to an internal list.
57
- # If status is failed, execute the errback immediately.
58
- # If status is succeeded, do nothing.
59
- #
60
- def errback &block
61
- return unless block
62
- if @deferred_status == :failed
63
- block.call(*@deferred_args)
64
- elsif @deferred_status != :succeeded
65
- @errbacks ||= []
66
- @errbacks.unshift block # << block
67
- end
68
- end
69
-
70
- # Sets the "disposition" (status) of the Deferrable object. See also the large set of
71
- # sugarings for this method.
72
- # Note that if you call this method without arguments,
73
- # no arguments will be passed to the callback/errback.
74
- # If the user has coded these with arguments, then the
75
- # user code will throw an argument exception.
76
- # Implementors of deferrable classes <b>must</b>
77
- # document the arguments they will supply to user callbacks.
78
- #
79
- # OBSERVE SOMETHING VERY SPECIAL here: you may call this method even
80
- # on the INSIDE of a callback. This is very useful when a previously-registered
81
- # callback wants to change the parameters that will be passed to subsequently-registered
82
- # ones.
83
- #
84
- # You may give either :succeeded or :failed as the status argument.
85
- #
86
- # If you pass :succeeded, then all of the blocks passed to the object using the #callback
87
- # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
88
- # passed to the object using #errback will be discarded.
89
- #
90
- # If you pass :failed, then all of the blocks passed to the object using the #errback
91
- # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
92
- # passed to the object using # callback will be discarded.
93
- #
94
- # If you pass any arguments to #set_deferred_status in addition to the status argument,
95
- # they will be passed as arguments to any callbacks or errbacks that are executed.
96
- # It's your responsibility to ensure that the argument lists specified in your callbacks and
97
- # errbacks match the arguments given in calls to #set_deferred_status, otherwise Ruby will raise
98
- # an ArgumentError.
99
- #
100
- #--
101
- # We're shifting callbacks off and discarding them as we execute them.
102
- # This is valid because by definition callbacks are executed no more than
103
- # once. It also has the magic effect of permitting recursive calls, which
104
- # means that a callback can call #set_deferred_status and change the parameters
105
- # that will be sent to subsequent callbacks down the chain.
106
- #
107
- # Changed @callbacks and @errbacks from push/shift to unshift/pop, per suggestion
108
- # by Kirk Haines, to work around the memory leak bug that still exists in many Ruby
109
- # versions.
110
- #
111
- # Changed 15Sep07: after processing callbacks or errbacks, CLEAR the other set of
112
- # handlers. This gets us a little closer to the behavior of Twisted's "deferred,"
113
- # which only allows status to be set once. Prior to making this change, it was possible
114
- # to "succeed" a Deferrable (triggering its callbacks), and then immediately "fail" it,
115
- # triggering its errbacks! That is clearly undesirable, but it's just as undesirable
116
- # to raise an exception is status is set more than once on a Deferrable. The latter
117
- # behavior would invalidate the idiom of resetting arguments by setting status from
118
- # within a callback or errback, but more seriously it would cause spurious errors
119
- # if a Deferrable was timed out and then an attempt was made to succeed it. See the
120
- # comments under the new method #timeout.
121
- #
122
- def set_deferred_status status, *args
123
- cancel_timeout
124
- @deferred_status = status
125
- @deferred_args = args
126
- case @deferred_status
127
- when :succeeded
128
- if @callbacks
129
- while cb = @callbacks.pop
130
- cb.call(*@deferred_args)
131
- end
132
- end
133
- @errbacks.clear if @errbacks
134
- when :failed
135
- if @errbacks
136
- while eb = @errbacks.pop
137
- eb.call(*@deferred_args)
138
- end
139
- end
140
- @callbacks.clear if @callbacks
141
- end
142
- end
143
-
144
-
145
- # Setting a timeout on a Deferrable causes it to go into the failed state after
146
- # the Timeout expires (passing no arguments to the object's errbacks).
147
- # Setting the status at any time prior to a call to the expiration of the timeout
148
- # will cause the timer to be cancelled.
149
- def timeout seconds
150
- cancel_timeout
151
- me = self
152
- @deferred_timeout = EventMachine::Timer.new(seconds) {me.fail}
153
- end
154
-
155
- # Cancels an outstanding timeout if any. Undoes the action of #timeout.
156
- #
157
- def cancel_timeout
158
- if @deferred_timeout
159
- @deferred_timeout.cancel
160
- @deferred_timeout = nil
161
- end
162
- end
163
-
164
-
165
- # Sugar for set_deferred_status(:succeeded, ...)
166
- #
167
- def succeed *args
168
- set_deferred_status :succeeded, *args
169
- end
170
- alias set_deferred_success succeed
171
-
172
- # Sugar for set_deferred_status(:failed, ...)
173
- #
174
- def fail *args
175
- set_deferred_status :failed, *args
176
- end
177
- alias set_deferred_failure fail
178
- end
179
-
180
-
181
- # DefaultDeferrable is an otherwise empty class that includes Deferrable.
182
- # This is very useful when you just need to return a Deferrable object
183
- # as a way of communicating deferred status to some other part of a program.
184
- class DefaultDeferrable
185
- include Deferrable
186
- end
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