asynchronous 2.1.0 → 3.0.0.pre.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Gemfile.lock +9 -1
- data/README.md +37 -7
- data/VERSION +1 -1
- data/asynchronous.gemspec +2 -0
- data/dump/shared_memory.rb +138 -0
- data/examples/array_of_value_with_native_threads.rb +6 -14
- data/examples/async_patterns.rb +9 -9
- data/examples/{shared_memory.rb → shared_memory1.rb} +0 -0
- data/examples/shared_memory2.rb +29 -0
- data/lib/asynchronous.rb +1 -0
- data/lib/asynchronous/clean_class.rb +4 -9
- data/lib/asynchronous/concurrency.rb +26 -22
- data/lib/asynchronous/kernel.rb +3 -1
- data/lib/asynchronous/parallelism.rb +84 -96
- data/lib/asynchronous/shared_memory.rb +100 -21
- metadata +21 -7
- data/test/test.rb +0 -0
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MzI1NjQ3MTczMjQ3YjNhNThlNjY4ZDZiMjA0MmI0MWNiYzgxODJlNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjAyZTNlNDYwZWY5NTJlOWViMWFmYTYzYjY3ZmEwNWQ5NmJhNWNkMg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YjZjY2FiOWY3YzFmNjk0ZDRhNjVjZmQwYzc1NjdiOWEwMzVkZmI3MWY3NTg1
|
10
|
+
NDFkM2E5Njg2ZGZkMjQ0MjBmZmU1YTliYTk0MTc0YzEyYTZmZmU0MGJlNzM0
|
11
|
+
OWE4ZTdmMzIxNTViM2VkNzc0YzljNWJkOTg2Mzk5OTE5NTljZDE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
Y2Y1MmY4NGRkMTJlYzU2NGU4ZjJhODNkMTNiMjEwNDQ4Y2QxYTc2YWZiNjg4
|
14
|
+
YzM2NDc4ZjM0Njk5MTE5YzFjMDg4NGNlOWViM2VmNGU3MWMzZDliODY5OGJi
|
15
|
+
ZjcwNWQ0ODc2YmIxMjcwZjBhNDY3NjMwZDNhODM0MGI5YjgyZTk=
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
asynchronous (
|
4
|
+
asynchronous (2.1.0)
|
5
5
|
process_shared
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
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)
|
10
17
|
ffi (1.9.3)
|
11
18
|
process_shared (0.2.0)
|
12
19
|
ffi (~> 1.0)
|
@@ -16,3 +23,4 @@ PLATFORMS
|
|
16
23
|
|
17
24
|
DEPENDENCIES
|
18
25
|
asynchronous!
|
26
|
+
debugger
|
data/README.md
CHANGED
@@ -52,7 +52,7 @@ calculation = async :parallelism do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# to call the value (syncronize):
|
55
|
-
calculation
|
55
|
+
calculation
|
56
56
|
|
57
57
|
```
|
58
58
|
|
@@ -70,7 +70,7 @@ Remember well that GarbageCollector will affect the speed.
|
|
70
70
|
|
71
71
|
calculation= async { sleep 3; 4 * 3 }
|
72
72
|
# to call the value (syncronize):
|
73
|
-
calculation
|
73
|
+
calculation
|
74
74
|
|
75
75
|
```
|
76
76
|
|
@@ -98,11 +98,21 @@ by default i set the memory allocation to 16Mb because it common usecase to me (
|
|
98
98
|
but feel free to change!:
|
99
99
|
```ruby
|
100
100
|
|
101
|
-
Asynchronous
|
101
|
+
Asynchronous.memory_allocation_size= 1024 #INT!
|
102
102
|
|
103
103
|
```
|
104
104
|
|
105
|
-
##
|
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
|
+
### Example
|
106
116
|
|
107
117
|
```ruby
|
108
118
|
|
@@ -123,10 +133,30 @@ calculation = async :OS do
|
|
123
133
|
|
124
134
|
end
|
125
135
|
|
126
|
-
calculation
|
136
|
+
calculation += 1
|
137
|
+
|
138
|
+
puts calculation
|
139
|
+
|
140
|
+
```
|
141
|
+
|
127
142
|
|
128
|
-
|
143
|
+
there are other examples that you can check in the exampels folder
|
129
144
|
|
145
|
+
### known bugs
|
146
|
+
|
147
|
+
In rare case when you get object_buffer error
|
148
|
+
* use .sync method on the async variable
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
calculation = async :OS do
|
152
|
+
sleep 4
|
153
|
+
4 * 5
|
154
|
+
end
|
155
|
+
|
156
|
+
calculation.sync #> or synchronize
|
130
157
|
```
|
131
158
|
|
132
|
-
|
159
|
+
Kernel holding on Native threads with pipes can choke up
|
160
|
+
* direct sleep commands can do this on multiple native threads
|
161
|
+
** hard processing load not like that, only kernel sleep
|
162
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.0.0-pre
|
data/asynchronous.gemspec
CHANGED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'process_shared'
|
2
|
+
require_relative "clean_class"
|
3
|
+
module Asynchronous
|
4
|
+
|
5
|
+
|
6
|
+
module Allocation
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :memory_allocation_size
|
10
|
+
end
|
11
|
+
|
12
|
+
self.memory_allocation_size= 16384
|
13
|
+
|
14
|
+
def self.mutex
|
15
|
+
@@mutex
|
16
|
+
end
|
17
|
+
|
18
|
+
@@mutex = ProcessShared::Mutex.new
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
class SharedMemory < CleanClass
|
24
|
+
class << self
|
25
|
+
def method_missing(method, *args)
|
26
|
+
|
27
|
+
::Asynchronous::Allocation.mutex.synchronize do
|
28
|
+
if method.to_s.include?('=')
|
29
|
+
begin
|
30
|
+
self.class_variable_get("@@#{method.to_s.sub('=','')}").write_object(args[0])
|
31
|
+
rescue ::NameError
|
32
|
+
self.class_variable_set(
|
33
|
+
"@@#{method.to_s.sub('=','')}",
|
34
|
+
::ProcessShared::SharedMemory.new( ::Asynchronous::Allocation.memory_allocation_size )
|
35
|
+
)
|
36
|
+
self.class_variable_get("@@#{method.to_s.sub('=','')}").write_object(args[0])
|
37
|
+
end
|
38
|
+
else
|
39
|
+
begin
|
40
|
+
self.class_variable_get("@@#{method.to_s}").read_object
|
41
|
+
rescue ::NameError
|
42
|
+
return nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
SharedMemory ||= Asynchronous::SharedMemory
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
=begin
|
59
|
+
|
60
|
+
|
61
|
+
# The C void type; only useful for function return types
|
62
|
+
:void => Type::VOID,
|
63
|
+
|
64
|
+
# C boolean type
|
65
|
+
:bool => Type::BOOL,
|
66
|
+
|
67
|
+
# C nul-terminated string
|
68
|
+
:string => Type::STRING,
|
69
|
+
|
70
|
+
# C signed char
|
71
|
+
:char => Type::CHAR,
|
72
|
+
# C unsigned char
|
73
|
+
:uchar => Type::UCHAR,
|
74
|
+
|
75
|
+
# C signed short
|
76
|
+
:short => Type::SHORT,
|
77
|
+
# C unsigned short
|
78
|
+
:ushort => Type::USHORT,
|
79
|
+
|
80
|
+
# C signed int
|
81
|
+
:int => Type::INT,
|
82
|
+
# C unsigned int
|
83
|
+
:uint => Type::UINT,
|
84
|
+
|
85
|
+
# C signed long
|
86
|
+
:long => Type::LONG,
|
87
|
+
|
88
|
+
# C unsigned long
|
89
|
+
:ulong => Type::ULONG,
|
90
|
+
|
91
|
+
# C signed long long integer
|
92
|
+
:long_long => Type::LONG_LONG,
|
93
|
+
|
94
|
+
# C unsigned long long integer
|
95
|
+
:ulong_long => Type::ULONG_LONG,
|
96
|
+
|
97
|
+
# C single precision float
|
98
|
+
:float => Type::FLOAT,
|
99
|
+
|
100
|
+
# C double precision float
|
101
|
+
:double => Type::DOUBLE,
|
102
|
+
|
103
|
+
# C long double
|
104
|
+
:long_double => Type::LONGDOUBLE,
|
105
|
+
|
106
|
+
# Native memory address
|
107
|
+
:pointer => Type::POINTER,
|
108
|
+
|
109
|
+
# 8 bit signed integer
|
110
|
+
:int8 => Type::INT8,
|
111
|
+
# 8 bit unsigned integer
|
112
|
+
:uint8 => Type::UINT8,
|
113
|
+
|
114
|
+
# 16 bit signed integer
|
115
|
+
:int16 => Type::INT16,
|
116
|
+
# 16 bit unsigned integer
|
117
|
+
:uint16 => Type::UINT16,
|
118
|
+
|
119
|
+
# 32 bit signed integer
|
120
|
+
:int32 => Type::INT32,
|
121
|
+
# 32 bit unsigned integer
|
122
|
+
:uint32 => Type::UINT32,
|
123
|
+
|
124
|
+
# 64 bit signed integer
|
125
|
+
:int64 => Type::INT64,
|
126
|
+
# 64 bit unsigned integer
|
127
|
+
:uint64 => Type::UINT64,
|
128
|
+
|
129
|
+
:buffer_in => Type::BUFFER_IN,
|
130
|
+
:buffer_out => Type::BUFFER_OUT,
|
131
|
+
:buffer_inout => Type::BUFFER_INOUT,
|
132
|
+
|
133
|
+
# Used in function prototypes to indicate the arguments are variadic
|
134
|
+
:varargs => Type::VARARGS,
|
135
|
+
|
136
|
+
|
137
|
+
=end
|
138
|
+
|
@@ -1,31 +1,23 @@
|
|
1
1
|
require_relative "../lib/asynchronous"
|
2
2
|
|
3
|
-
async1= async :OS do
|
4
3
|
|
4
|
+
async1= async :OS do
|
5
5
|
1000000*5
|
6
|
-
|
7
6
|
end
|
8
7
|
|
9
8
|
async2= async :OS do
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
"sup" * 10000
|
14
|
-
|
10
|
+
var = ("sup" * 1000000)
|
11
|
+
puts "the superHuge String length in the pipe is: #{var.length}"
|
15
12
|
|
13
|
+
var
|
16
14
|
end
|
17
15
|
|
18
16
|
|
19
17
|
async3= async :OS do
|
20
|
-
|
21
18
|
1000000*5.0
|
22
|
-
|
23
19
|
end
|
24
20
|
|
25
|
-
|
26
|
-
# Marshal String can take up time if you have big Strings like
|
27
|
-
# "sup" * 100000000
|
21
|
+
puts async1
|
28
22
|
|
29
|
-
puts async1
|
30
|
-
async2.value[0..5],
|
31
|
-
async3.value
|
23
|
+
puts [ async3, async2[0..5], async1 ]
|
data/examples/async_patterns.rb
CHANGED
@@ -14,9 +14,9 @@ calculation = async :concurrency do
|
|
14
14
|
end
|
15
15
|
puts "hello concurrency"
|
16
16
|
|
17
|
-
calculation
|
17
|
+
calculation += 1
|
18
18
|
|
19
|
-
puts calculation
|
19
|
+
puts calculation
|
20
20
|
|
21
21
|
#>--------------------------------------------------
|
22
22
|
# or you can use simple {} without sym and this will be by default a
|
@@ -26,10 +26,10 @@ calculation = async { sleep 3; 4 * 3 }
|
|
26
26
|
|
27
27
|
puts "hello simple concurrency"
|
28
28
|
|
29
|
-
calculation
|
29
|
+
calculation += 1
|
30
30
|
|
31
|
-
# remember you have to use
|
32
|
-
puts calculation
|
31
|
+
# remember you have to use to cal the return value from the code block!
|
32
|
+
puts calculation
|
33
33
|
|
34
34
|
|
35
35
|
#>--------------------------------------------------
|
@@ -49,9 +49,9 @@ calculation = async :parallelism do
|
|
49
49
|
end
|
50
50
|
puts "hello parallelism"
|
51
51
|
|
52
|
-
calculation
|
52
|
+
calculation += 1
|
53
53
|
|
54
|
-
puts calculation
|
54
|
+
puts calculation
|
55
55
|
|
56
56
|
#>--------------------------------------------------
|
57
57
|
|
@@ -70,6 +70,6 @@ calc2 = async {
|
|
70
70
|
[5+1,"sup!"]
|
71
71
|
}
|
72
72
|
|
73
|
-
puts calc1
|
74
|
-
puts (calc1
|
73
|
+
puts calc1 == calc2
|
74
|
+
puts (calc1+calc2).inspect
|
75
75
|
|
File without changes
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "../lib/asynchronous"
|
2
|
+
|
3
|
+
shared_memory.test_value = Array.new
|
4
|
+
shared_memory.ready_state = Hash.new
|
5
|
+
times_value= 5
|
6
|
+
|
7
|
+
times_value.times do
|
8
|
+
|
9
|
+
# remember! IO pipes cant be made too fast!
|
10
|
+
# this does not mean the Shared memory cant handle the speed
|
11
|
+
|
12
|
+
var= async :OS do
|
13
|
+
|
14
|
+
shared_memory.test_value.push $$
|
15
|
+
shared_memory.ready_state[$$]= true
|
16
|
+
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
shared_memory.ready_state[var.asynchronous_get_pid] ||= false
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
while shared_memory.ready_state.values.include?(false)
|
25
|
+
sleep 0.5
|
26
|
+
end
|
27
|
+
|
28
|
+
puts shared_memory.test_value.inspect
|
29
|
+
puts "#{times_value} OS thread should made this much shared memory update: #{times_value} / and it's #{shared_memory.test_value.count}"
|
data/lib/asynchronous.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
module Asynchronous
|
3
3
|
|
4
4
|
require 'process_shared'
|
5
|
+
|
5
6
|
require File.join(File.dirname(__FILE__),"asynchronous","clean_class")
|
6
7
|
require File.join(File.dirname(__FILE__),"asynchronous","concurrency")
|
7
8
|
require File.join(File.dirname(__FILE__),"asynchronous","parallelism")
|
@@ -1,19 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# remove methods from the class!
|
4
|
-
#def self.purge_methods
|
1
|
+
module Asynchronous
|
2
|
+
class CleanClass < BasicObject
|
5
3
|
|
4
|
+
# remove methods from the class!
|
6
5
|
(self.instance_methods-[
|
7
|
-
:undef_method,
|
8
6
|
:object_id,
|
9
7
|
:__send__,
|
10
|
-
:methods,
|
11
8
|
:alias,
|
12
|
-
:new
|
13
9
|
]).each do |method|
|
14
10
|
undef_method method
|
15
11
|
end
|
16
12
|
|
17
|
-
|
18
|
-
|
13
|
+
end
|
19
14
|
end
|
@@ -5,9 +5,9 @@ module Asynchronous
|
|
5
5
|
# you can modify the objects in memory
|
6
6
|
# This is ideal for little operations in simultaneously or
|
7
7
|
# when you need to update objects in the memory
|
8
|
-
class Concurrency < CleanClass
|
8
|
+
class Concurrency < Asynchronous::CleanClass
|
9
9
|
|
10
|
-
def initialize
|
10
|
+
def initialize callable
|
11
11
|
begin
|
12
12
|
@value= nil
|
13
13
|
@try_count= 0
|
@@ -27,7 +27,7 @@ module Asynchronous
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
30
|
+
def asynchronous_get_value
|
31
31
|
|
32
32
|
if @value.nil?
|
33
33
|
until @rescue_state.nil?
|
@@ -40,35 +40,39 @@ module Asynchronous
|
|
40
40
|
|
41
41
|
end
|
42
42
|
|
43
|
-
def
|
43
|
+
def asynchronous_set_value(obj)
|
44
44
|
@value= obj
|
45
45
|
end
|
46
|
+
alias :asynchronous_set_value= :asynchronous_set_value
|
46
47
|
|
47
|
-
def
|
48
|
-
|
49
|
-
"#<Async running>"
|
50
|
-
else
|
51
|
-
value.inspect
|
52
|
-
end
|
48
|
+
def synchronize
|
49
|
+
asynchronous_get_value
|
53
50
|
end
|
51
|
+
alias :sync :synchronize
|
54
52
|
|
55
53
|
def method_missing(method, *args)
|
56
|
-
value.__send__(method, *args)
|
57
|
-
end
|
58
54
|
|
59
|
-
|
60
|
-
|
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
|
62
|
+
|
63
|
+
return_value= new_value.__send__(method,*args)
|
64
|
+
unless new_value == original_value
|
65
|
+
asynchronous_set_value new_value
|
66
|
+
end
|
67
|
+
|
68
|
+
return return_value
|
69
|
+
|
61
70
|
end
|
62
71
|
|
63
|
-
|
72
|
+
#def respond_to_missing?(method, include_private = false)
|
73
|
+
# value.respond_to?(method, include_private)
|
74
|
+
#end
|
64
75
|
|
65
|
-
# alias
|
66
|
-
begin
|
67
|
-
#alias :v :value
|
68
|
-
#alias :get :value
|
69
|
-
#alias :gets :value
|
70
|
-
#alias :response :value
|
71
|
-
#alias :return :value
|
72
76
|
end
|
73
77
|
|
74
78
|
end
|
data/lib/asynchronous/kernel.rb
CHANGED
@@ -12,7 +12,8 @@
|
|
12
12
|
#
|
13
13
|
module Kernel
|
14
14
|
|
15
|
-
def async
|
15
|
+
def async type= :VM ,&block
|
16
|
+
|
16
17
|
case type.to_s.downcase[0]
|
17
18
|
# Concurrency / VM / Green
|
18
19
|
when "c","v","g"
|
@@ -30,6 +31,7 @@ module Kernel
|
|
30
31
|
end
|
31
32
|
|
32
33
|
end
|
34
|
+
|
33
35
|
end
|
34
36
|
|
35
37
|
def shared_memory
|
@@ -7,127 +7,106 @@ module Asynchronous
|
|
7
7
|
# and only get the return value so you can do big works without the fear of the
|
8
8
|
# Garbage collector slowness or the GIL lock
|
9
9
|
# when you need to update objects in the memory use :concurrency
|
10
|
-
class Parallelism < CleanClass
|
10
|
+
class Parallelism < Asynchronous::CleanClass
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
def asynchronous_fork callable
|
13
|
+
return ::Kernel.fork do
|
14
14
|
|
15
|
-
@@pids ||= []
|
16
|
-
@@tmpdir ||= nil
|
17
|
-
@@motherpid ||= $$
|
18
|
-
@@agent ||= nil
|
19
|
-
@@zombie ||= true
|
20
|
-
::Kernel.require 'yaml'
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
# main def for logic
|
25
|
-
begin
|
26
|
-
def initialize callable
|
27
|
-
|
28
|
-
# defaults
|
29
15
|
begin
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
begin
|
40
|
-
::Kernel.trap("TERM") do
|
41
|
-
::Kernel.exit
|
42
|
-
end
|
43
|
-
::Thread.new do
|
44
|
-
::Kernel.loop do
|
45
|
-
begin
|
46
|
-
::Kernel.sleep 1
|
47
|
-
if alive?(@@motherpid) == false
|
48
|
-
::Kernel.exit!
|
49
|
-
end
|
50
|
-
end
|
16
|
+
::Kernel.trap("TERM") do
|
17
|
+
::Kernel.exit
|
18
|
+
end
|
19
|
+
::Thread.new do
|
20
|
+
::Kernel.loop do
|
21
|
+
begin
|
22
|
+
::Kernel.sleep 1
|
23
|
+
if ::Asynchronous::Parallelism.asynchronous_alive?(@@motherpid) == false
|
24
|
+
::Kernel.exit
|
51
25
|
end
|
52
26
|
end
|
53
27
|
end
|
28
|
+
end
|
29
|
+
end
|
54
30
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
#::Kernel.puts callable.class
|
59
|
-
|
60
|
-
return_value= callable.call
|
61
|
-
|
62
|
-
@rd.close
|
31
|
+
@comm_line[0].close
|
32
|
+
@comm_line[1].write ::Marshal.dump(callable.call)
|
33
|
+
@comm_line[1].flush
|
63
34
|
|
64
|
-
|
65
|
-
|
35
|
+
#::Kernel.loop do
|
36
|
+
# #::Kernel.puts @comm_line[0].closed?
|
37
|
+
# #::Kernel.puts @comm_line[1].closed?
|
38
|
+
# ::Kernel.sleep 1
|
39
|
+
#end
|
66
40
|
|
67
|
-
@wr.close
|
68
41
|
|
69
|
-
|
70
|
-
|
42
|
+
end
|
43
|
+
end
|
71
44
|
|
72
|
-
|
73
|
-
|
45
|
+
def asynchronous_read_buffer
|
46
|
+
@read_buffer = ::Thread.new do
|
47
|
+
while !@comm_line[0].eof?
|
48
|
+
@value = ::Marshal.load(@comm_line[0])
|
74
49
|
end
|
75
|
-
|
76
50
|
end
|
77
51
|
end
|
78
52
|
|
79
|
-
# connection for in case of mother die
|
80
|
-
begin
|
81
53
|
|
82
|
-
|
83
|
-
begin
|
84
|
-
::Process.kill(0,pid)
|
85
|
-
return true
|
86
|
-
rescue ::Errno::ESRCH
|
87
|
-
return false
|
88
|
-
end
|
89
|
-
end
|
54
|
+
def initialize callable
|
90
55
|
|
91
|
-
|
56
|
+
@@pids ||= []
|
57
|
+
@@motherpid ||= $$
|
92
58
|
|
93
|
-
|
94
|
-
|
59
|
+
@comm_line = ::IO.pipe
|
60
|
+
@value = nil
|
61
|
+
@read_buffer = nil
|
95
62
|
|
96
|
-
|
63
|
+
asynchronous_read_buffer
|
64
|
+
@pid= asynchronous_fork callable
|
65
|
+
@@pids.push(@pid)
|
97
66
|
|
98
|
-
|
67
|
+
end
|
99
68
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
# #sleep 1
|
104
|
-
#end
|
69
|
+
def asynchronous_get_pid
|
70
|
+
return @pid
|
71
|
+
end
|
105
72
|
|
106
|
-
|
107
|
-
|
108
|
-
|
73
|
+
def self.asynchronous_alive?(pid)
|
74
|
+
begin
|
75
|
+
::Process.kill(0,pid)
|
76
|
+
return true
|
77
|
+
rescue ::Errno::ESRCH
|
78
|
+
return false
|
79
|
+
end
|
80
|
+
end
|
109
81
|
|
110
|
-
|
111
|
-
return_value= ::YAML.load(return_value)
|
82
|
+
def asynchronous_get_value
|
112
83
|
|
113
|
-
|
114
|
-
@value= return_value
|
84
|
+
if @value.nil?
|
115
85
|
|
116
|
-
|
86
|
+
::Process.wait(@pid, ::Process::WNOHANG )
|
117
87
|
|
118
|
-
|
88
|
+
@comm_line[1].close
|
89
|
+
@read_buffer.join
|
90
|
+
@comm_line[0].close
|
119
91
|
|
120
92
|
end
|
121
93
|
|
122
|
-
|
123
|
-
@value= obj
|
124
|
-
end
|
94
|
+
return @value
|
125
95
|
|
126
96
|
end
|
127
97
|
|
98
|
+
def asynchronous_set_value(obj)
|
99
|
+
@value= obj
|
100
|
+
end
|
101
|
+
alias :asynchronous_set_value= :asynchronous_set_value
|
102
|
+
|
103
|
+
def synchronize
|
104
|
+
asynchronous_get_value
|
105
|
+
end
|
106
|
+
alias :sync :synchronize
|
107
|
+
|
128
108
|
# kill kidos at Kernel Exit
|
129
|
-
|
130
|
-
::Kernel.at_exit {
|
109
|
+
::Kernel.at_exit {
|
131
110
|
@@pids.each { |pid|
|
132
111
|
begin
|
133
112
|
::Process.kill(:TERM, pid)
|
@@ -136,16 +115,25 @@ module Asynchronous
|
|
136
115
|
end
|
137
116
|
}
|
138
117
|
}
|
139
|
-
end
|
140
118
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
119
|
+
def method_missing(method, *args)
|
120
|
+
|
121
|
+
return_value= nil
|
122
|
+
new_value= asynchronous_get_value
|
123
|
+
begin
|
124
|
+
original_value= new_value.dup
|
125
|
+
rescue ::TypeError
|
126
|
+
original_value= new_value
|
127
|
+
end
|
128
|
+
return_value= new_value.__send__(method,*args)
|
129
|
+
unless new_value == original_value
|
130
|
+
asynchronous_set_value new_value
|
131
|
+
end
|
132
|
+
|
133
|
+
return return_value
|
134
|
+
|
148
135
|
end
|
149
136
|
|
137
|
+
|
150
138
|
end
|
151
139
|
end
|
@@ -1,15 +1,16 @@
|
|
1
|
-
require 'process_shared'
|
2
|
-
require_relative "clean_class"
|
3
1
|
module Asynchronous
|
4
2
|
|
3
|
+
class << self
|
4
|
+
attr_accessor :global_mutex
|
5
|
+
end
|
6
|
+
self.global_mutex = false
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
8
|
+
class << self
|
9
|
+
attr_accessor :memory_allocation_size
|
10
|
+
end
|
11
|
+
self.memory_allocation_size= 16384
|
11
12
|
|
12
|
-
|
13
|
+
module Global
|
13
14
|
|
14
15
|
def self.mutex
|
15
16
|
@@mutex
|
@@ -20,34 +21,112 @@ module Asynchronous
|
|
20
21
|
end
|
21
22
|
|
22
23
|
|
23
|
-
class
|
24
|
+
class MemoryObj < Asynchronous::CleanClass
|
25
|
+
|
26
|
+
@data = nil
|
27
|
+
@mutex = nil
|
28
|
+
|
29
|
+
def initialize(obj)
|
30
|
+
|
31
|
+
@data= ::ProcessShared::SharedMemory.new(
|
32
|
+
::Asynchronous.memory_allocation_size)
|
33
|
+
|
34
|
+
@mutex= ::ProcessShared::Mutex.new
|
35
|
+
|
36
|
+
@data.write_object(obj)
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
def asynchronous_set_value obj
|
41
|
+
return @data.write_object obj
|
42
|
+
end
|
43
|
+
|
44
|
+
def asynchronous_set_value= obj
|
45
|
+
self.asynchronous_set_value(obj)
|
46
|
+
end
|
47
|
+
|
48
|
+
def asynchronous_get_value
|
49
|
+
return @data.read_object
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def method_missing(method, *args, &block)
|
54
|
+
|
55
|
+
#::Kernel.puts "method: #{method}, #{args}, #{block}"
|
56
|
+
|
57
|
+
new_value= nil
|
58
|
+
original_value= nil
|
59
|
+
return_value= nil
|
60
|
+
mutex_obj= nil
|
61
|
+
|
62
|
+
if ::Asynchronous.global_mutex == true
|
63
|
+
mutex_obj= ::Asynchronous::Global.mutex
|
64
|
+
else
|
65
|
+
mutex_obj= @mutex
|
66
|
+
end
|
67
|
+
|
68
|
+
mutex_obj.synchronize do
|
69
|
+
|
70
|
+
new_value= asynchronous_get_value
|
71
|
+
|
72
|
+
begin
|
73
|
+
original_value= new_value.dup
|
74
|
+
rescue ::TypeError
|
75
|
+
original_value= new_value
|
76
|
+
end
|
77
|
+
|
78
|
+
return_value= new_value.__send__(method,*args,&block)
|
79
|
+
unless new_value == original_value
|
80
|
+
asynchronous_set_value new_value
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
return return_value
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
class SharedMemory < Asynchronous::CleanClass
|
24
92
|
class << self
|
25
93
|
def method_missing(method, *args)
|
26
94
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
95
|
+
case true
|
96
|
+
|
97
|
+
when method.to_s.include?('=')
|
98
|
+
|
99
|
+
@@static_variables ||= ::Asynchronous::MemoryObj.new(Array.new.push(:static_variables))
|
100
|
+
if @@static_variables.include?(method.to_s.sub!('=','').to_sym)
|
101
|
+
$stdout.puts "Warning! static varieble cant be changed without removing from the Asynchronous.static_variables array collection (sym)"
|
102
|
+
return nil
|
103
|
+
else
|
104
|
+
|
105
|
+
begin
|
106
|
+
self.class_variable_get("@@#{method.to_s.sub('=','')}").asynchronous_set_value= args[0]
|
107
|
+
rescue ::NameError
|
108
|
+
self.class_variable_set(
|
109
|
+
"@@#{method.to_s.sub('=','')}",
|
110
|
+
::Asynchronous::MemoryObj.new(args[0]))
|
111
|
+
end
|
112
|
+
|
37
113
|
end
|
114
|
+
|
38
115
|
else
|
39
116
|
begin
|
40
|
-
self.class_variable_get("@@#{method.to_s}")
|
117
|
+
self.class_variable_get("@@#{method.to_s}")
|
41
118
|
rescue ::NameError
|
42
119
|
return nil
|
43
120
|
end
|
44
|
-
end
|
45
121
|
end
|
46
122
|
|
47
123
|
end
|
48
124
|
end
|
49
125
|
end
|
50
126
|
|
127
|
+
def self.static_variables
|
128
|
+
SharedMemory.static_variables
|
129
|
+
end
|
51
130
|
|
52
131
|
end
|
53
132
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asynchronous
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0.pre.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Luzsi
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ! '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: debugger
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
description: ! 'DSL for for dead simple to use asynchronous patterns in both VM managed
|
28
42
|
and OS managed way (Concurrency and Parallelism) '
|
29
43
|
email:
|
@@ -39,10 +53,12 @@ files:
|
|
39
53
|
- VERSION
|
40
54
|
- asynchronous.gemspec
|
41
55
|
- dump/async.rb
|
56
|
+
- dump/shared_memory.rb
|
42
57
|
- examples/array_of_value_with_native_threads.rb
|
43
58
|
- examples/async_patterns.rb
|
44
59
|
- examples/no_zombie_test.rb
|
45
|
-
- examples/
|
60
|
+
- examples/shared_memory1.rb
|
61
|
+
- examples/shared_memory2.rb
|
46
62
|
- files.rb
|
47
63
|
- lib/asynchronous.rb
|
48
64
|
- lib/asynchronous/clean_class.rb
|
@@ -50,7 +66,6 @@ files:
|
|
50
66
|
- lib/asynchronous/kernel.rb
|
51
67
|
- lib/asynchronous/parallelism.rb
|
52
68
|
- lib/asynchronous/shared_memory.rb
|
53
|
-
- test/test.rb
|
54
69
|
homepage: https://github.com/adamluzsi/asynchronous
|
55
70
|
licenses: []
|
56
71
|
metadata: {}
|
@@ -65,15 +80,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
65
80
|
version: '0'
|
66
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
82
|
requirements:
|
68
|
-
- - ! '
|
83
|
+
- - ! '>'
|
69
84
|
- !ruby/object:Gem::Version
|
70
|
-
version:
|
85
|
+
version: 1.3.1
|
71
86
|
requirements: []
|
72
87
|
rubyforge_project:
|
73
88
|
rubygems_version: 2.2.1
|
74
89
|
signing_key:
|
75
90
|
specification_version: 4
|
76
91
|
summary: Simple Async Based on standard CRuby
|
77
|
-
test_files:
|
78
|
-
- test/test.rb
|
92
|
+
test_files: []
|
79
93
|
has_rdoc:
|
data/test/test.rb
DELETED
File without changes
|