ease_engine 0.0.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +25 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +4 -0
  5. data/README.md +33 -0
  6. data/Rakefile +1 -0
  7. data/benchmark/echo/echo_client.rb +90 -0
  8. data/benchmark/echo/echo_packet.rb +9 -0
  9. data/benchmark/echo/echo_server.rb +48 -0
  10. data/benchmark/fps.rb +23 -0
  11. data/benchmark/http.rb +9 -0
  12. data/benchmark/loop/Makefile +39 -0
  13. data/benchmark/loop/Makefile.rb +11 -0
  14. data/benchmark/loop/Rakefile +42 -0
  15. data/benchmark/loop/loop.c +38 -0
  16. data/benchmark/loop/loop.cs +33 -0
  17. data/benchmark/loop/loop.go +33 -0
  18. data/benchmark/loop/loop.js +23 -0
  19. data/benchmark/loop/loop.php +22 -0
  20. data/benchmark/loop/loop.rb +19 -0
  21. data/benchmark/loop/loop.scala +30 -0
  22. data/benchmark/loop/loop_c +0 -0
  23. data/benchmark/loop/loop_cs +0 -0
  24. data/benchmark/loop/loop_go +0 -0
  25. data/benchmark/measure/measure_client.rb +76 -0
  26. data/benchmark/measure/measure_server.rb +47 -0
  27. data/benchmark/process.rb +3 -0
  28. data/benchmark/tcp/tcp_client.rb +45 -0
  29. data/benchmark/tcp/tcp_server.rb +40 -0
  30. data/benchmark/udp/udp_client.rb +84 -0
  31. data/benchmark/udp/udp_packet.rb +40 -0
  32. data/benchmark/udp/udp_server.rb +33 -0
  33. data/bin/console +14 -0
  34. data/bin/setup +7 -0
  35. data/ease_engine.gemspec +27 -0
  36. data/lib/ease_engine.rb +35 -0
  37. data/lib/ease_engine/application.rb +269 -0
  38. data/lib/ease_engine/buffer.rb +25 -0
  39. data/lib/ease_engine/data.rb +158 -0
  40. data/lib/ease_engine/frame.rb +38 -0
  41. data/lib/ease_engine/http.rb +42 -0
  42. data/lib/ease_engine/log.rb +109 -0
  43. data/lib/ease_engine/measure.rb +25 -0
  44. data/lib/ease_engine/packet.rb +150 -0
  45. data/lib/ease_engine/platform.rb +19 -0
  46. data/lib/ease_engine/process.rb +31 -0
  47. data/lib/ease_engine/socket.rb +174 -0
  48. data/lib/ease_engine/time.rb +22 -0
  49. data/lib/ease_engine/timer.rb +72 -0
  50. data/lib/ease_engine/version.rb +3 -0
  51. data/lib/ease_engine/watcher.rb +95 -0
  52. data/types/Rakefile +83 -0
  53. data/types/csharp/EaseEngine.cs +39 -0
  54. data/types/csharp/EaseEngine/Buffer.cs +49 -0
  55. data/types/csharp/EaseEngine/Measure.cs +47 -0
  56. data/types/csharp/EaseEngine/Time.cs +41 -0
  57. data/types/csharp/EaseEngine/Version.cs +7 -0
  58. data/types/csharp/Unity/Assets/Menu.cs +56 -0
  59. data/types/csharp/Unity/Assets/Menu.unity +0 -0
  60. metadata +158 -0
