timed_semaphore 0.0.1
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 +7 -0
- data/lib/timed_semaphore.rb +45 -0
- data/test/timed_semaphore_test.rb +42 -0
- metadata +47 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6356f0e509d4d66d0fe37b7d83e498a7a5c02438
|
4
|
+
data.tar.gz: a4cbfb7255933034f2b97cd3e4d5b1a936519b8d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4520d9f271ade92caec7970c63fa052e38153fe34caacb47898b5a81aabed74b8fa45060e11c9e54ec038c7e9b8e54a62bd23a045a0ff2386fda4eefaf7980ee
|
7
|
+
data.tar.gz: 1d11602b416694c51f45d88291373699793d7543bfbd43c0ee75a1e2dbd154521c0a08ec1cec9a3068be53850b0ff5066485101d85df3fe1a33b9c66668b8830
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class TimedSemaphore
|
2
|
+
def initialize(num_of_ops, num_of_seconds)
|
3
|
+
@count = 0
|
4
|
+
@limit = num_of_ops
|
5
|
+
@period = num_of_seconds
|
6
|
+
@lock = Monitor.new
|
7
|
+
@condition = @lock.new_cond
|
8
|
+
@timer = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
# Acquires a permit or sleeps the thread if all permits are exhausted
|
12
|
+
def acquire
|
13
|
+
synchronize do
|
14
|
+
@condition.wait while @limit > 0 && @count == @limit
|
15
|
+
@count += 1
|
16
|
+
start_timer if @timer.nil?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Starts a thread which releases all permits after @period seconds
|
23
|
+
def start_timer
|
24
|
+
synchronize do
|
25
|
+
@timer = Thread.new do
|
26
|
+
sleep(@period)
|
27
|
+
release_permits
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Releases all permits and notifies all waiting threads to try acquire again
|
33
|
+
def release_permits
|
34
|
+
synchronize do
|
35
|
+
@timer = nil
|
36
|
+
@count = 0
|
37
|
+
@condition.broadcast
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def synchronize(&block)
|
42
|
+
fail 'No block given' unless block_given?
|
43
|
+
@lock.synchronize(&block)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'timed_semaphore'
|
3
|
+
|
4
|
+
class TimedSemaphoreTest < Minitest::Test
|
5
|
+
def test_successful_acquire
|
6
|
+
semaphore = TimedSemaphore.new(1, 10)
|
7
|
+
t = create_waiting_thread(semaphore)
|
8
|
+
assert_equal 'run', t.status
|
9
|
+
assert_equal 'finished', t.value
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_exhausted_permits
|
13
|
+
semaphore = TimedSemaphore.new(1, 10)
|
14
|
+
threads = []
|
15
|
+
5.times { threads << create_waiting_thread(semaphore) }
|
16
|
+
sleep(0.01)
|
17
|
+
count_sleeping = threads.count { |t| t.status == 'sleep' }
|
18
|
+
assert_equal 4, count_sleeping
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_releasing_permits
|
22
|
+
semaphore = TimedSemaphore.new(1, 2)
|
23
|
+
t = create_waiting_thread(semaphore)
|
24
|
+
sleep(0.01)
|
25
|
+
assert_equal false, t.status
|
26
|
+
t = create_waiting_thread(semaphore)
|
27
|
+
sleep(0.01)
|
28
|
+
assert_equal 'sleep', t.status
|
29
|
+
sleep(2)
|
30
|
+
assert_equal false, t.status
|
31
|
+
assert_equal 'finished', t.value
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def create_waiting_thread(semaphore)
|
37
|
+
Thread.new do
|
38
|
+
semaphore.acquire
|
39
|
+
'finished'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: timed_semaphore
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sadžid Suljić
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-10 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A TimedSemaphore is a specialized implementation of a Semaphore that
|
14
|
+
gives a number of permits in a given time frame
|
15
|
+
email: sadzid.suljic@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/timed_semaphore.rb
|
21
|
+
- test/timed_semaphore_test.rb
|
22
|
+
homepage: https://github.com/ssuljic/timed_semaphore
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
metadata: {}
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 2.4.6
|
43
|
+
signing_key:
|
44
|
+
specification_version: 4
|
45
|
+
summary: Implementation of TimedSemaphore
|
46
|
+
test_files:
|
47
|
+
- test/timed_semaphore_test.rb
|