lib/knj/threadhandler.rb in knjrbfw-0.0.8 vs lib/knj/threadhandler.rb in knjrbfw-0.0.9
- old
+ new
@@ -1,41 +1,48 @@
class Knj::Threadhandler
- attr_reader :inactive_blocks, :args, :activate_blocks, :mutex
-
- def initialize(args = {})
- @args = args
- @objects = []
- @args[:timeout] = 5 if !@args[:timeout]
- @inactive_blocks = []
- @activate_blocks = []
- @mutex = Mutex.new
-
- @thread_timeout = Knj::Thread.new do
- loop do
- sleep @args[:timeout]
- break if !@mutex
- check_inactive
- end
- end
- end
-
- def on_spawn_new(&block)
+ attr_reader :inactive_blocks, :args, :activate_blocks, :mutex, :objects
+
+ def initialize(args = {})
+ require "#{$knjpath}errors"
+
+ @args = args
+ @objects = []
+ @args[:timeout] = 5 if !@args[:timeout]
+ @args[:max] = 50 if !@args[:max]
+ @inactive_blocks = []
+ @activate_blocks = []
+ @mutex = Mutex.new
+
+ @thread_timeout = Thread.new do
+ begin
+ loop do
+ sleep @args[:timeout]
+ break if !@mutex
+ check_inactive
+ end
+ rescue => e
+ STDOUT.print Knj::Errors.error_str(e)
+ end
+ end
+ end
+
+ def on_spawn_new(&block)
raise "Destroyed Knj::Threadhandler." if !@mutex
- @spawn_new_block = block
- end
-
- def on_inactive(&block)
+ @spawn_new_block = block
+ end
+
+ def on_inactive(&block)
raise "Destroyed Knj::Threadhandler." if !@mutex
- @inactive_blocks << block
- end
-
- def on_activate(&block)
+ @inactive_blocks << block
+ end
+
+ def on_activate(&block)
raise "Destroyed Knj::Threadhandler." if !@mutex
- @activate_blocks << block
- end
-
- def destroy
+ @activate_blocks << block
+ end
+
+ def destroy
return false if !@mutex
@thread_timeout.kill if @thread_timeout and @thread_timeout.alive?
@thread_timeout = nil
@@ -51,80 +58,106 @@
@args = nil
@objects = nil
@inactive_blocks = nil
@activate_blocks = nil
@mutex = nil
- end
-
- def check_inactive
+ end
+
+ def check_inactive
raise "Destroyed Knj::Threadhandler." if !@mutex
- @mutex.synchronize do
- cur_time = Time.new.to_i - @args[:timeout]
- @objects.each do |data|
- if data[:free] and !data[:inactive] and data[:free] < cur_time
- @inactive_blocks.each do |block|
- data[:inactive] = true
- block.call(:obj => data[:object])
- end
- end
- end
- end
- end
-
- def get_and_lock
+ @mutex.synchronize do
+ cur_time = Time.now.to_i - @args[:timeout]
+ @objects.each do |data|
+ if data[:free] and !data[:inactive] and data[:free] < cur_time
+ @inactive_blocks.each do |block|
+ data[:inactive] = true
+ block.call(:obj => data[:object])
+ end
+ end
+ end
+ end
+ end
+
+ def get_and_lock
raise "Destroyed Knj::Threadhandler." if !@mutex
- newobj = nil
-
- @mutex.synchronize do
- retdata = false
- @objects.each do |data|
- if data[:free]
- retdata = data
- break
- end
- end
-
- if retdata
- #Test if object is still free - if not, try again - knj.
- return get_and_lock if !retdata[:free]
- retdata[:free] = false
-
- if retdata[:inactive]
- @activate_blocks.each do |block|
- block.call(:obj => retdata[:object])
- end
-
- retdata.delete(:inactive)
- end
-
- return retdata[:object]
- end
-
- newobj = @spawn_new_block.call
- @objects << {
- :free => false,
- :object => newobj
- }
- STDOUT.print "Spawned db and locked new.\n" if @args[:debug]
- end
-
- return newobj
- end
-
- def free(obj)
- @mutex.synchronize do
+ newobj = nil
+ sleep_do = false
+
+ begin
+ @mutex.synchronize do
+ retdata = false
+ @objects.each do |data|
+ if data[:free]
+ retdata = data
+ break
+ end
+ end
+
+ if retdata
+ #Test if object is still free - if not, try again - knj.
+ return get_and_lock if !retdata[:free]
+ retdata[:free] = false
+
+ if retdata[:inactive]
+ @activate_blocks.each do |block|
+ block.call(:obj => retdata[:object])
+ end
+
+ retdata.delete(:inactive)
+ end
+
+ return retdata[:object]
+ end
+
+ if @objects.length >= @args[:max]
+ #The maximum amount of objects has already been spawned... Sleep 0.1 sec and try to lock an object again...
+ raise Knj::Errors::Retry
+ else
+ #No free objects, but we can spawn a new one and use that...
+ newobj = @spawn_new_block.call
+ @objects << {
+ :free => false,
+ :object => newobj
+ }
+ STDOUT.print "Spawned db and locked new.\n" if @args[:debug]
+ end
+ end
+
+ return newobj
+ rescue Knj::Errors::Retry
+ STDOUT.print "All objects was taken - sleeping 0.1 sec and tries again.\n" #if @args[:debug]
+ sleep 0.1
+ retry
+ end
+ end
+
+ def free(obj)
+ @mutex.synchronize do
return false if !@mutex or !@objects #something is trying to free and object, but the handler is destroyed. Dont crash but return false.
- freedata = false
- @objects.each do |data|
- if data[:object] == obj
- freedata = data
- break
- end
- end
-
- raise "Could not find that object in list." if !freedata
- STDOUT.print "Freed one.\n" if @args[:debug]
- freedata[:free] = Time.new.to_i
- end
- end
+ freedata = false
+ @objects.each do |data|
+ if data[:object] == obj
+ freedata = data
+ break
+ end
+ end
+
+ raise "Could not find that object in list." if !freedata
+ STDOUT.print "Freed one.\n" if @args[:debug]
+ freedata[:free] = Time.now.to_i
+ end
+ end
+
+ #Executes the given block with an element and then frees it.
+ def use
+ raise "No block was given." if !block_given?
+
+ obj = self.get_and_lock
+
+ begin
+ yield(obj)
+ ensure
+ self.free(obj)
+ end
+ end
end
\ No newline at end of file