class Knj::Threadhandler

Attributes

activate_blocks[R]
args[R]
inactive_blocks[R]
mutex[R]
objects[R]

Public Class Methods

new(args = {}) click to toggle source
# File lib/knj/threadhandler.rb, line 4
def initialize(args = {})
  require "#{$knjpath}errors"
  require "tsafe" if !Kernel.const_defined?(:Tsafe)
  
  @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

Public Instance Methods

check_inactive() click to toggle source
# File lib/knj/threadhandler.rb, line 66
def check_inactive
  raise "Destroyed Knj::Threadhandler." if !@mutex
  cur_time = Time.now.to_i - @args[:timeout]
  
  @mutex.synchronize do
    @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
destroy() click to toggle source
# File lib/knj/threadhandler.rb, line 44
def destroy
  return false if !@mutex
  
  @thread_timeout.kill if @thread_timeout and @thread_timeout.alive?
  @thread_timeout = nil
  
  @mutex.synchronize do
    @objects.each do |data|
      @inactive_blocks.each do |block|
        data[:inactive] = true
        block.call(:obj => data[:object])
      end
    end
  end
  
  @args = nil
  @objects = nil
  @inactive_blocks = nil
  @activate_blocks = nil
  @mutex = nil
end
free(obj) click to toggle source
# File lib/knj/threadhandler.rb, line 137
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.now.to_i
  end
end
get_and_lock() click to toggle source
# File lib/knj/threadhandler.rb, line 82
def get_and_lock
  raise "Destroyed Knj::Threadhandler." if !@mutex
  newobj = nil
  
  begin
    retdata = nil
    
    @mutex.synchronize do
      @objects.each do |data|
        if data[:free]
          retdata = data
          break
        end
      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
      @mutex.synchronize do
        @objects << Tsafe::MonHash.new.merge(
          :free => false,
          :object => newobj
        )
      end
      STDOUT.print "Spawned db and locked new.\n" if @args[:debug]
    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
on_activate(&block) click to toggle source
# File lib/knj/threadhandler.rb, line 39
def on_activate(&block)
  raise "Destroyed Knj::Threadhandler." if !@mutex
  @activate_blocks << block
end
on_inactive(&block) click to toggle source
# File lib/knj/threadhandler.rb, line 34
def on_inactive(&block)
  raise "Destroyed Knj::Threadhandler." if !@mutex
  @inactive_blocks << block
end
on_spawn_new(&block) click to toggle source
# File lib/knj/threadhandler.rb, line 29
def on_spawn_new(&block)
  raise "Destroyed Knj::Threadhandler." if !@mutex
  @spawn_new_block = block
end
use() { |obj| ... } click to toggle source

Executes the given block with an element and then frees it.

# File lib/knj/threadhandler.rb, line 156
def use
  raise "No block was given." if !block_given?
  
  obj = self.get_and_lock
  
  begin
    yield(obj)
  ensure
    self.free(obj)
  end
end