vuf 0.0.1 → 0.0.2
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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +2 -0
- data/Rakefile +12 -0
- data/lib/vuf/batch.rb +34 -0
- data/lib/vuf/logger.rb +5 -0
- data/lib/vuf/pool.rb +91 -0
- data/lib/vuf/version.rb +3 -0
- data/lib/vuf/working_pool.rb +81 -0
- data/lib/vuf.rb +12 -0
- data/test/lib/vuf/batch_test.rb +26 -0
- data/test/lib/vuf/pool_test.rb +58 -0
- data/test/lib/vuf/wp_test.rb +30 -0
- data/test/test_helper.rb +4 -0
- data/test/tmp/.gitignore +4 -0
- data/vuf.gemspec +24 -0
- metadata +37 -10
- checksums.yaml +0 -7
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Bernard Rodier
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
data/Rakefile
ADDED
data/lib/vuf/batch.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Vuf
|
2
|
+
class Batch
|
3
|
+
def initialize(size,&batch)
|
4
|
+
@mutex = Mutex.new
|
5
|
+
@batchQ = SizedQueue.new(size)
|
6
|
+
@batch = batch
|
7
|
+
end
|
8
|
+
|
9
|
+
def push(obj)
|
10
|
+
@batchQ.push(obj)
|
11
|
+
objsToProc = get_objs(@batchQ.max)
|
12
|
+
@batch.call(objsToProc) unless objsToProc.nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
def flush
|
16
|
+
objsToProc = get_objs(0)
|
17
|
+
@batch.call(objsToProc)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def get_objs(size_condition)
|
22
|
+
objToProc = nil
|
23
|
+
@mutex.synchronize do
|
24
|
+
if size_condition <= @batchQ.size
|
25
|
+
objToProc = []
|
26
|
+
objToProc << @batchQ.pop until @batchQ.empty?
|
27
|
+
@batchQ.clear
|
28
|
+
end
|
29
|
+
end
|
30
|
+
return objToProc
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/vuf/logger.rb
ADDED
data/lib/vuf/pool.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
module Vuf
|
2
|
+
module Pool
|
3
|
+
# Raises a TypeError to prevent cloning.
|
4
|
+
def clone
|
5
|
+
raise TypeError, "can't clone instance of Pool #{self.class}"
|
6
|
+
end
|
7
|
+
|
8
|
+
# Raises a TypeError to prevent duping.
|
9
|
+
def dup
|
10
|
+
raise TypeError, "can't dup instance of Pool #{self.class}"
|
11
|
+
end
|
12
|
+
|
13
|
+
# By default, do not retain any state when marshalling.
|
14
|
+
def _dump(depth = -1)
|
15
|
+
''
|
16
|
+
end
|
17
|
+
|
18
|
+
module PoolClassMethods # :nodoc:
|
19
|
+
|
20
|
+
def clone # :nodoc:
|
21
|
+
Pool.__init__(super)
|
22
|
+
end
|
23
|
+
|
24
|
+
# By default calls instance(). Override to retain singleton state.
|
25
|
+
def _load(str)
|
26
|
+
raise TypeError, "can't _load Pool #{self.class}"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def inherited(sub_klass)
|
32
|
+
super
|
33
|
+
Pool.__init__(sub_klass)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class << Pool # :nodoc:
|
38
|
+
def __init__(klass) # :nodoc:
|
39
|
+
klass.instance_eval {
|
40
|
+
@pool__instances__ = Queue.new
|
41
|
+
@used__instances__ = Hash.new
|
42
|
+
@pool__mutex__ = Mutex.new
|
43
|
+
}
|
44
|
+
|
45
|
+
def klass.instance # :nodoc:
|
46
|
+
instance__ = nil
|
47
|
+
@pool__mutex__.synchronize do
|
48
|
+
instance__ = @used__instances__[Thread.current]
|
49
|
+
if instance__.nil? && @pool__instances__.size > 0
|
50
|
+
instance__ = @pool__instances__.pop
|
51
|
+
end
|
52
|
+
instance__ = new() if instance__.nil?
|
53
|
+
@used__instances__[Thread.current] = instance__
|
54
|
+
end
|
55
|
+
instance__
|
56
|
+
end
|
57
|
+
|
58
|
+
def klass.release # :nodoc:
|
59
|
+
instance__ = nil
|
60
|
+
@pool__mutex__.synchronize do
|
61
|
+
instance__ = @used__instances__.delete(Thread.current)
|
62
|
+
@pool__instances__.push(instance__) unless instance__.nil?
|
63
|
+
end
|
64
|
+
!instance__.nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
klass
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# extending an object with Pool is a bad idea
|
73
|
+
undef_method :extend_object
|
74
|
+
|
75
|
+
def append_features(mod)
|
76
|
+
# help out people counting on transitive mixins
|
77
|
+
unless mod.instance_of?(Class)
|
78
|
+
raise TypeError, "Inclusion of the OO-Singleton module in module #{mod}"
|
79
|
+
end
|
80
|
+
super
|
81
|
+
end
|
82
|
+
|
83
|
+
def included(klass)
|
84
|
+
super
|
85
|
+
klass.private_class_method :new, :allocate
|
86
|
+
klass.extend PoolClassMethods
|
87
|
+
Pool.__init__(klass)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/vuf/version.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
module Vuf
|
2
|
+
class WorkingPool
|
3
|
+
ENDING_TASK="ENDING_TASK"
|
4
|
+
|
5
|
+
def initialize(nb_workers, max_pending_tasks=nil)
|
6
|
+
@nb_workers = nb_workers
|
7
|
+
if max_pending_tasks.nil?
|
8
|
+
@wq = Queue.new
|
9
|
+
else
|
10
|
+
@wq = SizedQueue.new(max_pending_tasks)
|
11
|
+
end
|
12
|
+
@channels_mutex = Mutex.new
|
13
|
+
@channels = {}
|
14
|
+
@channelsQ = Array.new(@nb_workers){ Queue.new }
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
if @workers.nil?
|
19
|
+
@workers=[]
|
20
|
+
@nb_workers.times do
|
21
|
+
@workers << Thread.new do
|
22
|
+
works
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def do(channel=nil,&task)
|
29
|
+
@wq.push([channel,task])
|
30
|
+
end
|
31
|
+
|
32
|
+
def finalize
|
33
|
+
return if @workers.nil?
|
34
|
+
@nb_workers.times do
|
35
|
+
@wq.push(ENDING_TASK)
|
36
|
+
end
|
37
|
+
@workers.each do |worker|
|
38
|
+
worker.join
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def try_lock_channel(channel,task)
|
45
|
+
new_channel_q = nil
|
46
|
+
@channels_mutex.synchronize {
|
47
|
+
if @channels[channel].nil?
|
48
|
+
new_channel_q = @channelsQ.shift
|
49
|
+
@channels[channel]=new_channel_q
|
50
|
+
end
|
51
|
+
}
|
52
|
+
@channels[channel].push(task)
|
53
|
+
return new_channel_q
|
54
|
+
end
|
55
|
+
|
56
|
+
def is_clear(channel)
|
57
|
+
is_clear=nil
|
58
|
+
@channels_mutex.synchronize{
|
59
|
+
is_clear = @channels[channel].empty?
|
60
|
+
@channelsQ << @channels.delete(channel) if is_clear
|
61
|
+
}
|
62
|
+
return is_clear
|
63
|
+
end
|
64
|
+
|
65
|
+
def works
|
66
|
+
task=nil
|
67
|
+
until ENDING_TASK == (task= @wq.pop)
|
68
|
+
channel = task.first
|
69
|
+
task = task.last
|
70
|
+
channelQ = nil
|
71
|
+
channelQ = try_lock_channel(channel,task) unless channel.nil?
|
72
|
+
if channelQ.nil?
|
73
|
+
task.call
|
74
|
+
else
|
75
|
+
channelQ.pop.call until is_clear(channel)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
data/lib/vuf.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Vuf::Batch do
|
4
|
+
subject {
|
5
|
+
Vuf::Batch.new(50) do |objQ|
|
6
|
+
objQ.size.must_equal(50) unless objQ.empty?
|
7
|
+
end
|
8
|
+
}
|
9
|
+
|
10
|
+
it "must respond to push" do
|
11
|
+
subject.must_respond_to(:push)
|
12
|
+
1000.times do |i|
|
13
|
+
subject.push(i)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "must respond to flush" do
|
18
|
+
subject.must_respond_to(:flush)
|
19
|
+
1000.times do |i|
|
20
|
+
subject.push(i)
|
21
|
+
end
|
22
|
+
subject.flush
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Vuf::Pool do
|
4
|
+
subject {
|
5
|
+
class TestKlass
|
6
|
+
include Vuf::Pool
|
7
|
+
def initialize
|
8
|
+
end
|
9
|
+
end
|
10
|
+
TestKlass
|
11
|
+
}
|
12
|
+
|
13
|
+
it "must not respond to new" do
|
14
|
+
subject.wont_respond_to(:new)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "must respond_to use_instance" do
|
18
|
+
subject.must_respond_to(:instance)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "must respond_to release" do
|
22
|
+
subject.must_respond_to(:release)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Vuf::Pool do
|
27
|
+
class PoolKlass
|
28
|
+
include Vuf::Pool
|
29
|
+
attr_reader :i_index
|
30
|
+
def initialize
|
31
|
+
@@index ||= 0
|
32
|
+
@@index += 1
|
33
|
+
@i_index = @@index
|
34
|
+
@f = File.open(File.join("test", "tmp", "file_#{@@index}.txt"),"w+")
|
35
|
+
end
|
36
|
+
|
37
|
+
def write(msg)
|
38
|
+
@f.write(msg)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
subject { 5 }
|
44
|
+
|
45
|
+
it "must create 5 Files" do
|
46
|
+
wp = Vuf::WorkingPool.new(subject)
|
47
|
+
wp.run
|
48
|
+
1000.times do |i|
|
49
|
+
wp.do do
|
50
|
+
poolklass_instance = PoolKlass.instance
|
51
|
+
poolklass_instance.write("Message #{i.to_s}\n")
|
52
|
+
PoolKlass.release
|
53
|
+
end
|
54
|
+
end
|
55
|
+
wp.finalize
|
56
|
+
Dir[File.join("test", "tmp","file_*.txt")].size.must_equal(subject)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Vuf::WorkingPool do
|
4
|
+
subject { Vuf::WorkingPool.new(5) }
|
5
|
+
|
6
|
+
it "must be a WorkingPool" do
|
7
|
+
subject.must_be_instance_of(Vuf::WorkingPool)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "must respond_to run" do
|
11
|
+
subject.must_respond_to(:run)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "must respond_to do" do
|
15
|
+
subject.must_respond_to(:do)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "must respond_to finalize" do
|
19
|
+
subject.must_respond_to(:finalize)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "must handle without error" do
|
23
|
+
subject.run
|
24
|
+
5.times do |i|
|
25
|
+
subject.do { sleep(1/10) }
|
26
|
+
end
|
27
|
+
subject.finalize
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
data/test/test_helper.rb
ADDED
data/test/tmp/.gitignore
ADDED
data/vuf.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'vuf/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "vuf"
|
8
|
+
spec.version = Vuf::VERSION
|
9
|
+
spec.authors = ["Bernard Rodier"]
|
10
|
+
spec.email = ["bernard.rodier@gmail.com"]
|
11
|
+
spec.description = %q{My Very Usefull Patterns}
|
12
|
+
spec.summary = %q{This gem provide usefulle patterns like workingpool,
|
13
|
+
batch executor, object instance recyclor, etc..}
|
14
|
+
spec.homepage = "https://github.com/brodier/vuf"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($/)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
end
|
metadata
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vuf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Bernard Rodier
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
12
|
+
date: 2014-01-13 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
@@ -20,6 +22,7 @@ dependencies:
|
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - ~>
|
25
28
|
- !ruby/object:Gem::Version
|
@@ -27,15 +30,17 @@ dependencies:
|
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: rake
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
|
-
- - '>='
|
35
|
+
- - ! '>='
|
32
36
|
- !ruby/object:Gem::Version
|
33
37
|
version: '0'
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
|
-
- - '>='
|
43
|
+
- - ! '>='
|
39
44
|
- !ruby/object:Gem::Version
|
40
45
|
version: '0'
|
41
46
|
description: My Very Usefull Patterns
|
@@ -45,30 +50,52 @@ executables: []
|
|
45
50
|
extensions: []
|
46
51
|
extra_rdoc_files: []
|
47
52
|
files:
|
53
|
+
- .gitignore
|
54
|
+
- Gemfile
|
55
|
+
- LICENSE.txt
|
48
56
|
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- lib/vuf.rb
|
59
|
+
- lib/vuf/batch.rb
|
60
|
+
- lib/vuf/logger.rb
|
61
|
+
- lib/vuf/pool.rb
|
62
|
+
- lib/vuf/version.rb
|
63
|
+
- lib/vuf/working_pool.rb
|
64
|
+
- test/lib/vuf/batch_test.rb
|
65
|
+
- test/lib/vuf/pool_test.rb
|
66
|
+
- test/lib/vuf/wp_test.rb
|
67
|
+
- test/test_helper.rb
|
68
|
+
- test/tmp/.gitignore
|
69
|
+
- vuf.gemspec
|
49
70
|
homepage: https://github.com/brodier/vuf
|
50
71
|
licenses:
|
51
72
|
- MIT
|
52
|
-
metadata: {}
|
53
73
|
post_install_message:
|
54
74
|
rdoc_options: []
|
55
75
|
require_paths:
|
56
76
|
- lib
|
57
77
|
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
58
79
|
requirements:
|
59
|
-
- - '>='
|
80
|
+
- - ! '>='
|
60
81
|
- !ruby/object:Gem::Version
|
61
82
|
version: '0'
|
62
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
63
85
|
requirements:
|
64
|
-
- - '>='
|
86
|
+
- - ! '>='
|
65
87
|
- !ruby/object:Gem::Version
|
66
88
|
version: '0'
|
67
89
|
requirements: []
|
68
90
|
rubyforge_project:
|
69
|
-
rubygems_version:
|
91
|
+
rubygems_version: 1.8.23
|
70
92
|
signing_key:
|
71
|
-
specification_version:
|
93
|
+
specification_version: 3
|
72
94
|
summary: This gem provide usefulle patterns like workingpool, batch executor, object
|
73
95
|
instance recyclor, etc..
|
74
|
-
test_files:
|
96
|
+
test_files:
|
97
|
+
- test/lib/vuf/batch_test.rb
|
98
|
+
- test/lib/vuf/pool_test.rb
|
99
|
+
- test/lib/vuf/wp_test.rb
|
100
|
+
- test/test_helper.rb
|
101
|
+
- test/tmp/.gitignore
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 4089f9d841dfb7c01a2317d994730b8d76d73ebb
|
4
|
-
data.tar.gz: 5f76bb26084789cdf11930739570ed05fd39858d
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 4671e8622031c303263a6fade5a7c04978aecf0a8eb1340cffb66c2efaa2ad0cfba2376b2e56e10ae2ffeeefa10258c8ff531bc0f74978bad4e37a404bb8d1da
|
7
|
-
data.tar.gz: 259136799b9a50f564682c5fdfd27eaf5e4f7082c4dbb65ebef0b032d2118284de652f771df043d21c7c7886c47a2014e505524c17eaa9e0755104ee9bc4d542
|