asynchronous 3.0.1 → 4.0.0.pre
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.
- checksums.yaml +5 -13
- data/Gemfile.lock +1 -13
- data/README.md +36 -87
- data/VERSION +1 -1
- data/asynchronous.gemspec +0 -4
- data/examples/async_patterns.rb +17 -14
- data/examples/bootstrap.rb +2 -0
- data/examples/no_zombie_test.rb +5 -2
- data/examples/parallelism.rb +35 -0
- data/lib/async.rb +1 -0
- data/lib/asynchronous.rb +4 -9
- data/lib/asynchronous/concurrency.rb +33 -67
- data/lib/asynchronous/error.rb +8 -0
- data/lib/asynchronous/kernel.rb +18 -17
- data/lib/asynchronous/parallelism.rb +102 -106
- metadata +12 -45
- data/dump/async.rb +0 -4
- data/dump/shared_memory.rb +0 -138
- data/examples/array_of_value_with_native_threads.rb +0 -23
- data/examples/ruby_worker.rb +0 -54
- data/examples/shared_memory1.rb +0 -19
- data/examples/shared_memory2.rb +0 -29
- data/lib/asynchronous/clean_class.rb +0 -14
- data/lib/asynchronous/shared_memory.rb +0 -214
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
OGNlZWE3MjliNGRhMzY3NGEzZTZkMGE4M2Q3NTExZGU0NGY0OWNhMQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8b9e12c7186a3dc906e14faede2ecab396c1d6d1
|
4
|
+
data.tar.gz: 6ce4ccbbfe6fd0bbf064e323278fec86ecd3b814
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
YjMzN2U3NTBhNjMzNGM4Y2I1ODI1MDBhNTgyMTg2NzQ1YWM5YzM3MDhlNWIw
|
11
|
-
ZDBiOTlkMjI2MTM4OTcwYTg0YjA3YWNlOTlmZGRhN2E3MWI2NzI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NDRlMmNhODk3NDQ0YjkwNWY4MzJiNDNiMDQwZTg3YjNkNDE5Yzg3ZTQwYTRk
|
14
|
-
OWNiZWRjZjg1NGMwODhmODE3OGU2NDNhYjQ5M2UwMTI4MzA2NWM4ZDc5OWRj
|
15
|
-
ZTdhNmUxZTRmMDI5NmZjNmFjYWRiOTIwMGZmYjczNDgxYjU1YmM=
|
6
|
+
metadata.gz: 69ec170beaa0e9ff62e3044f25aa67f07ef42e7b6f5b1117aad5de72f907e4244a1a58039214db3ad09ac4b93149a3ee4902ed444104968daaabc67a4856e3c6
|
7
|
+
data.tar.gz: 337e7edc8238f24a442f79f33ee265fbb4d51856e9bfa755a9ae41d4f21eaea4d0d855f045a64e0b9f8e1aed1c1482e83c58efc2aa0b464fb4e26c4be20b1f3f
|
data/Gemfile.lock
CHANGED
@@ -1,26 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
asynchronous (
|
5
|
-
process_shared
|
4
|
+
asynchronous (4.0.0.pre)
|
6
5
|
|
7
6
|
GEM
|
8
7
|
remote: http://rubygems.org/
|
9
8
|
specs:
|
10
|
-
columnize (0.3.6)
|
11
|
-
debugger (1.6.2)
|
12
|
-
columnize (>= 0.3.1)
|
13
|
-
debugger-linecache (~> 1.2.0)
|
14
|
-
debugger-ruby_core_source (~> 1.2.3)
|
15
|
-
debugger-linecache (1.2.0)
|
16
|
-
debugger-ruby_core_source (1.2.3)
|
17
|
-
ffi (1.9.3)
|
18
|
-
process_shared (0.2.0)
|
19
|
-
ffi (~> 1.0)
|
20
9
|
|
21
10
|
PLATFORMS
|
22
11
|
ruby
|
23
12
|
|
24
13
|
DEPENDENCIES
|
25
14
|
asynchronous!
|
26
|
-
debugger
|
data/README.md
CHANGED
@@ -40,7 +40,7 @@ Like parsing (in some case)
|
|
40
40
|
|
41
41
|
```ruby
|
42
42
|
|
43
|
-
|
43
|
+
thr = async :parallelism do
|
44
44
|
|
45
45
|
sleep 4
|
46
46
|
# remember, everything you
|
@@ -51,8 +51,8 @@ calculation = async :parallelism do
|
|
51
51
|
|
52
52
|
end
|
53
53
|
|
54
|
-
# to call the value
|
55
|
-
|
54
|
+
# to call the value:
|
55
|
+
thr.value
|
56
56
|
|
57
57
|
```
|
58
58
|
|
@@ -68,74 +68,40 @@ Remember well that GarbageCollector will affect the speed.
|
|
68
68
|
|
69
69
|
```ruby
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
thr = async { sleep 3; 4 * 3 }
|
72
|
+
|
73
|
+
# to call the value:
|
74
|
+
calculation = thr.value
|
74
75
|
|
75
76
|
```
|
76
77
|
|
77
|
-
### Shared Memory
|
78
|
-
|
79
|
-
By default the last value will be returned (OS) in IO.pipe,
|
80
|
-
but when you need something else, there is the shared_memory!
|
81
|
-
|
82
|
-
Shared memory is good when you want make a ruby worked on native OS thread ,
|
83
|
-
but need to update data back at the mother process.
|
84
|
-
|
85
|
-
the usecase is simple like that:
|
86
|
-
```ruby
|
87
|
-
|
88
|
-
SharedMemory.anything_you_want_use_as_variable_name= {:some=>:object}
|
89
|
-
SharedMemory.anything_you_want_use_as_variable_name #> {:some=>:object}
|
90
|
-
|
91
|
-
# or
|
92
|
-
|
93
|
-
shared_memory.anything_you_want_use_as_variable_name #> {:some=>:object}
|
94
|
-
|
95
|
-
```
|
96
|
-
|
97
|
-
by default i set the memory allocation to 16Mb because it common usecase to me (MongoDB),
|
98
|
-
but feel free to change!:
|
99
|
-
```ruby
|
100
|
-
|
101
|
-
Asynchronous.memory_allocation_size= 1024 #INT!
|
102
|
-
|
103
|
-
```
|
104
|
-
|
105
|
-
## making shared memory obj static (constant)
|
106
|
-
|
107
|
-
you can set a shared memory obj to be static if you dont want it to be changed later on
|
108
|
-
```ruby
|
109
|
-
shared_memory.test_value= Array.new.push(:something)
|
110
|
-
Asynchronous.static_variables.push :test_value
|
111
|
-
shared_memory.test_value= Array.new #> this wont happen
|
112
|
-
```
|
113
|
-
|
114
|
-
|
115
78
|
### Example
|
116
79
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
# you CANT modify the objects in memory only in sharedmemories,
|
122
|
-
# the normal variables will only be copy on write modify
|
123
|
-
# This is ideal for big operations where you need do a big process
|
124
|
-
# w/o the fear of the Garbage collector slowness or the GIL lock
|
125
|
-
# when you need to update objects in the memory use SharedMemory
|
126
|
-
#
|
127
|
-
# Remember! if the hardware only got 1 cpu, it will be like a harder
|
128
|
-
# to use concurrency with an expensive memory allocation
|
129
|
-
calculation = async :OS do
|
80
|
+
you can use simple :p or :parallelism as nametag
|
81
|
+
remember :parallelism is all about real OS thread case,
|
82
|
+
so you CANT modify the objects in the memory,
|
83
|
+
the normal variables will only be copy on write modify
|
130
84
|
|
131
|
-
|
132
|
-
|
85
|
+
This is ideal for big operations where you need do a big process
|
86
|
+
w/o the fear of the Garbage collector slowness or the GIL lock
|
87
|
+
when you need to update objects in the memory use SharedMemory
|
133
88
|
|
134
|
-
|
89
|
+
Remember! if the hardware only got 1 cpu, it will be like a harder
|
90
|
+
to use concurrency with an expensive memory allocation
|
135
91
|
|
136
|
-
|
92
|
+
```ruby
|
137
93
|
|
138
|
-
|
94
|
+
thr = async :OS do
|
95
|
+
|
96
|
+
sleep 4
|
97
|
+
4 * 5
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
calculation = thr.value
|
102
|
+
calculation += 1
|
103
|
+
|
104
|
+
puts calculation
|
139
105
|
|
140
106
|
```
|
141
107
|
|
@@ -145,32 +111,15 @@ there are other examples that you can check in the exampels folder
|
|
145
111
|
### known bugs
|
146
112
|
|
147
113
|
In rare case when you get object_buffer error
|
148
|
-
* use .
|
114
|
+
* use .join method on the async variable
|
149
115
|
|
150
116
|
```ruby
|
151
|
-
calculation = async :OS do
|
152
|
-
sleep 4
|
153
|
-
4 * 5
|
154
|
-
end
|
155
117
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
SharedMemory objects not updating on chain method obj manipulation
|
164
|
-
|
165
|
-
```ruby
|
166
|
-
shared_memory.var= {'jobs'=>[]}
|
118
|
+
thr = async :OS do
|
119
|
+
sleep 4
|
120
|
+
4 * 5
|
121
|
+
end
|
122
|
+
|
123
|
+
thr.join #> thr
|
167
124
|
|
168
|
-
|
169
|
-
|
170
|
-
workaround is like that:
|
171
|
-
|
172
|
-
local_variable= {'jobs'=>[]}
|
173
|
-
local_variable['jobs'].push('data')
|
174
|
-
|
175
|
-
shared_memory.var= local_variable
|
176
|
-
```
|
125
|
+
```
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
4.0.0.pre
|
data/asynchronous.gemspec
CHANGED
data/examples/async_patterns.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# Require Gemfile gems
|
2
|
-
require_relative
|
2
|
+
require_relative 'bootstrap'
|
3
3
|
|
4
4
|
# you can use simple :c also instead of :concurrency
|
5
5
|
# remember :concurrency is all about GIL case, so
|
6
6
|
# you can modify the objects in memory
|
7
7
|
# This is ideal for little operations in simultaneously or
|
8
8
|
# when you need to update objects in the memory
|
9
|
-
|
9
|
+
thr1 = async :concurrency do
|
10
10
|
|
11
11
|
sleep 2
|
12
12
|
4 * 2
|
@@ -14,22 +14,24 @@ calculation = async :concurrency do
|
|
14
14
|
end
|
15
15
|
puts "hello concurrency"
|
16
16
|
|
17
|
-
|
17
|
+
calculation1 = thr1.value
|
18
|
+
calculation1 += 1
|
18
19
|
|
19
|
-
puts
|
20
|
+
puts calculation1
|
20
21
|
|
21
22
|
#>--------------------------------------------------
|
22
23
|
# or you can use simple {} without sym and this will be by default a
|
23
24
|
# :concurrency pattern
|
24
25
|
|
25
|
-
|
26
|
+
thr2 = async { sleep 3; 4 * 3 }
|
26
27
|
|
27
28
|
puts "hello simple concurrency"
|
28
29
|
|
29
|
-
|
30
|
+
calculation2 = thr2.value
|
31
|
+
calculation2 += 1
|
30
32
|
|
31
33
|
# remember you have to use to cal the return value from the code block!
|
32
|
-
puts
|
34
|
+
puts calculation2
|
33
35
|
|
34
36
|
|
35
37
|
#>--------------------------------------------------
|
@@ -41,7 +43,7 @@ puts calculation
|
|
41
43
|
# This is ideal for big operations where you need do a big process
|
42
44
|
# w/o the fear of the Garbage collector slowness or the GIL lock
|
43
45
|
# when you need to update objects in the memory use SharedMemory
|
44
|
-
|
46
|
+
thr3 = async :parallelism do
|
45
47
|
|
46
48
|
sleep 4
|
47
49
|
4 * 5
|
@@ -49,16 +51,17 @@ calculation = async :parallelism do
|
|
49
51
|
end
|
50
52
|
puts "hello parallelism"
|
51
53
|
|
52
|
-
|
54
|
+
calculation3 = thr3.value
|
55
|
+
calculation3 += 1
|
53
56
|
|
54
|
-
puts
|
57
|
+
puts calculation3
|
55
58
|
|
56
59
|
#>--------------------------------------------------
|
57
60
|
|
58
61
|
# more complex way
|
59
62
|
|
60
63
|
puts "mixed usecase with arrays as return obj"
|
61
|
-
|
64
|
+
thr4 = async :parallelism do
|
62
65
|
|
63
66
|
sleep 4
|
64
67
|
# some big database processing brutal memory eater stuff
|
@@ -66,10 +69,10 @@ calc1 = async :parallelism do
|
|
66
69
|
|
67
70
|
end
|
68
71
|
|
69
|
-
|
72
|
+
thr5 = async {
|
70
73
|
[5+1,"sup!"]
|
71
74
|
}
|
72
75
|
|
73
|
-
puts calc1 ==
|
74
|
-
puts (
|
76
|
+
puts 'calc1 is eql calc2:',thr4.value == thr5.value
|
77
|
+
puts (thr4.value+thr5.value).inspect
|
75
78
|
|
data/examples/no_zombie_test.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require_relative
|
1
|
+
require_relative 'bootstrap'
|
2
2
|
|
3
|
-
|
3
|
+
thr = async :parallelism do
|
4
4
|
|
5
5
|
# Zombie!
|
6
6
|
loop do
|
7
7
|
sleep 1
|
8
|
+
puts "brains(#{$$})"
|
8
9
|
end
|
9
10
|
# inf loop
|
10
11
|
#
|
@@ -13,12 +14,14 @@ end
|
|
13
14
|
|
14
15
|
puts $$
|
15
16
|
Thread.new do
|
17
|
+
|
16
18
|
sleep 5
|
17
19
|
|
18
20
|
# this want to demonstrate that,
|
19
21
|
# if the main process is killed,
|
20
22
|
# you wont leave zombies behind!
|
21
23
|
system "kill -9 #{$$}"
|
24
|
+
|
22
25
|
end
|
23
26
|
|
24
27
|
loop do
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'bootstrap'
|
2
|
+
|
3
|
+
async1= async :OS do
|
4
|
+
1000000*5
|
5
|
+
end
|
6
|
+
|
7
|
+
async2= async :OS do
|
8
|
+
|
9
|
+
var = ("!" * 1000000)
|
10
|
+
puts "the superHuge String length in the pipe is: #{var.length}"
|
11
|
+
|
12
|
+
var
|
13
|
+
end
|
14
|
+
|
15
|
+
async2_error= async :OS do
|
16
|
+
|
17
|
+
raise(SystemExit)
|
18
|
+
puts 'never happen, to system error happened!'
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
async3= async :OS do
|
23
|
+
1000000*5.0
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
async2_error.value
|
28
|
+
rescue Exception => ex
|
29
|
+
puts "\n",'when error happen:',ex
|
30
|
+
end
|
31
|
+
|
32
|
+
puts "\n",'result length based on string form:'
|
33
|
+
puts async1.value.to_s.length
|
34
|
+
puts async2.value.to_s.length
|
35
|
+
puts async3.value.to_s.length
|
data/lib/async.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'asynchronous'
|
data/lib/asynchronous.rb
CHANGED
@@ -1,12 +1,7 @@
|
|
1
1
|
#encoding: UTF-8
|
2
2
|
module Asynchronous
|
3
|
-
|
4
|
-
require '
|
5
|
-
|
6
|
-
require
|
7
|
-
require File.join(File.dirname(__FILE__),"asynchronous","concurrency")
|
8
|
-
require File.join(File.dirname(__FILE__),"asynchronous","parallelism")
|
9
|
-
require File.join(File.dirname(__FILE__),"asynchronous","shared_memory")
|
10
|
-
require File.join(File.dirname(__FILE__),"asynchronous","kernel")
|
11
|
-
|
3
|
+
require 'asynchronous/error'
|
4
|
+
require 'asynchronous/concurrency'
|
5
|
+
require 'asynchronous/parallelism'
|
6
|
+
require 'asynchronous/kernel'
|
12
7
|
end
|
@@ -1,78 +1,44 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
1
|
+
# you can use simple :c also instead of :concurrency
|
2
|
+
# remember :concurrency is all about GIL case, so
|
3
|
+
# you can modify the objects in memory
|
4
|
+
# This is ideal for little operations in simultaneously or
|
5
|
+
# when you need to update objects in the memory
|
6
|
+
class Asynchronous::Concurrency
|
7
|
+
|
8
|
+
def initialize(&block)
|
9
|
+
|
10
|
+
@rescue_state= nil
|
11
|
+
@try_count = 0
|
12
|
+
|
13
|
+
begin
|
14
|
+
@value= nil
|
15
|
+
@thread ||= ::Thread.new { block.call }
|
16
|
+
@rescue_state= nil
|
17
|
+
rescue ThreadError
|
18
|
+
@rescue_state ||= true
|
19
|
+
@try_count += 1
|
20
|
+
if 3 <= @try_count
|
21
|
+
@value= block.call
|
16
22
|
@rescue_state= nil
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
if 3 <= @try_count
|
21
|
-
@value= callable.call
|
22
|
-
@rescue_state= nil
|
23
|
-
else
|
24
|
-
sleep 5
|
25
|
-
retry
|
26
|
-
end
|
23
|
+
else
|
24
|
+
sleep 5
|
25
|
+
retry
|
27
26
|
end
|
28
27
|
end
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
if @value.nil?
|
33
|
-
until @rescue_state.nil?
|
34
|
-
sleep 1
|
35
|
-
end
|
36
|
-
@value= @thread.value
|
37
|
-
end
|
38
|
-
|
39
|
-
return @value
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
def asynchronous_set_value(obj)
|
44
|
-
@value= obj
|
45
|
-
end
|
46
|
-
alias :asynchronous_set_value= :asynchronous_set_value
|
47
|
-
|
48
|
-
def synchronize
|
49
|
-
asynchronous_get_value
|
50
|
-
end
|
51
|
-
alias :sync :synchronize
|
52
|
-
|
53
|
-
def method_missing(method, *args)
|
54
|
-
|
55
|
-
new_value= asynchronous_get_value
|
56
|
-
|
57
|
-
begin
|
58
|
-
original_value= new_value.dup
|
59
|
-
rescue ::TypeError
|
60
|
-
original_value= new_value
|
61
|
-
end
|
29
|
+
end
|
62
30
|
|
63
|
-
|
64
|
-
|
65
|
-
|
31
|
+
def join
|
32
|
+
if @value.nil?
|
33
|
+
until @rescue_state.nil?
|
34
|
+
sleep 1
|
66
35
|
end
|
67
|
-
|
68
|
-
return return_value
|
69
|
-
|
36
|
+
@value= @thread.value
|
70
37
|
end
|
38
|
+
end
|
71
39
|
|
72
|
-
|
73
|
-
|
74
|
-
#end
|
75
|
-
|
40
|
+
def value
|
41
|
+
join; @value
|
76
42
|
end
|
77
43
|
|
78
44
|
end
|