concurrent-ruby 0.7.0.rc0-x86-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +15 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +166 -0
  4. data/ext/concurrent_ruby_ext/atomic_reference.c +78 -0
  5. data/ext/concurrent_ruby_ext/atomic_reference.h +12 -0
  6. data/ext/concurrent_ruby_ext/extconf.rb +59 -0
  7. data/ext/concurrent_ruby_ext/rb_concurrent.c +28 -0
  8. data/lib/concurrent.rb +45 -0
  9. data/lib/concurrent/actress.rb +221 -0
  10. data/lib/concurrent/actress/ad_hoc.rb +20 -0
  11. data/lib/concurrent/actress/context.rb +98 -0
  12. data/lib/concurrent/actress/core.rb +228 -0
  13. data/lib/concurrent/actress/core_delegations.rb +42 -0
  14. data/lib/concurrent/actress/envelope.rb +41 -0
  15. data/lib/concurrent/actress/errors.rb +14 -0
  16. data/lib/concurrent/actress/reference.rb +64 -0
  17. data/lib/concurrent/actress/type_check.rb +48 -0
  18. data/lib/concurrent/agent.rb +232 -0
  19. data/lib/concurrent/async.rb +319 -0
  20. data/lib/concurrent/atomic.rb +46 -0
  21. data/lib/concurrent/atomic/atomic_boolean.rb +157 -0
  22. data/lib/concurrent/atomic/atomic_fixnum.rb +162 -0
  23. data/lib/concurrent/atomic/condition.rb +67 -0
  24. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +118 -0
  25. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +117 -0
  26. data/lib/concurrent/atomic/count_down_latch.rb +116 -0
  27. data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
  28. data/lib/concurrent/atomic/event.rb +98 -0
  29. data/lib/concurrent/atomic/thread_local_var.rb +117 -0
  30. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +7 -0
  31. data/lib/concurrent/atomic_reference/delegated_update.rb +28 -0
  32. data/lib/concurrent/atomic_reference/direct_update.rb +28 -0
  33. data/lib/concurrent/atomic_reference/jruby.rb +8 -0
  34. data/lib/concurrent/atomic_reference/mutex_atomic.rb +47 -0
  35. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +24 -0
  36. data/lib/concurrent/atomic_reference/rbx.rb +16 -0
  37. data/lib/concurrent/atomic_reference/ruby.rb +16 -0
  38. data/lib/concurrent/atomics.rb +10 -0
  39. data/lib/concurrent/channel/buffered_channel.rb +85 -0
  40. data/lib/concurrent/channel/channel.rb +41 -0
  41. data/lib/concurrent/channel/unbuffered_channel.rb +34 -0
  42. data/lib/concurrent/channel/waitable_list.rb +40 -0
  43. data/lib/concurrent/channels.rb +5 -0
  44. data/lib/concurrent/collection/blocking_ring_buffer.rb +71 -0
  45. data/lib/concurrent/collection/priority_queue.rb +305 -0
  46. data/lib/concurrent/collection/ring_buffer.rb +59 -0
  47. data/lib/concurrent/collections.rb +3 -0
  48. data/lib/concurrent/configuration.rb +158 -0
  49. data/lib/concurrent/dataflow.rb +91 -0
  50. data/lib/concurrent/delay.rb +112 -0
  51. data/lib/concurrent/dereferenceable.rb +101 -0
  52. data/lib/concurrent/errors.rb +30 -0
  53. data/lib/concurrent/exchanger.rb +34 -0
  54. data/lib/concurrent/executor/cached_thread_pool.rb +44 -0
  55. data/lib/concurrent/executor/executor.rb +229 -0
  56. data/lib/concurrent/executor/fixed_thread_pool.rb +33 -0
  57. data/lib/concurrent/executor/immediate_executor.rb +16 -0
  58. data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
  59. data/lib/concurrent/executor/java_fixed_thread_pool.rb +33 -0
  60. data/lib/concurrent/executor/java_single_thread_executor.rb +21 -0
  61. data/lib/concurrent/executor/java_thread_pool_executor.rb +187 -0
  62. data/lib/concurrent/executor/per_thread_executor.rb +24 -0
  63. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
  64. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +32 -0
  65. data/lib/concurrent/executor/ruby_single_thread_executor.rb +73 -0
  66. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +286 -0
  67. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +72 -0
  68. data/lib/concurrent/executor/safe_task_executor.rb +35 -0
  69. data/lib/concurrent/executor/serialized_execution.rb +90 -0
  70. data/lib/concurrent/executor/single_thread_executor.rb +35 -0
  71. data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
  72. data/lib/concurrent/executor/timer_set.rb +143 -0
  73. data/lib/concurrent/executors.rb +9 -0
  74. data/lib/concurrent/future.rb +124 -0
  75. data/lib/concurrent/ivar.rb +111 -0
  76. data/lib/concurrent/logging.rb +17 -0
  77. data/lib/concurrent/mvar.rb +200 -0
  78. data/lib/concurrent/obligation.rb +171 -0
  79. data/lib/concurrent/observable.rb +40 -0
  80. data/lib/concurrent/options_parser.rb +46 -0
  81. data/lib/concurrent/promise.rb +169 -0
  82. data/lib/concurrent/scheduled_task.rb +78 -0
  83. data/lib/concurrent/supervisor.rb +343 -0
  84. data/lib/concurrent/timer_task.rb +341 -0
  85. data/lib/concurrent/tvar.rb +252 -0
  86. data/lib/concurrent/utilities.rb +3 -0
  87. data/lib/concurrent/utility/processor_count.rb +150 -0
  88. data/lib/concurrent/utility/timeout.rb +35 -0
  89. data/lib/concurrent/utility/timer.rb +21 -0
  90. data/lib/concurrent/version.rb +3 -0
  91. data/lib/concurrent_ruby.rb +1 -0
  92. data/lib/concurrent_ruby_ext.so +0 -0
  93. data/lib/extension_helper.rb +9 -0
  94. metadata +140 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ODdmZGQzYTA0NTU5NTU0MzZlODU4MDk5ZjU2YWI1YTUyMmVkNDhiNA==
