asynchronous 2.1.0 → 3.0.0.pre.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 +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
|