dramatis 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. data/History.txt +7 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +119 -0
  4. data/README.txt +57 -0
  5. data/Rakefile +4 -0
  6. data/config/hoe.rb +70 -0
  7. data/config/requirements.rb +17 -0
  8. data/examples/README.txt +20 -0
  9. data/examples/auction.rb +90 -0
  10. data/examples/bank/bank.rb +7 -0
  11. data/examples/bank/bank_test.rb +7 -0
  12. data/examples/exception.rb +40 -0
  13. data/examples/fib/conservative.rb +50 -0
  14. data/examples/fib/future.rb +5 -0
  15. data/examples/fib/original.rb +33 -0
  16. data/examples/fib/threads.rb +51 -0
  17. data/examples/im/distributed/chat/client.rb +49 -0
  18. data/examples/im/distributed/chat/screen/fox.rb +92 -0
  19. data/examples/im/distributed/chat/screen.rb +11 -0
  20. data/examples/im/distributed/chat/server.rb +72 -0
  21. data/examples/im/distributed/chat.rb +5 -0
  22. data/examples/im/distributed/client.rb +9 -0
  23. data/examples/im/distributed/run.rb +18 -0
  24. data/examples/im/distributed/server.rb +11 -0
  25. data/examples/im/single/chat/client.rb +50 -0
  26. data/examples/im/single/chat/screen/fox.rb +96 -0
  27. data/examples/im/single/chat/screen/wxs.rb +63 -0
  28. data/examples/im/single/chat/screen.rb +11 -0
  29. data/examples/im/single/chat/server.rb +72 -0
  30. data/examples/im/single/chat.rb +5 -0
  31. data/examples/im/single/fox.rb +18 -0
  32. data/examples/im/single/wxchat.rb +19 -0
  33. data/examples/pingpong/actor.rb +33 -0
  34. data/examples/pingpong/actor_rec.rb +34 -0
  35. data/examples/pingpong/pingpong.txt +315 -0
  36. data/examples/pingpong/scala.rb +41 -0
  37. data/examples/pingpong/serial.rb +26 -0
  38. data/examples/pretty.txt +108 -0
  39. data/examples/telephone/.irbrc +2 -0
  40. data/examples/telephone/3esl.txt +21877 -0
  41. data/examples/telephone/fifth/kid.rb +36 -0
  42. data/examples/telephone/fifth/run.rb +26 -0
  43. data/examples/telephone/first/kid.rb +31 -0
  44. data/examples/telephone/first/run.rb +20 -0
  45. data/examples/telephone/fourth/kid.rb +31 -0
  46. data/examples/telephone/fourth/run.rb +26 -0
  47. data/examples/telephone/mangler.rb +53 -0
  48. data/examples/telephone/second/kid.rb +26 -0
  49. data/examples/telephone/second/run.rb +20 -0
  50. data/examples/telephone/seventh/kid.rb +40 -0
  51. data/examples/telephone/seventh/run.rb +35 -0
  52. data/examples/telephone/seventh/test.rb +28 -0
  53. data/examples/telephone/seventh/test2.rb +10 -0
  54. data/examples/telephone/sixth/kid.rb +39 -0
  55. data/examples/telephone/sixth/run.rb +26 -0
  56. data/examples/telephone/third/kid.rb +31 -0
  57. data/examples/telephone/third/run.rb +21 -0
  58. data/lib/dramatis/actor/interface.rb +118 -0
  59. data/lib/dramatis/actor/name/interface.rb +128 -0
  60. data/lib/dramatis/actor/name.rb +44 -0
  61. data/lib/dramatis/actor.rb +96 -0
  62. data/lib/dramatis/deadlock.rb +123 -0
  63. data/lib/dramatis/error/uncaught.rb +19 -0
  64. data/lib/dramatis/error.rb +125 -0
  65. data/lib/dramatis/future/interface.rb +45 -0
  66. data/lib/dramatis/future.rb +32 -0
  67. data/lib/dramatis/runtime/actor/main.rb +3 -0
  68. data/lib/dramatis/runtime/actor.rb +294 -0
  69. data/lib/dramatis/runtime/gate.rb +244 -0
  70. data/lib/dramatis/runtime/scheduler.rb +374 -0
  71. data/lib/dramatis/runtime/task.rb +390 -0
  72. data/lib/dramatis/runtime/thread_pool.rb +149 -0
  73. data/lib/dramatis/runtime/timer.rb +5 -0
  74. data/lib/dramatis/runtime.rb +129 -0
  75. data/lib/dramatis/shoes/runtime.rb +7 -0
  76. data/lib/dramatis/shoes.rb +14 -0
  77. data/lib/dramatis/version.rb +8 -0
  78. data/lib/dramatis.rb +73 -0
  79. data/log/debug.log +0 -0
  80. data/script/destroy +14 -0
  81. data/script/generate +14 -0
  82. data/script/txt2html +74 -0
  83. data/setup.rb +1585 -0
  84. data/spec/dramatis/actor/become_spec.rb +17 -0
  85. data/spec/dramatis/actor/future_spec.rb +189 -0
  86. data/spec/dramatis/actor/name_spec.rb +141 -0
  87. data/spec/dramatis/actor/task_spec.rb +75 -0
  88. data/spec/dramatis/actor_spec.rb +492 -0
  89. data/spec/dramatis/dramatis_spec.rb +23 -0
  90. data/spec/dramatis/exc_spec.rb +78 -0
  91. data/spec/dramatis/runtime/gate_spec.rb +57 -0
  92. data/spec/dramatis/runtime/thread_pool.rb +30 -0
  93. data/spec/dramatis/shoes_spec.rb +11 -0
  94. data/spec/dramatis/simple_spec.rb +32 -0
  95. data/spec/exp_spec.rb +21 -0
  96. data/spec/simple2_spec.rb +36 -0
  97. data/spec/simple_spec.rb +30 -0
  98. data/spec/spec.opts +0 -0
  99. data/spec/spec_helper.rb +26 -0
  100. data/spec/thread_spec.rb +13 -0
  101. data/tasks/deployment.rake +34 -0
  102. data/tasks/environment.rake +7 -0
  103. data/tasks/rspec.rake +21 -0
  104. data/tasks/website.rake +17 -0
  105. data/test/jruby_lm.rb +13 -0
  106. data/test/test.rb +19 -0
  107. data/test/test10.rb +43 -0
  108. data/test/test11.rb +45 -0
  109. data/test/test12.rb +60 -0
  110. data/test/test13.rb +71 -0
  111. data/test/test2.rb +12 -0
  112. data/test/test3.rb +10 -0
  113. data/test/test4.rb +29 -0
  114. data/test/test5.rb +8 -0
  115. data/test/test6.rb +32 -0
  116. data/test/test7.rb +48 -0
  117. data/test/test8.rb +133 -0
  118. data/test/test9.rb +105 -0
  119. data/test/test_exc.rb +22 -0
  120. metadata +180 -0