5
+ data.tar.gz: !binary |-
6
+ NmMwNWU0NzRlMzQ2ODE1YTUxZGFlZDExZDVmNWViYTUxM2U0NzRkZA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ OGFhOGI4YTY0NGRjNzkzNzZjMmEzNjE0ZmM5NmZiNjk1ZmE3ZTJiM2M5NWNj
10
+ Mzk4MTFlY2ZiMzNlMGM4MWJhZDdlYmIxZDg3M2RmNTg2M2UwZmEwMjVlYzhi
11
+ ZGVhMzI4YTg5NmU1ZGExOTQ4MTQ5NWNmZTlhOGU4NGI2YjYzYTE=
12
+ data.tar.gz: !binary |-
13
+ ZTQ1OTA4NWI3N2Y2OTgyOWIwNjIwNTNjNWI2ZGI0Y2Q4MDlkYmVjMDk0OTA0
14
+ ZjY5OTUyN2ZlNzI4NThmYWQ1ZDc5ZjkzNzc2YTY3MTY4MjdkZjQ2YWI0ZDBk
15
+ ZmE3ZmMzZjMzYTRmOTZiZmE0M2QxOWJlYTk3MTVkYWNhZWZjYTc=
@@ -0,0 +1,21 @@
1
+ Copyright (c) Jerry D'Antonio -- released under the MIT license.
2
+
3
+ http://www.opensource.org/licenses/mit-license.php
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,166 @@
1
+ # Concurrent Ruby
2
+ [![Gem Version](https://badge.fury.io/rb/concurrent-ruby.png)](http://badge.fury.io/rb/concurrent-ruby) [![Build Status](https://travis-ci.org/ruby-concurrency/concurrent-ruby.svg?branch=master)](https://travis-ci.org/ruby-concurrency/concurrent-ruby) [![Coverage Status](https://coveralls.io/repos/ruby-concurrency/concurrent-ruby/badge.png)](https://coveralls.io/r/ruby-concurrency/concurrent-ruby) [![Code Climate](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby.png)](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby) [![Inline docs](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby.png)](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby) [![Dependency Status](https://gemnasium.com/ruby-concurrency/concurrent-ruby.png)](https://gemnasium.com/ruby-concurrency/concurrent-ruby)
3
+
4
+ <table>
5
+ <tr>
6
+ <td align="left" valign="top">
7
+ <p>
8
+ Modern concurrency tools for Ruby. Inspired by
9
+ <a href="http://www.erlang.org/doc/reference_manual/processes.html">Erlang</a>,
10
+ <a href="http://clojure.org/concurrent_programming">Clojure</a>,
11
+ <a href="http://akka.io/">Scala</a>,
12
+ <a href="http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell">Haskell</a>,
13
+ <a href="http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx">F#</a>,
14
+ <a href="http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx">C#</a>,
15
+ <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html">Java</a>,
16
+ and classic concurrency patterns.
17
+ </p>
18
+ <p>
19
+ The design goals of this gem are:
20
+ <ul>
21
+ <li>Be an 'unopinionated' toolbox that provides useful utilities without debating which is better or why</li>
22
+ <li>Remain free of external gem dependencies</li>
23
+ <li>Stay true to the spirit of the languages providing inspiration</li>
24
+ <li>But implement in a way that makes sense for Ruby</li>
25
+ <li>Keep the semantics as idiomatic Ruby as possible</li>
26
+ <li>Support features that make sense in Ruby</li>
27
+ <li>Exclude features that don't make sense in Ruby</li>
28
+ <li>Be small, lean, and loosely coupled</li>
29
+ </ul>
30
+ </p>
31
+ </td>
32
+ <td align="right" valign="top">
33
+ <img src="https://raw.githubusercontent.com/wiki/ruby-concurrency/concurrent-ruby/logo/concurrent-ruby-logo-300x300.png"/>
34
+ </td>
35
+ </tr>
36
+ </table>
37
+
38
+ ## Install
39
+
40
+ ```shell
41
+ gem install concurrent-ruby
42
+ ```
43
+
44
+ or add the following line to Gemfile:
45
+
46
+ ```ruby
47
+ gem 'concurrent-ruby'
48
+ ```
49
+
50
+ and run `bundle install` from your shell.
51
+
52
+ _NOTE: There is an old gem from 2007 called "concurrent" that does not appear to be under active development. That isn't us. Please do not run* `gem install concurrent`*. It is not the droid you are looking for._
53
+
54
+ ## Features & Documentation
55
+
56
+ Please see the [Concurrent Ruby Wiki](https://github.com/ruby-concurrency/concurrent-ruby/wiki)
57
+ or the [API documentation](http://ruby-concurrency.github.io/concurrent-ruby/frames.html))
58
+ for more information or join our [mailing list](http://groups.google.com/group/concurrent-ruby).
59
+
60
+ There are many concurrency abstractions in this library. These abstractions can be broadly categorized
61
+ into several general groups:
62
+
63
+ * Asynchronous concurrency abstractions including
64
+ [Async](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Async),
65
+ [Agent](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Agent),
66
+ [Future](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Future),
67
+ [Promise](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Promise),
68
+ [ScheduledTask](https://github.com/ruby-concurrency/concurrent-ruby/wiki/ScheduledTask),
69
+ and [TimerTask](https://github.com/ruby-concurrency/concurrent-ruby/wiki/TimerTask)
70
+ * Erlang-inspired [Supervisor](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Supervisor) and other lifecycle classes/mixins
71
+ for managing long-running threads
72
+ * Thread-safe variables including [M-Structures](https://github.com/ruby-concurrency/concurrent-ruby/wiki/MVar-(M-Structure)),
73
+ [I-Structures](https://github.com/ruby-concurrency/concurrent-ruby/wiki/IVar-(I-Structure)),
74
+ [thread-local variables](https://github.com/ruby-concurrency/concurrent-ruby/wiki/ThreadLocalVar),
75
+ atomic counters, and [software transactional memory](https://github.com/ruby-concurrency/concurrent-ruby/wiki/TVar-(STM))
76
+ * Thread synchronization classes and algorithms including [dataflow](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Dataflow),
77
+ timeout, condition, countdown latch, dependency counter, and event
78
+ * Java-inspired [thread pools](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Thread%20Pools)
79
+ * New fast light-weighted [Actor model](http://ruby-concurrency.github.io/concurrent-ruby/frames.html#!Concurrent/Actress.html) implementation.
80
+ * And many more...
81
+
82
+ ### Semantic Versioning
83
+
84
+ This gem adheres to the rules of [semantic versioning](http://semver.org/).
85
+
86
+ ### Supported Ruby versions
87
+
88
+ MRI 1.9.3, 2.0, 2.1, JRuby (1.9 mode), and Rubinius 2.x.
89
+ This library is pure Ruby and has no gem dependencies.
90
+ It should be fully compatible with any interpreter that is compliant with Ruby 1.9.3 or newer.
91
+
92
+ ### Examples
93
+
94
+ Many more code examples can be found in the documentation for each class (linked above).
95
+ This one simple example shows some of the power of this gem.
96
+
97
+ ```ruby
98
+ require 'concurrent'
99
+ require 'thread' # for Queue
100
+ require 'open-uri' # for open(uri)
101
+
102
+ class Ticker
103
+ def get_year_end_closing(symbol, year)
104
+ uri = "http://ichart.finance.yahoo.com/table.csv?s=#{symbol}&a=11&b=01&c=#{year}&d=11&e=31&f=#{year}&g=m"
105
+ data = open(uri) {|f| f.collect{|line| line.strip } }
106
+ data[1].split(',')[4].to_f
107
+ end
108
+ end
109
+
110
+ # Future
111
+ price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013) }
112
+ price.state #=> :pending
113
+ sleep(1) # do other stuff
114
+ price.value #=> 63.65
115
+ price.state #=> :fulfilled
116
+
117
+ # Promise
118
+ prices = Concurrent::Promise.new{ puts Ticker.new.get_year_end_closing('AAPL', 2013) }.
119
+ then{ puts Ticker.new.get_year_end_closing('MSFT', 2013) }.
120
+ then{ puts Ticker.new.get_year_end_closing('GOOG', 2013) }.
121
+ then{ puts Ticker.new.get_year_end_closing('AMZN', 2013) }.execute
122
+ prices.state #=> :pending
123
+ sleep(1) # do other stuff
124
+ #=> 561.02
125
+ #=> 37.41
126
+ #=> 1120.71
127
+ #=> 398.79
128
+
129
+ # ScheduledTask
130
+ task = Concurrent::ScheduledTask.execute(2){ Ticker.new.get_year_end_closing('INTC', 2013) }
131
+ task.state #=> :pending
132
+ sleep(3) # do other stuff
133
+ task.value #=> 25.96
134
+ ```
135
+
136
+ ## Contributors
137
+
138
+ * [Jerry D'Antonio](https://github.com/jdantonio)
139
+ * [Michele Della Torre](https://github.com/mighe)
140
+ * [Chris Seaton](https://github.com/chrisseaton)
141
+ * [Lucas Allan](https://github.com/lucasallan)
142
+ * [Petr Chalupa](https://github.com/pitr-ch)
143
+ * [Ravil Bayramgalin](https://github.com/brainopia)
144
+ * [Larry Lv](https://github.com/larrylv)
145
+ * [Giuseppe Capizzi](https://github.com/gcapizzi)
146
+ * [Bill Dueber](https://github.com/billdueber)
147
+ * [Brian Shirai](https://github.com/brixen)
148
+ * [Chip Miller](https://github.com/chip-miller)
149
+ * [Jamie Hodge](https://github.com/jamiehodge)
150
+ * [Zander Hill](https://github.com/zph)
151
+
152
+ ## Contributing
153
+
154
+ 1. Fork it
155
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
156
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
157
+ 4. Push to the branch (`git push origin my-new-feature`)
158
+ 5. Create new Pull Request
159
+
160
+ ## License and Copyright
161
+
162
+ *Concurrent Ruby* is free software released under the [MIT License](http://www.opensource.org/licenses/MIT).
163
+
164
+ The *Concurrent Ruby* [logo](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Logo)
165
+ was designed by [David Jones](https://twitter.com/zombyboy).
166
+ It is Copyright &copy; 2014 [Jerry D'Antonio](https://twitter.com/jerrydantonio). All Rights Reserved.
@@ -0,0 +1,78 @@
1
+ #include <ruby.h>
2
+ #if defined(__sun)
3
+ #include <atomic.h>
4
+ #endif
5
+
6
+ #ifdef HAVE_LIBKERN_OSATOMIC_H
7
+ #include <libkern/OSAtomic.h>
8
+ #endif
9
+
10
+ #include "atomic_reference.h"
11
+
12
+ void ir_mark(void *value) {
13
+ rb_gc_mark_maybe((VALUE) value);
14
+ }
15
+
16
+ VALUE ir_alloc(VALUE klass) {
17
+ return rb_data_object_alloc(klass, (void *) Qnil, ir_mark, NULL);
18
+ }
19
+
20
+ VALUE ir_initialize(int argc, VALUE* argv, VALUE self) {
21
+ VALUE value = Qnil;
22
+ if (rb_scan_args(argc, argv, "01", &value) == 1) {
23
+ value = argv[0];
24
+ }
25
+ DATA_PTR(self) = (void *) value;
26
+ return Qnil;
27
+ }
28
+
29
+ VALUE ir_get(VALUE self) {
30
+ return (VALUE) DATA_PTR(self);
31
+ }
32
+
33
+ VALUE ir_set(VALUE self, VALUE new_value) {
34
+ DATA_PTR(self) = (void *) new_value;
35
+ return new_value;
36
+ }
37
+
38
+ VALUE ir_get_and_set(VALUE self, VALUE new_value) {
39
+ VALUE old_value;
40
+ old_value = (VALUE) DATA_PTR(self);
41
+ DATA_PTR(self) = (void *) new_value;
42
+ return old_value;
43
+ }
44
+
45
+ VALUE ir_compare_and_set(volatile VALUE self, VALUE expect_value, VALUE new_value) {
46
+ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
47
+ if (OSAtomicCompareAndSwap64(expect_value, new_value, &DATA_PTR(self))) {
48
+ return Qtrue;
49
+ }
50
+ #elif defined(__sun)
51
+ /* Assuming VALUE is uintptr_t */
52
+ /* Based on the definition of uintptr_t from /usr/include/sys/int_types.h */
53
+ #if defined(_LP64) || defined(_I32LPx)
54
+ /* 64-bit: uintptr_t === unsigned long */
55
+ if (atomic_cas_ulong((uintptr_t *) &DATA_PTR(self), expect_value, new_value)) {
56
+ return Qtrue;
57
+ }
58
+ #else
59
+ /* 32-bit: uintptr_t === unsigned int */
60
+ if (atomic_cas_uint((uintptr_t *) &DATA_PTR(self), expect_value, new_value)) {
61
+ return Qtrue;
62
+ }
63
+ #endif
64
+ #elif defined _MSC_VER && defined _M_AMD64
65
+ if (InterlockedCompareExchange64((LONGLONG*)&DATA_PTR(self), new_value, expect_value)) {
66
+ return Qtrue;
67
+ }
68
+ #elif defined _MSC_VER && defined _M_IX86
69
+ if (InterlockedCompareExchange((LONG*)&DATA_PTR(self), new_value, expect_value)) {
70
+ return Qtrue;
71
+ }
72
+ #else
73
+ if (__sync_bool_compare_and_swap(&DATA_PTR(self), expect_value, new_value)) {
74
+ return Qtrue;
75
+ }
76
+ #endif
77
+ return Qfalse;
78
+ }
@@ -0,0 +1,12 @@
1
+ #ifndef __ATOMIC_REFERENCE_H__
2
+ #define __ATOMIC_REFERENCE_H__
3
+
4
+ void ir_mark(void*);
5
+ VALUE ir_alloc(VALUE);
6
+ VALUE ir_initialize(int, VALUE*, VALUE);
7
+ VALUE ir_get(VALUE);
8
+ VALUE ir_set(VALUE, VALUE);
9
+ VALUE ir_get_and_set(VALUE, VALUE);
10
+ VALUE ir_compare_and_set(volatile VALUE, VALUE, VALUE);
11
+
12
+ #endif
@@ -0,0 +1,59 @@
1
+ require 'fileutils'
2
+
3
+ $:.push File.join(File.dirname(__FILE__), '../../lib')
4
+ require 'extension_helper'
5
+
6
+ EXTENSION_NAME = 'concurrent_ruby_ext'
7
+
8
+ def create_dummy_makefile
9
+ File.open('Makefile', 'w') do |f|
10
+ f.puts 'all:'
11
+ f.puts 'install:'
12
+ end
13
+ end
14
+
15
+ if defined?(JRUBY_VERSION) || ! Concurrent.use_c_extensions?
16
+ create_dummy_makefile
17
+ warn 'C optimizations are not supported on this version of Ruby.'
18
+ else
19
+ begin
20
+
21
+ require 'mkmf'
22
+ dir_config(EXTENSION_NAME)
23
+
24
+ have_header "libkern/OSAtomic.h"
25
+
26
+ def compiler_is_gcc
27
+ if CONFIG["GCC"] && CONFIG["GCC"] != ""
28
+ return true
29
+ elsif ( # This could stand to be more generic... but I am afraid.
30
+ CONFIG["CC"] =~ /\bgcc\b/
31
+ )
32
+ return true
33
+ end
34
+ return false
35
+ end
36
+
37
+ if compiler_is_gcc
38
+ case CONFIG["arch"]
39
+ when /mswin32|mingw|solaris/
40
+ $CFLAGS += " -march=native"
41
+ when 'i686-linux'
42
+ $CFLAGS += " -march=i686"
43
+ end
44
+ end
45
+
46
+ try_run(<<CODE,$CFLAGS) && ($defs << '-DHAVE_GCC_CAS')
47
+ int main() {
48
+ int i = 1;
49
+ __sync_bool_compare_and_swap(&i, 1, 4);
50
+ return (i != 4);
51
+ }
52
+ CODE
53
+
54
+ create_makefile(EXTENSION_NAME)
55
+ rescue
56
+ create_dummy_makefile
57
+ warn 'C optimizations cannot be compiled on this version of Ruby.'
58
+ end
59
+ end
@@ -0,0 +1,28 @@
1
+ #include <ruby.h>
2
+
3
+ #include "atomic_reference.h"
4
+
5
+ // module and class definitions
6
+
7
+ static VALUE rb_mConcurrent;
8
+ static VALUE rb_cAtomic;
9
+
10
+ // Init_concurrent_ruby_ext
11
+
12
+ void Init_concurrent_ruby_ext() {
13
+
14
+ // define modules and classes
15
+ rb_mConcurrent = rb_define_module("Concurrent");
16
+ rb_cAtomic = rb_define_class_under(rb_mConcurrent, "CAtomic", rb_cObject);
17
+
18
+ // CAtomic
19
+ rb_define_alloc_func(rb_cAtomic, ir_alloc);
20
+ rb_define_method(rb_cAtomic, "initialize", ir_initialize, -1);
21
+ rb_define_method(rb_cAtomic, "get", ir_get, 0);
22
+ rb_define_method(rb_cAtomic, "value", ir_get, 0);
23
+ rb_define_method(rb_cAtomic, "set", ir_set, 1);
24
+ rb_define_method(rb_cAtomic, "value=", ir_set, 1);
25
+ rb_define_method(rb_cAtomic, "get_and_set", ir_get_and_set, 1);
26
+ rb_define_method(rb_cAtomic, "swap", ir_get_and_set, 1);
27
+ rb_define_method(rb_cAtomic, "_compare_and_set", ir_compare_and_set, 2);
28
+ }
@@ -0,0 +1,45 @@
1
+ require 'concurrent/version'
2
+
3
+ require 'concurrent/configuration'
4
+
5
+ require 'concurrent/atomics'
6
+ require 'concurrent/channels'
7
+ require 'concurrent/collections'
8
+ require 'concurrent/executors'
9
+ require 'concurrent/utilities'
10
+
11
+ require 'concurrent/actress'
12
+ require 'concurrent/atomic'
13
+ require 'concurrent/agent'
14
+ require 'concurrent/async'
15
+ require 'concurrent/dataflow'
16
+ require 'concurrent/delay'
17
+ require 'concurrent/dereferenceable'
18
+ require 'concurrent/errors'
19
+ require 'concurrent/exchanger'
20
+ require 'concurrent/future'
21
+ require 'concurrent/ivar'
22
+ require 'concurrent/mvar'
23
+ require 'concurrent/obligation'
24
+ require 'concurrent/observable'
25
+ require 'concurrent/options_parser'
26
+ require 'concurrent/promise'
27
+ require 'concurrent/scheduled_task'
28
+ require 'concurrent/supervisor'
29
+ require 'concurrent/timer_task'
30
+ require 'concurrent/tvar'
31
+
32
+ # Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell,
33
+ # F#, C#, Java, and classic concurrency patterns.
34
+ #
35
+ # The design goals of this gem are:
36
+ #
37
+ # * Stay true to the spirit of the languages providing inspiration
38
+ # * But implement in a way that makes sense for Ruby
39
+ # * Keep the semantics as idiomatic Ruby as possible
40
+ # * Support features that make sense in Ruby
41
+ # * Exclude features that don't make sense in Ruby
42
+ # * Be small, lean, and loosely coupled
43
+ module Concurrent
44
+
45
+ end
@@ -0,0 +1,221 @@
1
+ require 'concurrent/configuration'
2
+ require 'concurrent/executor/serialized_execution'
3
+ require 'concurrent/ivar'
4
+ require 'concurrent/logging'
5
+
6
+ module Concurrent
7
+
8
+ # # Actor model
9
+ #
10
+ # - Light-weighted.
11
+ # - Inspired by Akka and Erlang.
12
+ #
13
+ # Actors are sharing a thread-pool by default which makes them very cheap to create and discard.
14
+ # Thousands of actors can be created allowing to brake the program to small maintainable pieces
15
+ # without breaking single responsibility principles.
16
+ #
17
+ # ## What is an actor model?
18
+ #
19
+ # [Wiki](http://en.wikipedia.org/wiki/Actor_model) says:
20
+ # The actor model in computer science is a mathematical model of concurrent computation
21
+ # that treats _actors_ as the universal primitives of concurrent digital computation:
22
+ # in response to a message that it receives, an actor can make local decisions,
23
+ # create more actors, send more messages, and determine how to respond to the next
24
+ # message received.
25
+ #
26
+ # ## Why?
27
+ #
28
+ # Concurrency is hard this is one of many ways how to simplify the problem.
29
+ # It is simpler to reason about actors then about locks (and all their possible states).
30
+ #
31
+ # ## How to use it
32
+ #
33
+ # {include:file:doc/actress/quick.out.rb}
34
+ #
35
+ # ## Messaging
36
+ #
37
+ # Messages are processed in same order as they are sent by a sender. It may interleaved with
38
+ # messages form other senders though. There is also a contract in actor model that
39
+ # messages sent between actors should be immutable. Gems like
40
+ #
41
+ # - [Algebrick](https://github.com/pitr-ch/algebrick) - Typed struct on steroids based on
42
+ # algebraic types and pattern matching
43
+ # - [Hamster](https://github.com/hamstergem/hamster) - Efficient, Immutable, Thread-Safe
44
+ # Collection classes for Ruby
45
+ #
46
+ # are very useful.
47
+ #
48
+ # ## Architecture
49
+ #
50
+ # Actors are running on shared thread poll which allows user to create many actors cheaply.
51
+ # Downside is that these actors cannot be directly used to do IO or other blocking operations.
52
+ # Blocking operations could starve the `default_task_pool`. However there are two options:
53
+ #
54
+ # - Create an regular actor which will schedule blocking operations in `global_operation_pool`
55
+ # (which is intended for blocking operations) sending results back to self in messages.
56
+ # - Create an actor using `global_operation_pool` instead of `global_task_pool`, e.g.
57
+ # `AnIOActor.spawn name: :blocking, executor: Concurrent.configuration.global_operation_pool`.
58
+ #
59
+ # Each actor is composed from 3 objects:
60
+ #
61
+ # ### {Reference}
62
+ # {include:Actress::Reference}
63
+ #
64
+ # ### {Core}
65
+ # {include:Actress::Core}
66
+ #
67
+ # ### {Context}
68
+ # {include:Actress::Context}
69
+ #
70
+ # ## Speed
71
+ #
72
+ # Simple benchmark Actress vs Celluloid, the numbers are looking good
73
+ # but you know how it is with benchmarks. Source code is in
74
+ # `examples/actress/celluloid_benchmark.rb`. It sends numbers between x actors
75
+ # and adding 1 until certain limit is reached.
76
+ #
77
+ # Benchmark legend:
78
+ #
79
+ # - mes. - number of messages send between the actors
80
+ # - act. - number of actors exchanging the messages
81
+ # - impl. - which gem is used
82
+ #
83
+ # ### JRUBY
84
+ #
85
+ # Rehearsal --------------------------------------------------------
86
+ # 50000 2 actress 24.110000 0.800000 24.910000 ( 7.728000)
87
+ # 50000 2 celluloid 28.510000 4.780000 33.290000 ( 14.782000)
88
+ # 50000 500 actress 13.700000 0.280000 13.980000 ( 4.307000)
89
+ # 50000 500 celluloid 14.520000 11.740000 26.260000 ( 12.258000)
90
+ # 50000 1000 actress 10.890000 0.220000 11.110000 ( 3.760000)
91
+ # 50000 1000 celluloid 15.600000 21.690000 37.290000 ( 18.512000)
92
+ # 50000 1500 actress 10.580000 0.270000 10.850000 ( 3.646000)
93
+ # 50000 1500 celluloid 14.490000 29.790000 44.280000 ( 26.043000)
94
+ # --------------------------------------------- total: 201.970000sec
95
+ #
96
+ # mes. act. impl. user system total real
97
+ # 50000 2 actress 9.820000 0.510000 10.330000 ( 5.735000)
98
+ # 50000 2 celluloid 10.390000 4.030000 14.420000 ( 7.494000)
99
+ # 50000 500 actress 9.880000 0.200000 10.080000 ( 3.310000)
100
+ # 50000 500 celluloid 12.430000 11.310000 23.740000 ( 11.727000)
101
+ # 50000 1000 actress 10.590000 0.190000 10.780000 ( 4.029000)
102
+ # 50000 1000 celluloid 14.950000 23.260000 38.210000 ( 20.841000)
103
+ # 50000 1500 actress 10.710000 0.250000 10.960000 ( 3.892000)
104
+ # 50000 1500 celluloid 13.280000 30.030000 43.310000 ( 24.620000) (1)
105
+ #
106
+ # ### MRI 2.1.0
107
+ #
108
+ # Rehearsal --------------------------------------------------------
109
+ # 50000 2 actress 4.640000 0.080000 4.720000 ( 4.852390)
110
+ # 50000 2 celluloid 6.110000 2.300000 8.410000 ( 7.898069)
111
+ # 50000 500 actress 6.260000 2.210000 8.470000 ( 7.400573)
112
+ # 50000 500 celluloid 10.250000 4.930000 15.180000 ( 14.174329)
113
+ # 50000 1000 actress 6.300000 1.860000 8.160000 ( 7.303162)
114
+ # 50000 1000 celluloid 12.300000 7.090000 19.390000 ( 17.962621)
115
+ # 50000 1500 actress 7.410000 2.610000 10.020000 ( 8.887396)
116
+ # 50000 1500 celluloid 14.850000 10.690000 25.540000 ( 24.489796)
117
+ # ---------------------------------------------- total: 99.890000sec
118
+ #
119
+ # mes. act. impl. user system total real
120
+ # 50000 2 actress 4.190000 0.070000 4.260000 ( 4.306386)
121
+ # 50000 2 celluloid 6.490000 2.210000 8.700000 ( 8.280051)
122
+ # 50000 500 actress 7.060000 2.520000 9.580000 ( 8.518707)
123
+ # 50000 500 celluloid 10.550000 4.980000 15.530000 ( 14.699962)
124
+ # 50000 1000 actress 6.440000 1.870000 8.310000 ( 7.571059)
125
+ # 50000 1000 celluloid 12.340000 7.510000 19.850000 ( 18.793591)
126
+ # 50000 1500 actress 6.720000 2.160000 8.880000 ( 7.929630)
127
+ # 50000 1500 celluloid 14.140000 10.130000 24.270000 ( 22.775288) (1)
128
+ #
129
+ # *Note (1):* Celluloid is using thread per actor so this bench is creating about 1500
130
+ # native threads. Actress is using constant number of threads.
131
+ module Actress
132
+
133
+ require 'concurrent/actress/type_check'
134
+ require 'concurrent/actress/errors'
135
+ require 'concurrent/actress/core_delegations'
136
+ require 'concurrent/actress/envelope'
137
+ require 'concurrent/actress/reference'
138
+ require 'concurrent/actress/core'
139
+ require 'concurrent/actress/context'
140
+
141
+ require 'concurrent/actress/ad_hoc'
142
+
143
+ # @return [Reference, nil] current executing actor if any
144
+ def self.current
145
+ Thread.current[:__current_actor__]
146
+ end
147
+
148
+ # implements ROOT
149
+ class Root
150
+ include Context
151
+ # to allow spawning of new actors, spawn needs to be called inside the parent Actor
152
+ def on_message(message)
153
+ if message.is_a?(Array) && message.first == :spawn
154
+ spawn message[1], &message[2]
155
+ else
156
+ # ignore
157
+ end
158
+ end
159
+ end
160
+
161
+ # A root actor, a default parent of all actors spawned outside an actor
162
+ ROOT = Core.new(parent: nil, name: '/', class: Root).reference
163
+
164
+ # Spawns a new actor.
165
+ #
166
+ # @example simple
167
+ # Actress.spawn(AdHoc, :ping1) { -> message { message } }
168
+ #
169
+ # @example complex
170
+ # Actress.spawn name: :ping3,
171
+ # class: AdHoc,
172
+ # args: [1]
173
+ # executor: Concurrent.configuration.global_task_pool do |add|
174
+ # lambda { |number| number + add }
175
+ # end
176
+ #
177
+ # @param block for actress_class instantiation
178
+ # @param args see {.spawn_optionify}
179
+ # @return [Reference] never the actual actor
180
+ def self.spawn(*args, &block)
181
+ experimental_acknowledged? or
182
+ warn '[EXPERIMENTAL] A full release of `Actress`, renamed `Actor`, is expected in the 0.7.0 release.'
183
+
184
+ if Actress.current
185
+ Core.new(spawn_optionify(*args).merge(parent: Actress.current), &block).reference
186
+ else
187
+ ROOT.ask([:spawn, spawn_optionify(*args), block]).value
188
+ end
189
+ end
190
+
191
+ # as {.spawn} but it'll raise when Actor not initialized properly
192
+ def self.spawn!(*args, &block)
193
+ spawn(spawn_optionify(*args).merge(initialized: ivar = IVar.new), &block).tap { ivar.no_error! }
194
+ end
195
+
196
+ # @overload spawn_optionify(actress_class, name, *args)
197
+ # @param [Context] actress_class to be spawned
198
+ # @param [String, Symbol] name of the instance, it's used to generate the {Core#path} of the actor
199
+ # @param args for actress_class instantiation
200
+ # @overload spawn_optionify(opts)
201
+ # see {Core#initialize} opts
202
+ def self.spawn_optionify(*args)
203
+ if args.size == 1 && args.first.is_a?(Hash)
204
+ args.first
205
+ else
206
+ { class: args[0],
207
+ name: args[1],
208
+ args: args[2..-1] }
209
+ end
210
+ end
211
+
212
+ # call this to disable experimental warning
213
+ def self.i_know_it_is_experimental!
214
+ @experimental_acknowledged = true
215
+ end
216
+
217
+ def self.experimental_acknowledged?
218
+ !!@experimental_acknowledged
219
+ end
220
+ end
221
+ end