asynchronous 3.0.1 → 4.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ class Asynchronous::Error < StandardError
2
+
3
+ attr_reader :wrapped_error
4
+ def initialize(wrapped_error)
5
+ @wrapped_error= wrapped_error
6
+ end
7
+
8
+ end
@@ -10,32 +10,33 @@
10
10
  # "some awsome ruby code here!"
11
11
  # end
12
12
  #
13
- module Kernel
13
+ module Asynchronous::DCI
14
14
 
15
- def async type= :VM ,&block
15
+ extend self
16
16
 
17
+ def async(type= :VM, &block)
17
18
  case type.to_s.downcase[0]
19
+
18
20
  # Concurrency / VM / Green
19
- when "c","v","g"
20
- begin
21
- Asynchronous::Concurrency.new(block)
22
- end
21
+ when *%W[ c v g ]
22
+ ::Asynchronous::Concurrency.new(&block)
23
+
23
24
  # Parallelism / OS / Native
24
- when "p","o","n"
25
- begin
26
- Asynchronous::Parallelism.new(block)
27
- end
25
+ when *%W[ p o n ]
26
+ ::Asynchronous::Parallelism.new(&block)
27
+
28
28
  else
29
- begin
30
- Asynchronous::Concurrency.new(block)
31
- end
29
+ ::Asynchronous::Concurrency.new(&block)
32
30
 
33
31
  end
34
-
35
32
  end
36
33
 
37
- def shared_memory
38
- Asynchronous::SharedMemory
39
- end unless method_defined? :shared_memory
34
+ end
35
+
36
+ Kernel.class_eval do
37
+
38
+ def async(type=nil, &block)
39
+ ::Asynchronous::DCI.async(type, &block)
40
+ end
40
41
 
41
42
  end
@@ -1,139 +1,135 @@
1
- module Asynchronous
2
- # now let's see the Parallelism
3
- # you can use simple :p also instead of :parallelism
4
- # remember :parallelism is all about real OS thread case, so
5
- # you CANT modify the objects in memory only copy on write modify
6
- # This is ideal for big operations where you need do a big process
7
- # and only get the return value so you can do big works without the fear of the
8
- # Garbage collector slowness or the GIL lock
9
- # when you need to update objects in the memory use :concurrency
10
- class Parallelism < Asynchronous::CleanClass
11
-
12
- @@pids ||= []
13
- @@motherpid ||= $$
14
-
15
- def asynchronous_fork callable
16
- return ::Kernel.fork do
1
+ # now let's see the Parallelism
2
+ # you can use simple :p also instead of :parallelism
3
+ # remember :parallelism is all about real OS thread case, so
4
+ # you CANT modify the objects in memory only copy on write modify
5
+ # This is ideal for big operations where you need do a big process
6
+ # and only get the return value so you can do big works without the fear of the
7
+ # Garbage collector slowness or the GIL lock
8
+ # when you need to update objects in the memory use :concurrency
9
+ class Asynchronous::Parallelism
17
10
 
18
- begin
19
- ::Kernel.trap("TERM") do
20
- ::Kernel.exit
21
- end
22
- ::Thread.new do
23
- ::Kernel.loop do
24
- begin
25
- ::Kernel.sleep 1
26
- if ::Asynchronous::Parallelism.asynchronous_alive?(@@motherpid) == false
27
- ::Kernel.exit
28
- end
29
- end
30
- end
31
- end
32
- end
11
+ attr_reader :pid
33
12
 
34
- @comm_line[0].close
35
- @comm_line[1].write ::Marshal.dump(callable.call)
36
- @comm_line[1].flush
13
+ @@pids ||= []
14
+ @@motherpid ||= $$
37
15
 
38
- #::Kernel.loop do
39
- # #::Kernel.puts @comm_line[0].closed?
40
- # #::Kernel.puts @comm_line[1].closed?
41
- # ::Kernel.sleep 1
42
- #end
16
+ def initialize(disable_gc=true,&callable)
43
17
 