@@ -0,0 +1,128 @@
1
+ module Dramatis; end
2
+ module Dramatis::Actor; end
3
+ class Dramatis::Actor::Name; end
4
+
5
+ # An Dramatis::Actor::Name::Interface object provides the ability to
6
+ # modify the semantics of actor name and preform other actor-level operations on an
7
+ # actor. It is typically created via Dramatis.interface.
8
+
9
+ class Dramatis::Actor::Name::Interface
10
+
11
+ # call-seq:
12
+ # continue nil -> a_name
13
+ # continue { |retval| ... } -> a_name
14
+ # continue( :exception => lambda { |exception| ... } ) { |retval| ... } -> a_name
15
+ #
16
+ # In call cases, returns a new name with the specified continuation semantics.
17
+ #
18
+ # When passed a nil argument, returns a new actor name with a nil
19
+ # continuation such that when used in an actor method call, the call
20
+ # will return nil immediately. The return value from such a call is
21
+ # lost. Equivalent to and usually called as Dramatis.release.
22
+ #
23
+ # The second form sets up the block passed to the function as the
24
+ # continuation of the call. When the continuation task is received from the
25
+ # target actor, the block will be executed. From senders point of
26
+ # view, the block is an unnamed method: it will only be
27
+ # scheduled when the actor is not executing any other task.
28
+ #
29
+ # Currently it is not possible to gate off block continuations.
30
+ #
31
+ # The third example is a variant on the second and is used to
32
+ # provide a second block to receive an exception object if the actor
33
+ # method call results in an exception being thrown. Otherwise, the
34
+ # runtime will try to deliver exceptions to a dramatis_exception
35
+ # actor method if defined. Otherwise it will be recored by the
36
+ # runtime.
37
+ #
38
+ #--
39
+ # this stuff is either tricky or evil; i need to lookup
40
+ # variable look ordering for instance_eval
41
+ # i'm assuming lexical scope over object scope
42
+ #++
43
+
44
+ def continue options = {}, &continuation
45
+ raise "contradictory options passed to continue" \
46
+ if ( options == nil and continuation ) or
47
+ ( options and !continuation )
48
+ a, o = @name.instance_eval { [ @actor, @options ] }
49
+ @name = Dramatis::Actor::Name.new a
50
+ @name.instance_eval do
51
+ @options = o.dup
52
+ @options[:continuation] = options == nil ? :none : continuation
53
+ options and @options[:exception] = options[:exception]
54
+ end
55
+ @name
56
+ end
57
+
58
+
59
+ # call-seq:
60
+ # future -> a_name
61
+ #
62
+ # Returns a new actor name that when used in an actor method call will return a Dramatis::Future. Usually
63
+ # called via Dramatis.future rather than directly.
64
+
65
+ def future
66
+ a, o = @name.instance_eval { [ @actor, @options ] }
67
+ @name = Dramatis::Actor::Name.new a
68
+ @name.instance_eval do
69
+ @options = o.dup
70
+ @options[:continuation] = :future
71
+ end
72
+ @name
73
+ end
74
+
75
+ # Binds the actor identified by this name to supplied behavior,
76
+ # which should be a native ruby object. Can only be called on
77
+ # unbound actors, typically created with Dramatis::Actor.new(). The
78
+ # result of the call is the actor name of the actor. The
79
+ # continuation semantics of the call depend on the name like a
80
+ # normal actor method call.
81
+
82
+ def bind behavior
83
+ actor_send :bind, behavior
84
+ end
85
+
86
+ def url #:nodoc: not done
87
+ "http://something"
88
+ end
89
+
90
+ def exception exception #:nodoc: this should be private/protected
91
+ actor_send :exception, exception
92
+ end
93
+
94
+ private
95
+
96
+ def continuation c, options
97
+ a, o = @name.instance_eval { [ @actor, @options ] }
98
+ @name = Dramatis::Actor::Name.new a
99
+ @name.instance_eval do
100
+ @actor.register_continuation c
101
+ @options = o.dup
102
+ @options[:continuation_send] = c.to_s
103
+ @options[:continuation] = :none
104
+ # FIX merge options, rather than cherry-pck
105
+ options[:call_thread] and @options[:call_thread] = options[:call_thread]
106
+ end
107
+ @name
108
+ end
109
+
110
+ def actor_send *args, &block
111
+ @name.instance_eval do
112
+ options = @options
113
+ if block
114
+ options = options.dup
115
+ options[:block] = block
116
+ end
117
+ @actor.actor_send args, options
118
+ end
119
+ end
120
+
121
+ def initialize name #:nodoc:
122
+ raise "hell: " + name.inspect \
123
+ if !name or !name.kind_of? Dramatis::Actor::Name
124
+ @name = name
125
+ end
126
+
127
+ end
128
+
@@ -0,0 +1,44 @@
1
+ module Dramatis; end
2
+ module Dramatis::Actor; end
3
+ class Dramatis::Actor::Name; end
4
+
5
+ require 'dramatis/actor'
6
+
7
+ # Dramatis::Actor::Names are proxy objects for actors. When a method
8
+ # is called on an actor name, the dramatis runtime creates and
9
+ # schedules an actor task to be run on the actors (virtual) thread.
10
+
11
+ # Dramatis::Actor::Name has no user-callable methods (except for the
12
+ # implicit method_missing). Other actor name operations are available
13
+ # through the Dramatis::Actor::Name::Interface object, accessible via
14
+ # Dramatis.interface.
15
+
16
+ class Dramatis::Actor::Name
17
+
18
+ def to_s_off #:nodoc:
19
+ method_missing :to_s
20
+ end
21
+
22
+ def dup #:nodoc:
23
+ raise "hell again"
24
+ end
25
+
26
+ def method_missing *args, &block #:nodoc:
27
+ options = @options
28
+ if block
29
+ options = options.clone
30
+ options[:block] = block
31
+ end
32
+ @actor.object_send args, options
33
+ end
34
+
35
+ private
36
+
37
+ def initialize actor #:nodoc:
38
+ raise "hell" if !actor or !actor.kind_of? Dramatis::Runtime::Actor
39
+ @actor = actor
40
+ @options = { :continuation => :rpc }
41
+ self
42
+ end
43
+
44
+ end
@@ -0,0 +1,96 @@
1
+ module Dramatis; end
2
+ module Dramatis::Actor; end
3
+
4
+ require 'dramatis/runtime/actor'
5
+
6
+ # The Dramatis::Actor module is used to create actor classes and
7
+ # objects. An actor class can be created by mixing Dramatis::Actor, e.g.,
8
+ # class MyClass
9
+ # include Dramatis::Actor
10
+ # ...
11
+ # end
12
+ # or can be used to create so called _naked_ _actors_, e.g.,
13
+ # my_hash_actor = Dramatis::Actor.new Hash.new
14
+ #
15
+ # When mixed in to a class, Dramatis::Actor has two effects:
16
+ # 1. It causes new to return a Dramatis::Actor::Name rather than an object reference
17
+ # 1. It defines an actor method which can be used by the class to access its actor name and
18
+ # otherwise affect its actor semantics
19
+
20
+ module Dramatis::Actor
21
+
22
+ def self.included cls #:nodoc:
23
+ cls.instance_eval do
24
+ include Dramatis
25
+ end
26
+ class << cls
27
+ def new *args
28
+ new_actor = Dramatis::Runtime::Actor.new
29
+ object = allocate
30
+ eigenclass = ( class << object; self; end )
31
+ eigenclass.send :define_method, :actor,
32
+ ( lambda { new_actor.object_interface } )
33
+ new_actor.bind object
34
+ new_actor.instance_eval { @gate.refuse :object }
35
+ new_actor.actor_send [ :object_initialize, *args ],
36
+ :continuation => :rpc
37
+ new_actor.name
38
+ end
39
+ end
40
+ end
41
+
42
+ if false # for docs only ...
43
+
44
+ # call-seq:
45
+ # actor -> an_interface
46
+ #
47
+ # actor provides classes that have mixed in Dramatis::Actor access
48
+ # to a Dramatis::Actor::Interface object by which they can access
49
+ # their actor name and other actor operations.
50
+
51
+ def actor; end
52
+
53
+ end
54
+
55
+ # call-seq:
56
+ # new( *args, &block ) -> an_actor_name
57
+ # new( behavior = nil ) -> an_actor_name
58
+ #
59
+ # The first case is used when a class has mixed in
60
+ # Dramatis::Actor. In this case, the arguments are passed to the
61
+ # initialize of method of the including class like normal.
62
+ #
63
+ # The second case is used when creating so called <em>naked
64
+ # actors</em>, e.g.,
65
+ # my_hash = Dramatis::Actor.new Hash.new
66
+ # If no
67
+ # behavior is provided, the actor can be later bound to a behavior
68
+ # by calling Dramatis::Actor::Name::Interface.bind
69
+ #
70
+ # In all cases, new returns a Dramatis::Actor::Name proxy
71
+ # object.
72
+
73
+ def self.new behavior = nil
74
+ ( Dramatis::Runtime::Actor.new behavior ).name
75
+ end
76
+
77
+ if false
78
+ def self.included cls #:nodoc:
79
+ pp caller(0)
80
+ warn "Dramatis::Actor included by #{cls}"
81
+ end
82
+
83
+ def self.derived cls #:nodoc:
84
+ warn "Dramatis::Actor included by #{cls}"
85
+ end
86
+
87
+ def self.extended cls #:nodoc:
88
+ warn "Dramatis::Actor included by #{cls}"
89
+ end
90
+
91
+ def self.inherited cls #:nodoc:
92
+ warn "Dramatis::Actor included by #{cls}"
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,123 @@
1
+ module Dramatis; end
2
+
3
+ class Dramatis::Error < StandardError; end
4
+
5
+ # Exception raised when the runtime determines that deadlock has
6
+ # occurred: that is, there are no executing actors and that while
7
+ # there are one or more tasks queued for one or more actors, all are
8
+ # gated off. Note that case where there are no tasks at all signals
9
+ # normal termination.
10
+ #
11
+ # Inherits most methods from Exception.
12
+ #
13
+ # Dramatis::Deadlock (and eventually all Dramatis::Error subclasses)
14
+ # modify the backtrace generated by native language exceptions in
15
+ # order to put them in a more useful context:
16
+ # 1. They chain exceptions across threads using continuation information
17
+ # 1. They remove dramatis runtime internal information
18
+ # See raw_backtrace.
19
+
20
+ class Dramatis::Deadlock < Dramatis::Error; end
21
+
22
+ class Dramatis::Deadlock_ < Dramatis::Error
23
+
24
+ # call-seq:
25
+ # raw_backtrace -> array of strings
26
+ #
27
+ # raw_backtrace returns the unfiltered but still chained backtrace
28
+ # information. It is the concatenation of the backtrace from each
29
+ # actor call site as an exception propagates back the continuation
30
+ # chain.
31
+ def raw_backtrace
32
+ @raw_backtrace
33
+ end
34
+
35
+ def initialize string = nil, opts = {} #:nodoc:
36
+ super string
37
+ @next = opts[:next]
38
+ @raw_backtrace = []
39
+ end
40
+
41
+ # how things stand:
42
+ # r18 and r19 call set_backtrace at the raise
43
+ # jr never calls it; instead the base class synthesizes it
44
+ # at the first backtrace call
45
+ # as far as frames go, it seems lke jr elides sends sometimes
46
+
47
+ def set_backtrace *args #:nodoc:
48
+ # p "sbt!"
49
+ # pp args[0]
50
+ array = @raw_backtrace = args[0]
51
+ if @next
52
+ @raw_backtrace = @next.raw_backtrace + @raw_backtrace
53
+ array = @next.backtrace + array
54
+ end
55
+
56
+ # pp "raw", @raw_backtrace
57
+
58
+ # remove the scheduler
59
+
60
+ filtered = []
61
+ array.each do |v|
62
+ file, line, func = v.split ':'
63
+ file =~ %r{/lib/dramatis/} or ( filtered << v and next )
64
+ func =~ %r{\Wmaybe_deadlock\W} and next
65
+ file =~ %r{/runtime/scheduler} and func =~ %r{\Wrun\W} and break
66
+ filtered << v
67
+ end
68
+
69
+ # remove queueing delivery
70
+
71
+ array = filtered
72
+ filtered = []
73
+ skipping = false
74
+ array.each do |v|
75
+
76
+ # p v
77
+
78
+ file, line, func = v.split ':'
79
+
80
+ if file !~ %r{/lib/dramatis/}
81
+ # p "not skipping x"
82
+ skipping = false
83
+ filtered << v
84
+ next
85
+ end
86
+
87
+ if !skipping and
88
+ ( ( file =~ %r{/runtime/task} and func =~ %r{\Wqueued\W} ) or
89
+ ( file =~ %r{/runtime/actor} and func =~ %r{\Wsend\W} ) or # r18, r19
90
+ ( file =~ %r{/runtime/actor} and func =~ %r{\Wdeliver\W} ) ) # jr
91
+ # p "skipping"
92
+ skipping = true
93
+ next
94
+ end
95
+
96
+ if file =~ %r{/dramatis/actor/name} and func =~ %r{\Wmethod_missing\W}
97
+ # p "not skipping"
98
+ skipping = false
99
+ next
100
+ end
101
+
102
+ skipping or filtered << v
103
+
104
+ end
105
+
106
+ # pp "filt", filtered
107
+ # pp args[0]
108
+ super filtered
109
+ # super args[0]
110
+ end
111
+
112
+ def backtrace #:nodoc:
113
+ if @raw_backtrace.empty?
114
+ bt = super
115
+ if bt
116
+ set_backtrace bt
117
+ end
118
+ end
119
+ # p "d"
120
+ super
121
+ end
122
+
123
+ end
@@ -0,0 +1,19 @@
1
+ module Dramatis; end
2
+
3
+ class Dramatis::Error < StandardError; end
4
+
5
+ # Exception raised when the runtime exits with uncaught exceptions.
6
+
7
+ class Dramatis::Error::Uncaught < Dramatis::Error
8
+
9
+ # combines the name of all uncaught exceptions.
10
+
11
+ def to_s
12
+ super + ": " + @exceptions.join( " " )
13
+ end
14
+
15
+ def initialize exceptions #:nodoc:
16
+ @exceptions = exceptions
17
+ end
18
+
19
+ end
@@ -0,0 +1,125 @@
1
+ module Dramatis; end
2
+
3
+ # The base class of all non-internal dramatis exceptions.
4
+
5
+ class Dramatis::Error < StandardError; end
6
+
7
+ # Raised when an attempt is made to create an interface object on an
8
+ # object that does not define an interface class.
9
+
10
+ class Dramatis::Error::Interface < StandardError; end
11
+
12
+ # Raised when an attempt is made to bind an already-bound actor.
13
+
14
+ class Dramatis::Error::Bind < Dramatis::Error; end
15
+
16
+ require 'dramatis/error/uncaught'
17
+
18
+ class Dramatis::Error < StandardError
19
+
20
+ def self._traceback exception, _next = nil
21
+ tb = exception.instance_variable_get :@_dramatis_traceback
22
+ if !tb
23
+ tb = exception.instance_variable_set( :@_dramatis_traceback,
24
+ Traceback.new( _next ) )
25
+ end
26
+ tb
27
+ end
28
+
29
+ end
30
+
31
+ class Dramatis::Error::Traceback_
32
+
33
+ def initialize _next
34
+ end
35
+
36
+ end
37
+
38
+ class Exception
39
+
40
+ alias _dramatis_set_backtrace set_backtrace
41
+ alias _dramatis_backtrace backtrace
42
+
43
+ def set_backtrace arg
44
+ # p "set back #{self}"
45
+ _dramatis_set_backtrace arg
46
+ end
47
+
48
+ def backtrace
49
+ # p "back #{self}"
50
+ if instance_variable_defined? :@_dramatis_raw_backtrace
51
+ filter @_dramatis_raw_backtrace
52
+ else
53
+ _dramatis_backtrace
54
+ end
55
+ end
56
+
57
+ def _dramatis_reraise
58
+ # return
59
+ # p "reraise"
60
+ if @_dramatis_raw_backtrace
61
+ @_dramatis_raw_backtrace = backtrace + filter( caller )
62
+ else
63
+ @_dramatis_raw_backtrace = filter( backtrace ) + filter( caller )
64
+ end
65
+ end
66
+
67
+ def filter array
68
+
69
+ # pp "_", array
70
+
71
+ filtered = []
72
+ array.each do |v|
73
+ file, line, func = v.split ':'
74
+ file =~ %r{/lib/dramatis/} or ( filtered << v and next )
75
+ func =~ %r{\Wmaybe_deadlock\W} and next
76
+ file =~ %r{/runtime/scheduler} and func =~ %r{\Wrun\W} and break
77
+ filtered << v
78
+ end
79
+
80
+ # pp "0", filtered
81
+
82
+ # remove queueing delivery
83
+
84
+ array = filtered
85
+ filtered = []
86
+ skipping = false
87
+ array.each do |v|
88
+
89
+ # p v
90
+
91
+ file, line, func = v.split ':'
92
+
93
+ if file !~ %r{/lib/dramatis/}
94
+ # p "not skipping x"
95
+ skipping = false
96
+ filtered << v
97
+ next
98
+ end
99
+
100
+ if !skipping and
101
+ ( ( file =~ %r{/runtime/task} and func =~ %r{\Wqueued\W} ) or
102
+ ( file =~ %r{/runtime/actor} and func =~ %r{\Wsend\W} ) or # r18, r19
103
+ ( file =~ %r{/runtime/actor} and func =~ %r{\Wdeliver\W} ) ) # jr
104
+ # p "skipping"
105
+ skipping = true
106
+ next
107
+ end
108
+
109
+ if file =~ %r{/dramatis/actor/name} and func =~ %r{\Wmethod_missing\W}
110
+ # p "not skipping"
111
+ skipping = false
112
+ next
113
+ end
114
+
115
+ skipping or filtered << v
116
+
117
+ end
118
+
119
+ # pp "filt", filtered
120
+ # pp args[0]
121
+ filtered
122
+ # super args[0]
123
+ end
124
+
125
+ end
@@ -0,0 +1,45 @@
1
+ module Dramatis; end
2
+ class Dramatis::Future; end
3
+
4
+ # A Dramatis::Future::Interface object provides the ability to
5
+ # observe and access the semantics of a future. It is typically
6
+ # created via Dramatis.interface.
7
+
8
+ class Dramatis::Future::Interface
9
+
10
+ # Returns the native value of the future. If the value of the future
11
+ # is not yet available, the method blocks (with rpc gating
12
+ # semantics) until it is.
13
+ #
14
+ # In many cases, this method is not necessary since the
15
+ # method_missing method on the future will catch most attempts to
16
+ # accesses the value. This method may be necessary in corner cases,
17
+ # for example when usingconditionals, conversions, and
18
+ # metaprogramming.
19
+
20
+ def value
21
+ @future.instance_eval do
22
+ @continuation.value
23
+ end
24
+ end
25
+
26
+ # Returns true if the future may be evaluated without
27
+ # blocking. Returns false if the value is not yet available.
28
+ #
29
+ # Once a future is ready it cannot become unready, so once ready? returns
30
+ # true, it will always be true and value access will never block.
31
+
32
+ def ready?
33
+ @future.instance_eval do
34
+ @continuation.ready?
35
+ end
36
+ end
37
+
38
+ def initialize *args, &block #:nodoc:
39
+ @future = args.shift
40
+ @args = args
41
+ @block = block
42
+ end
43
+
44
+ end
45
+
@@ -0,0 +1,32 @@
1
+ module Dramatis; end
2
+
3
+ # Dramatis::Futures are proxy objects for the values returned from
4
+ # actor method calls made with future continuations. When a method is
5
+ # called on a future, the runtime checks to see if the future has been
6
+ # evaluated and returned from the actor that executed the task. If it
7
+ # has, the method is executed on the returned value as if the proxy
8
+ # object was not there.
9
+ #
10
+ # If the task with the future continuation has not yet completed or
11
+ # the continuation task has not yet been run, the method called on
12
+ # the proxy is suspended until the reply is received. Thus, methods on
13
+ # futures sometimes but not always block. If they block, they have
14
+ # normal continuation gating semantics.
15
+ #
16
+ # Dramatis::Future has no user-callable methods (except for the
17
+ # implicit method_missing). Other future operations are available
18
+ # through the Dramatis::Future::Interface object, accessible via
19
+ # Dramatis.interface.
20
+
21
+ class Dramatis::Future
22
+
23
+ def method_missing *args #:nodoc:
24
+ @continuation.value.send( *args )
25
+ end
26
+
27
+ def initialize continuation #:nodoc:
28
+ @continuation = continuation
29
+ end
30
+
31
+ end
32
+
@@ -0,0 +1,3 @@
1
+ module Dramatis; end
2
+ class Dramatis::Runtime; end
3
+