@@ -0,0 +1,33 @@
1
+ require "ease_engine"
2
+ require "./udp_packet"
3
+
4
+ class BenchmarkApplication < EaseEngine::Application
5
+ def on_start
6
+ super
7
+
8
+ @is_update = true
9
+ EaseEngine::Frame.fps = 60
10
+
11
+ host = ARGV[ 0 ]
12
+ port = ARGV[ 1 ].to_i
13
+
14
+ udp_socket = EaseEngine::UDPSocket.new
15
+ udp_socket.bind( host, port )
16
+ add_socket( udp_socket )
17
+
18
+ EE_LOG_DBG.call "host=#{host} port=#{port}"
19
+ end
20
+
21
+ def on_update
22
+ if 1000000 <= @measure.check
23
+ EE_LOG_DBG.call "watcher.size=#{@watcher.size} update_usec=#{@measure.update_usec} count=#{@measure.count}"
24
+
25
+ @measure.start
26
+ end
27
+ end
28
+
29
+ def on_read_socket( socket, packet )
30
+ write_packet( socket, packet, 0 )
31
+ end
32
+ end
33
+ BenchmarkApplication::run
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ease_engine"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ease_engine/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ease_engine"
8
+ spec.version = EaseEngine::VERSION
9
+ spec.authors = ["liveralmask"]
10
+ spec.email = ["liveralmask.lisk@gmail.com"]
11
+ spec.license = "MIT"
12
+
13
+ spec.summary = %q{Easy application programming scripts.}
14
+ spec.description = %q{Easy application programming scripts.}
15
+ spec.homepage = "https://github.com/liveralmask/ease_engine"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.9"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+
25
+ spec.add_dependency "cool.io"
26
+ spec.add_dependency "msgpack"
27
+ end
@@ -0,0 +1,35 @@
1
+ require "ease_engine/version"
2
+ require "ease_engine/application"
3
+
4
+ module EaseEngine
5
+ def self.assert( result, *args )
6
+ if ! result
7
+ args = [ "Assert" ] if 0 == args.length
8
+ raise sprintf( *args )
9
+ end
10
+ end
11
+
12
+ def self.rotate( min, max, value, add )
13
+ return min if value < min || max < value
14
+
15
+ value += add
16
+ ( value < min || max < value ) ? min : value
17
+ end
18
+
19
+ def self.trace_info( trace = 0 )
20
+ trace = caller[ trace ] if ! trace.instance_of?( String )
21
+
22
+ info = {
23
+ :file => "",
24
+ :line => 0,
25
+ :method => "",
26
+ }
27
+ if /^(.+?):(\d+)(?::in `(.*)')?/ =~ trace
28
+ info[ :file ] = $1
29
+ info[ :line ] = $2.to_i
30
+ info[ :method ] = $3
31
+ end
32
+ info[ :str ] = "#{info[ :file ]}:#{info[ :line ]} #{info[ :method ]}"
33
+ info
34
+ end
35
+ end
@@ -0,0 +1,269 @@
1
+ require "ease_engine/measure"
2
+ require "ease_engine/frame"
3
+ require "ease_engine/watcher"
4
+ require "ease_engine/packet"
5
+ require "ease_engine/log"
6
+ require "ease_engine/http"
7
+ require "ease_engine/process"
8
+ require "ease_engine/platform"
9
+ require "ease_engine/timer"
10
+
11
+ module EaseEngine
12
+ class Application
13
+ def self.run( options = {} )
14
+ EaseEngine::Log.inf( "EaseEngine #{EaseEngine::VERSION} options=#{options}" )
15
+ application = new( options )
16
+ begin
17
+ application.on_start
18
+ rescue => err
19
+ application.on_error( err )
20
+
21
+ application.is_update = false
22
+ end
23
+
24
+ while application.is_update
25
+ begin
26
+ EaseEngine::Frame.update{|sleep_time_usec, sleep_time_f|
27
+ application.watcher.watch( sleep_time_f )
28
+ }
29
+ application.timer.update
30
+ application.socket_timer.update
31
+ application.on_update
32
+ rescue => err
33
+ application.on_error( err )
34
+ end
35
+ end
36
+
37
+ begin
38
+ application.on_end
39
+ rescue => err
40
+ application.on_error( err )
41
+ end
42
+
43
+ application.exit_status
44
+ end
45
+
46
+ attr_accessor :options
47
+ attr_accessor :exit_status, :is_update
48
+ attr_accessor :watcher, :measure
49
+ attr_accessor :timer, :socket_timer
50
+ attr_accessor :is_daemon
51
+
52
+ def initialize( options )
53
+ @options = options
54
+ if ! @options.key?( :watcher )
55
+ @options[ :watcher ] = {}
56
+ end
57
+ if ! @options.key?( :timer )
58
+ @options[ :timer ] = {}
59
+ end
60
+ if ! @options.key?( :socket_timer )
61
+ @options[ :socket_timer ] = {
62
+ :connect_timeout_usec => 10000000,
63
+ :connected_timeout_usec => 10000000,
64
+ }
65
+ end
66
+ @options[ :is_daemon ] = false if ! @options.key?( :is_daemon )
67
+
68
+ @exit_status = 0
69
+ @is_update = false
70
+
71
+ @watcher = EaseEngine::Watcher.new( @options[ :watcher ] )
72
+ @measure = EaseEngine::Measure.new
73
+ @timer = EaseEngine::Timer.new( @options[ :timer ] )
74
+ @socket_timer = EaseEngine::Timer.new( @options[ :socket_timer ] )
75
+
76
+ @is_daemon = @options[ :is_daemon ]
77
+ end
78
+
79
+ def on_start
80
+ trap( :INT ){
81
+ @is_update = false
82
+ @exit_status = :INT
83
+ }
84
+
85
+ trap( :TERM ){
86
+ @is_update = false
87
+ @exit_status = :TERM
88
+ }
89
+
90
+ trap( :PIPE ){}
91
+ end
92
+
93
+ def on_update
94
+ end
95
+
96
+ def on_end
97
+ @watcher.each{|info|
98
+ @watcher.remove( info.io )
99
+ }
100
+ end
101
+
102
+ def on_accept_socket( socket )
103
+ accepted_socket = socket.accept
104
+ if ! socket.err.nil?
105
+ on_error_socket( socket )
106
+ return
107
+ end
108
+
109
+ add_socket( accepted_socket )
110
+ on_accepted_socket( accepted_socket, socket )
111
+ end
112
+
113
+ def on_accepted_socket( accepted_socket, server_socket )
114
+ end
115
+
116
+ def on_connected_socket( socket )
117
+ end
118
+
119
+ def on_read_socket( socket, packet )
120
+ end
121
+
122
+ def on_close_socket( socket )
123
+ end
124
+
125
+ def on_timeout_socket( socket )
126
+ EaseEngine::Log.wrn( "on_timeout_socket #{socket}" )
127
+ end
128
+
129
+ def on_error_socket( socket )
130
+ EaseEngine::Log.err( "on_error_socket #{socket} #{socket.err.class.name}: #{socket.err}\n#{socket.err.backtrace}" )
131
+ end
132
+
133
+ def on_error( err )
134
+ EaseEngine::Log.err( "on_error #{err.class.name}: #{err}\n#{err.backtrace}" )
135
+ end
136
+
137
+ def add_server_socket( socket )
138
+ application = self
139
+ @watcher.add( socket, {
140
+ :on_read => Proc.new{|socket|
141
+ application.on_accept_socket( socket )
142
+ },
143
+ :on_remove => Proc.new{|socket|
144
+ application.close_socket( socket )
145
+ }
146
+ })
147
+ end
148
+
149
+ def add_socket( socket )
150
+ application = self
151
+ @watcher.add( socket, {
152
+ :on_read => Proc.new{|socket|
153
+ application.read_socket( socket )
154
+ },
155
+ :on_remove => Proc.new{|socket|
156
+ application.close_socket( socket )
157
+ }
158
+ })
159
+ end
160
+
161
+ def add_connect_socket( socket )
162
+ application = self
163
+ @watcher.add( socket, {
164
+ :on_read => Proc.new{|socket|
165
+ socket.err = SystemCallError.new( socket.errno )
166
+ application.on_error_socket( socket )
167
+ application.remove_socket( socket )
168
+ },
169
+ :on_write => Proc.new{|socket|
170
+ application.remove_socket_timer( socket.to_i )
171
+
172
+ socket.err = nil
173
+ application.add_socket( socket )
174
+ application.on_connected_socket( socket )
175
+
176
+ if socket.is_heartbeat
177
+ # connected timeout
178
+ hash = {
179
+ :socket => socket,
180
+ :timeout_usec => @options[ :socket_timer ][ :connected_timeout_usec ],
181
+ }
182
+ hash[ :callback ] = Proc.new{|hash|
183
+ if hash[ :socket ].is_timeout
184
+ application.timeout_socket( hash[ :socket ] )
185
+ next
186
+ end
187
+
188
+ hash[ :socket ].is_timeout = true
189
+ application.write_packet( socket, EaseEngine::HeartbeatBeginPacket.new )
190
+ application.add_socket_timer( hash[ :socket ].to_i, hash[ :timeout_usec ], hash, hash[ :callback ] )
191
+ }
192
+ hash[ :callback ].call( hash )
193
+ end
194
+ },
195
+ :on_remove => Proc.new{|socket|
196
+ application.close_socket( socket )
197
+ }
198
+ })
199
+
200
+ # connect timeout
201
+ add_socket_timer( socket.to_i, @options[ :socket_timer ][ :connect_timeout_usec ], socket, Proc.new{|socket|
202
+ application.timeout_socket( socket )
203
+ })
204
+ end
205
+
206
+ def remove_socket( socket )
207
+ @watcher.remove( socket )
208
+ end
209
+
210
+ def read_socket( socket )
211
+ Packet.creates( socket ).each{|packet|
212
+ case packet.packet_name
213
+ when "EaseEngine.HeartbeatBeginPacket"
214
+ write_packet( socket, EaseEngine::HeartbeatEndPacket.new )
215
+ when "EaseEngine.HeartbeatEndPacket"
216
+ else
217
+ on_read_socket( socket, packet )
218
+ end
219
+ }
220
+ check_socket( socket )
221
+ end
222
+
223
+ def write_packet( socket, packet, flags = 0, *args )
224
+ packet.write( socket, flags, *args )
225
+ end
226
+
227
+ def reflect_socket( socket, recv_flags = 0, send_flags = 0 )
228
+ buf = socket.recv( socket.read_max_size, recv_flags )
229
+ if ! buf.empty?
230
+ result = socket.send( buf, send_flags )
231
+ return if result == buf.length
232
+ EaseEngine::Log.err( "reflect_socket #{result} != #{buf.length}" ) if 0 < result && result != buf.length
233
+ end
234
+ check_socket( socket )
235
+ end
236
+
237
+ def check_socket( socket )
238
+ on_error_socket( socket ) if ! socket.err.nil?
239
+ remove_socket( socket ) if socket.is_disable
240
+ end
241
+
242
+ def timeout_socket( socket )
243
+ on_timeout_socket( socket )
244
+ remove_socket( socket )
245
+ end
246
+
247
+ def close_socket( socket )
248
+ remove_socket_timer( socket.to_i )
249
+ on_close_socket( socket )
250
+ socket.close
251
+ end
252
+
253
+ def add_timer( group_id, timeout_usec, arg, callback )
254
+ @timer.add( group_id, timeout_usec, arg, callback )
255
+ end
256
+
257
+ def remove_timer( group_id, timer_id = 0 )
258
+ @timer.remove( group_id, timer_id )
259
+ end
260
+
261
+ def add_socket_timer( socket_id, timeout_usec, arg, callback )
262
+ @socket_timer.add( socket_id, timeout_usec, arg, callback )
263
+ end
264
+
265
+ def remove_socket_timer( socket_id, timer_id = 0 )
266
+ @socket_timer.remove( socket_id, timer_id )
267
+ end
268
+ end
269
+ end
@@ -0,0 +1,25 @@
1
+ module EaseEngine
2
+ class Buffer
3
+ attr_accessor :value, :size
4
+
5
+ def initialize( value = "" )
6
+ @value = value
7
+ @size = value.length
8
+ end
9
+
10
+ def <<( value )
11
+ if ! value.empty?
12
+ @value << value
13
+ @size += value.length
14
+ end
15
+ @value
16
+ end
17
+
18
+ def >>( size )
19
+ return "" if size <= 0
20
+
21
+ @size -= size
22
+ @value.slice!( 0, size )
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,158 @@
1
+ module EaseEngine
2
+ module Data
3
+ class Hary
4
+ class Info
5
+ attr_accessor :id, :index, :data
6
+
7
+ def initialize( id, index, data )
8
+ @id = id
9
+ @index = index
10
+ @data = data
11
+ end
12
+ end
13
+
14
+ def initialize
15
+ @ary = []
16
+ @indexes = {}
17
+ end
18
+
19
+ def add( id, data )
20
+ if ! @indexes.key?( id )
21
+ info = Info.new( id, @ary.size, data )
22
+ @ary.push info
23
+ @indexes[ id ] = info.index
24
+ else
25
+ info = @ary[ @indexes[ id ] ]
26
+ info.id = id
27
+ info.data = data
28
+ end
29
+
30
+ sort!
31
+ id
32
+ end
33
+
34
+ def remove( id )
35
+ remove_at( @indexes[ id ] ) if @indexes.key?( id )
36
+ end
37
+
38
+ def remove_at( index )
39
+ return nil if @ary.size <= index
40
+
41
+ info = @ary[ index ]
42
+ @ary.delete_at( index )
43
+ @indexes.delete( info.id )
44
+ update if index != @ary.size # 末尾データの削除なら、更新しない
45
+ info.data
46
+ end
47
+
48
+ def get( id )
49
+ @indexes[ id ]
50
+ end
51
+
52
+ def get_at( index )
53
+ ( @ary.size <= index ) ? nil : @ary[ index ]
54
+ end
55
+
56
+ def key?( id )
57
+ @indexes.key?( id )
58
+ end
59
+
60
+ def size
61
+ @ary.size
62
+ end
63
+
64
+ def each
65
+ @ary.each{|info|
66
+ yield info.id, info.index, info.data
67
+ }
68
+ end
69
+
70
+ def update
71
+ @ary.each_with_index{|info, index|
72
+ info.index = index
73
+ @indexes[ info.id ] = index
74
+ }
75
+ end
76
+
77
+ def sort!
78
+ update
79
+ end
80
+ end
81
+
82
+ class Record < Hary
83
+ def initialize( min, max )
84
+ @min = min
85
+ @max = max
86
+ @id = min
87
+
88
+ super()
89
+ end
90
+
91
+ def add( data )
92
+ @id = generate_id( @id )
93
+ return 0 if 0 == @id
94
+
95
+ super( @id, data )
96
+ end
97
+
98
+ protected
99
+ def generate_id( id )
100
+ generated_id = 0
101
+ start_id = id
102
+ begin
103
+ generated_id = id if ! key?( id )
104
+
105
+ id = EaseEngine::rotate( @min, @max, id, 1 )
106
+ end while 0 == generated_id && start_id != id
107
+ generated_id
108
+ end
109
+ end
110
+
111
+ class Group
112
+ def initialize
113
+ @group = {}
114
+ @data = {}
115
+ end
116
+
117
+ def add( group_id, data_id )
118
+ if @group.key?( group_id )
119
+ @group[ group_id ][ data_id ] = group_id
120
+ else
121
+ @group[ group_id ] = {
122
+ data_id => group_id
123
+ }
124
+ end
125
+
126
+ if @data.key?( data_id )
127
+ @data[ data_id ][ group_id ] = data_id
128
+ else
129
+ @data[ data_id ] = {
130
+ group_id => data_id
131
+ }
132
+ end
133
+ end
134
+
135
+ def remove( group_id, data_id )
136
+ if @group.key?( group_id )
137
+ @group[ group_id ].each{|data_id, group_id|
138
+ @data.delete( data_id )
139
+ }
140
+ @group.delete( group_id )
141
+ elsif @data.key?( data_id )
142
+ @data[ data_id ].each{|group_id, data_id|
143
+ @group[ group_id ].delete( data_id )
144
+ }
145
+ @data.delete( data_id )
146
+ end
147
+ end
148
+
149
+ def group( group_id )
150
+ @group.key?( group_id ) ? @group[ group_id ] : {}
151
+ end
152
+
153
+ def data( data_id )
154
+ @data.key?( data_id ) ? @data[ data_id ] : {}
155
+ end
156
+ end
157
+ end
158
+ end