murasaki 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0acb7462bef6b0277cbfdfbb84ba90f3394158df
4
- data.tar.gz: 1ea68e3f5bc60ac1af1df69f7c1c250414a67f21
3
+ metadata.gz: 9ecdeb71724f0d1efe13027d3acee86a7575b1f4
4
+ data.tar.gz: 4523b9a2b5ebb11f93002b3190d360bc8ac667e3
5
5
  SHA512:
6
- metadata.gz: dfb808c62ad84b2ebde6088251a95d092800c0937b7fa8d9022dcbc0e98af00ce5491befc66f99fdfda3cb1f0b25b9cfd2a9c8f73fd8267699c9479e46fc71e1
7
- data.tar.gz: f1070c1e11587753a49c0bfc54ba2d91f4078dd716fa31080c65d3d3b539953c708ff14f981cc1857a256f51777dc6fe2ce0d04f99a088b7a06c3fa468b569ce
6
+ metadata.gz: ed8ca771ea23774b154477690d892ae658861fe929c42511357249468a562a5a598f005ae90f0b6798dc88d292ee6c948e815c2d52a0154b74cb05079bead52a
7
+ data.tar.gz: 81e4529da54237d5fe8dbe536c86eaca74c99055c60f781fe9aac6247728babeed2ac8ce19dedca4653db62390e59d7ecd88340b5cde2adf3dd4ee4bdb4d20e4
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+
7
+ [*.rb]
8
+ indent_style = space
9
+ indent_size = 2
@@ -0,0 +1,7 @@
1
+ require 'fiber'
2
+ require 'nio'
3
+
4
+ require_relative 'murasaki/version'
5
+ require_relative 'murasaki/event_loop'
6
+ require_relative 'murasaki/timer'
7
+ require_relative 'murasaki/promise'
@@ -0,0 +1,118 @@
1
+ ##
2
+ # EventLoop Module, providing main loop for events
3
+ module EventLoop
4
+ class << self
5
+ # Config EvnetLoop, call by default if any other methods called
6
+ # @param [NIO::Selector] selector an event selector
7
+ def config(selector = NIO::Selector.new)
8
+ # Raw NIO Selector
9
+ @selector = selector
10
+ # Array of active timers
11
+ @timers = []
12
+ # Hash of io and its callback
13
+ @ios = Hash.new
14
+ # IO queue
15
+ @queue = Hash.new
16
+ end
17
+
18
+ # Add timer in event loop
19
+ # @param [EventLoop::Timer] timer timer to insert
20
+ # @return [nil] nil
21
+ def add_timer(timer)
22
+ config if @selector.nil?
23
+ timer.start_time = Time.now.to_f + timer.time
24
+ @timers << timer
25
+ nil
26
+ end
27
+
28
+ # Register I/O event with queue protection
29
+ # @param [IO] io io to register
30
+ # @param [Symbol] interest :r for read only, :w for write only, and :rw for both
31
+ # @yield what to run when io callbacks
32
+ # @return [nil] nil
33
+ def register(io, interest=(:rw), &callback)
34
+ config if @selector.nil?
35
+ if @queue[io.to_i].nil?
36
+ @queue[io.to_i] = Array.new
37
+ register_raw(io, interest, callback)
38
+ else
39
+ @queue[io.to_i] << [io, interest, callback]
40
+ end
41
+ nil
42
+ end
43
+
44
+ # Register I/O event directly, without any queue protection
45
+ # @param [IO] io io to register
46
+ # @param [Symbol] interest :r for read only, :w for write only, and :rw for both
47
+ # @param [Proc] callback what to run when io callbacks
48
+ # @return [nil] nil
49
+ def register_raw(io, interest=(:rw), callback)
50
+ config if @selector.nil?
51
+ @selector.register(io, interest)
52
+ @ios[io] = { callback: callback }
53
+ nil
54
+ end
55
+
56
+ # Deregister I/O event
57
+ # @param [IO] io io to deregister
58
+ # @return [nil] nil
59
+ def deregister(io)
60
+ fd = io.to_i
61
+ @selector.deregister(io)
62
+ @ios.delete(io)
63
+ next_register = @queue[fd].shift
64
+ next_register.nil? ? @queue.delete(fd) : register_raw(*next_register)
65
+ nil
66
+ end
67
+
68
+ # Run I/O selector once
69
+ # @return [nil] nil
70
+ def run_once
71
+ config if @selector.nil?
72
+ @selector.select(0.2) do |monitor| # Timeout for 0.2 secs
73
+ @ios[monitor.io][:callback].call(monitor)
74
+ end
75
+ timer_once
76
+ nil
77
+ end
78
+
79
+ # Run timer once
80
+ # @return [nil] nil
81
+ def timer_once
82
+ config if @selector.nil?
83
+ now_time = Time.now.to_f
84
+ @timers.delete_if do |timer|
85
+ if timer.start_time < now_time
86
+ timer.callback.call
87
+ true
88
+ end
89
+ end
90
+ nil
91
+ end
92
+
93
+ # Start the event loop
94
+ # @return [nil] nil
95
+ def start
96
+ return if running?
97
+ @stop = false
98
+ until @stop
99
+ run_once
100
+ end
101
+ @stop = nil
102
+ end
103
+
104
+ # Set the stop flag
105
+ # @return [nil] nil
106
+ def stop
107
+ @stop = true
108
+ nil
109
+ end
110
+
111
+ # Detect the stop flag
112
+ # @return [Boolean] return if eventloop is set to be stopped
113
+ def running?
114
+ @stop = true if @stop.nil?
115
+ !@stop
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,70 @@
1
+ ##
2
+ # Meta-programming String for Syntactic Sugars
3
+ # Referenced from {Qiita}[http://qiita.com/south37/items/99a60345b22ef395d424]
4
+ class Promise
5
+ # Init a Promise
6
+ # @param [Proc] callback an async method
7
+ def initialize(&callback)
8
+ @callback = callback
9
+ end
10
+
11
+ # Define what to do after a method callbacks
12
+ # @param [Proc] resolve what on callback
13
+ # @return [nil] nil
14
+ def then(&resolve)
15
+ @callback.call(resolve)
16
+ end
17
+ end
18
+
19
+ module Kernel
20
+ # Make fiber as async chain
21
+ # @param [Fiber] fiber root of async chain
22
+ def async_fiber(fiber)
23
+ chain = proc do |result|
24
+ next unless result.is_a? Promise
25
+ result.then do |val|
26
+ chain.call(fiber.resume(val))
27
+ end
28
+ end
29
+ chain.call(fiber.resume)
30
+ end
31
+
32
+ # Define an async method
33
+ # @param [Symbol] method method name
34
+ # @yield async method
35
+ # @example
36
+ # async :hello do
37
+ # puts 'Hello'
38
+ # end
39
+ def async(method)
40
+ define_singleton_method method do |*args|
41
+ async_fiber(Fiber.new {yield(*args)})
42
+ end
43
+ end
44
+
45
+ # Block the I/O to wait for async method response
46
+ # @param [Promise] promise promise method
47
+ # @example
48
+ # result = await SQL.query('SELECT * FROM hello')
49
+ def await(promise)
50
+ result = Fiber.yield promise
51
+ if result.is_a? PromiseException
52
+ raise result.payload
53
+ end
54
+ result
55
+ end
56
+ end
57
+
58
+
59
+ ##
60
+ # Exceptions for Promises
61
+ # @!attribute [r] payload
62
+ # @return [Exception] raw execption
63
+ class PromiseException < Exception
64
+ attr_reader :payload
65
+ # Init PromiseException with existed Exception
66
+ # @param [Exception] payload raw execption
67
+ def initialize(payload)
68
+ @payload = payload
69
+ end
70
+ end
@@ -0,0 +1,22 @@
1
+ ##
2
+ # Timer Object in EventLoop
3
+ # @!attribute [r] time
4
+ # @return [Float] timeout length
5
+ # @!attribute [r] callback
6
+ # @return [Proc] proc to call when callbacks
7
+ # @!attribute start_time
8
+ # @return [Float] when timer should callbacks
9
+ class EventLoop::Timer
10
+
11
+ attr_reader :time, :callback
12
+ attr_accessor :start_time
13
+
14
+ # Init a timer with a time period and callback
15
+ # @param [Float] time timeout length
16
+ # @yield proc to call when callbacks
17
+ def initialize(time, &callback)
18
+ @time = time
19
+ @callback = callback
20
+ @start_time = Float::INFINITY
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ # Murasaki Module
2
+ module Murasaki
3
+ # Current Version Code
4
+ VERSION = '0.1.0'.freeze
5
+ end
@@ -0,0 +1,19 @@
1
+ require './lib/murasaki/version'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'murasaki'
5
+ s.version = Murasaki::VERSION
6
+ s.required_ruby_version = '>=2.2.6'
7
+ s.date = Time.now.strftime('%Y-%m-%d')
8
+ s.summary = 'Event Kernel for Ruby'
9
+ s.description = 'Event Kernel for Ruby, power for midori project'
10
+ s.authors = ['HeckPsi Lab']
11
+ s.email = 'business@heckpsi.com'
12
+ s.require_paths = ['lib']
13
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|.resources)/}) } \
14
+ - %w(README.md CONTRIBUTOR_COVENANT_CODE_OF_CONDUCT.md Gemfile Rakefile em-midori.gemspec .gitignore .rspec .codeclimate.yml .rubocop.yml .travis.yml logo.png Rakefile Gemfile)
15
+ s.homepage = 'https://github.com/heckpsi-lab/murasaki'
16
+ s.metadata = { 'issue_tracker' => 'https://github.com/heckpsi-lab/murasaki/issues' }
17
+ s.license = 'MIT'
18
+ s.add_runtime_dependency 'nio4r', '~> 2.0'
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: murasaki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - HeckPsi Lab
@@ -9,14 +9,35 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2017-06-13 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nio4r
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
13
27
  description: Event Kernel for Ruby, power for midori project
14
28
  email: business@heckpsi.com
15
29
  executables: []
16
30
  extensions: []
17
31
  extra_rdoc_files: []
18
32
  files:
33
+ - ".editorconfig"
19
34
  - LICENSE
35
+ - lib/murasaki.rb
36
+ - lib/murasaki/event_loop.rb
37
+ - lib/murasaki/promise.rb
38
+ - lib/murasaki/timer.rb
39
+ - lib/murasaki/version.rb
40
+ - murasaki.gemspec
20
41
  homepage: https://github.com/heckpsi-lab/murasaki
21
42
  licenses:
22
43
  - MIT