18
+ @disable_gc = !!disable_gc
44
19
 
45
- end
46
- end
20
+ @comm_line = ::IO.pipe
47
21
 
48
- def asynchronous_read_buffer
49
- @read_buffer = ::Thread.new do
50
- while !@comm_line[0].eof?
51
- @value = ::Marshal.load(@comm_line[0])
52
- end
53
- end
54
- end
22
+ @value = nil
23
+ @read_buffer = nil
24
+
25
+ read_buffer
55
26
 
27
+ @pid = fork(&callable)
28
+ @@pids.push(@pid)
56
29
 
57
- def initialize callable
30
+ end
58
31
 
59
- @comm_line = ::IO.pipe
60
- @value = nil
61
- @read_buffer = nil
32
+ def self.alive?(pid)
33
+ ::Process.kill(0, pid)
34
+ return true
35
+ rescue ::Errno::ESRCH
36
+ return false
37
+ end
62
38
 
63
- asynchronous_read_buffer
64
- @pid= asynchronous_fork callable
65
- @@pids.push(@pid)
39
+ def join
40
+ if @value.nil?
66
41
 
67
- end
42
+ ::Process.wait(@pid, ::Process::WNOHANG)
68
43
 
69
- def asynchronous_get_pid
70
- return @pid
71
- end
44
+ @comm_line[1].close
45
+ @read_buffer.join
46
+ @comm_line[0].close
72
47
 
73
- def self.asynchronous_alive?(pid)
74
- begin
75
- ::Process.kill(0,pid)
76
- return true
77
- rescue ::Errno::ESRCH
78
- return false
48
+ if @value.is_a?(::Asynchronous::Error)
49
+ raise(@value.wrapped_error)
79
50
  end
80
- end
81
51
 
82
- def asynchronous_get_value
52
+ end; self
53
+ end
83
54
 
84
- if @value.nil?
55
+ def value
56
+ join; @value
57
+ end
85
58
 
86
- ::Process.wait(@pid, ::Process::WNOHANG )
59
+ protected
87
60
 
88
- @comm_line[1].close
89
- @read_buffer.join
90
- @comm_line[0].close
61
+ def pipe_read
62
+ @comm_line[0]
63
+ end
91
64
 
92
- end
65
+ def pipe_write
66
+ @comm_line[1]
67
+ end
93
68
 
94
- return @value
69
+ def fork(&block)
70
+ return ::Kernel.fork do
95
71
 
96
- end
72
+ GC.disable if @disable_gc
97
73
 
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
-
108
- # kill kidos at Kernel Exit
109
- ::Kernel.at_exit {
110
- @@pids.each { |pid|
111
- begin
112
- ::Process.kill(:TERM, pid)
113
- rescue ::Errno::ESRCH, ::Errno::ECHILD
114
- #::STDOUT.puts "`kill': No such process (Errno::ESRCH)"
74
+ begin
75
+ ::Kernel.trap("TERM") do
76
+ ::Kernel.exit
77
+ end
78
+ ::Thread.new do
79
+ ::Kernel.loop do
80
+ begin
81
+ ::Kernel.sleep 1
82
+ if ::Asynchronous::Parallelism.alive?(@@motherpid) == false
83
+ ::Kernel.exit!
84
+ end
85
+ end
115
86
  end
116
- }
117
- }
87
+ end
88
+ end
118
89
 
119
- def method_missing(method, *args)
90
+ @comm_line[0].close
120
91
 
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
92
+ result = begin
93
+ block.call
94
+ rescue ::Exception => ex
95
+ ::Asynchronous::Error.new(ex)
127
96
  end
128
- return_value= new_value.__send__(method,*args)
129
- unless new_value == original_value
130
- asynchronous_set_value new_value
131
- end
132
97
 
133
- return return_value
98
+ dumped_result = ::Marshal.dump(result).to_s
99
+
100
+ @comm_line[1].write(dumped_result)
101
+ ::Kernel.sleep(dumped_result.length.to_f*0.005)
102
+
103
+ @comm_line[1].flush
104
+ @comm_line[1].close
134
105
 
135
106
  end
107
+ end
136
108
 
109
+ def read_buffer
110
+ @read_buffer = ::Thread.new do
111
+ while !@comm_line[0].eof?
137
112
 
113
+ begin
114
+ @value = ::Marshal.load(@comm_line[0])
115
+ rescue ::ArgumentError => ex
116
+ sleep(1)
117
+ retry if ex.respond_to?(:message) && ex.message =~ /marshal data too short/i
118
+ end
119
+
120
+ end
121
+ end
138
122
  end
123
+
124
+ # kill kidos at Kernel Exit
125
+ ::Kernel.at_exit do
126
+ @@pids.each do |pid|
127
+ begin
128
+ ::Process.kill(:TERM, pid)
129
+ rescue ::Errno::ESRCH, ::Errno::ECHILD
130
+ #::STDOUT.puts "`kill': No such process (Errno::ESRCH)"
131
+ end
132
+ end
133
+ end
134
+
139
135
  end
metadata CHANGED
@@ -1,44 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asynchronous
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 4.0.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Luzsi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-17 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: process_shared
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ! '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ! '>='
25
- - !ruby/object:Gem::Version
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'
41
- description: ! 'DSL for for dead simple to use asynchronous patterns in both VM managed
11
+ date: 2015-06-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: 'DSL for for dead simple to use asynchronous patterns in both VM managed
42
14
  and OS managed way (Concurrency and Parallelism) '
43
15
  email:
44
16
  - adamluzsi@gmail.com
@@ -52,21 +24,17 @@ files:
52
24
  - Rakefile
53
25
  - VERSION
54
26
  - asynchronous.gemspec
55
- - dump/async.rb
56
- - dump/shared_memory.rb
57
- - examples/array_of_value_with_native_threads.rb
58
27
  - examples/async_patterns.rb
28
+ - examples/bootstrap.rb
59
29
  - examples/no_zombie_test.rb
60
- - examples/ruby_worker.rb
61
- - examples/shared_memory1.rb
62
- - examples/shared_memory2.rb
30
+ - examples/parallelism.rb
63
31
  - files.rb
32
+ - lib/async.rb
64
33
  - lib/asynchronous.rb
65
- - lib/asynchronous/clean_class.rb
66
34
  - lib/asynchronous/concurrency.rb
35
+ - lib/asynchronous/error.rb
67
36
  - lib/asynchronous/kernel.rb
68
37
  - lib/asynchronous/parallelism.rb
69
- - lib/asynchronous/shared_memory.rb
70
38
  homepage: https://github.com/adamluzsi/asynchronous
71
39
  licenses: []
72
40
  metadata: {}
@@ -76,19 +44,18 @@ require_paths:
76
44
  - lib
77
45
  required_ruby_version: !ruby/object:Gem::Requirement
78
46
  requirements:
79
- - - ! '>='
47
+ - - ">="
80
48
  - !ruby/object:Gem::Version
81
49
  version: '0'
82
50
  required_rubygems_version: !ruby/object:Gem::Requirement
83
51
  requirements:
84
- - - ! '>='
52
+ - - ">"
85
53
  - !ruby/object:Gem::Version
86
- version: '0'
54
+ version: 1.3.1
87
55
  requirements: []
88
56
  rubyforge_project:
89
- rubygems_version: 2.2.1
57
+ rubygems_version: 2.2.2
90
58
  signing_key:
91
59
  specification_version: 4
92
60
  summary: Simple Async Based on standard CRuby
93
61
  test_files: []
94
- has_rdoc:
@@ -1,4 +0,0 @@
1
- #encoding: UTF-8
2
- module Asynchronous
3
- require 'asynchronous'
4
- end
@@ -1,138 +0,0 @@
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
-