module TeamUtil
# Get all matching method names out of definition.
# A definition is a
# * simple string
# * regular expression
# * array of strings or regular expressions
# * symbol
# _[String|Regexp|Array|Symbol]*_
def get_all_method_names(baseclass, definition)
#return value
result = nil
if (definition.instance_of?(Array))
#array of definitions? => concat all subsets
result = Array.new
#list of methods given
definition.each { |methoddef|
result.concat(get_all_method_names(baseclass, methoddef))
}
elsif (definition.instance_of?(String))
#simple string? =>
result = get_method_names(baseclass, /^#{Regexp.escape(definition)}$/)
elsif (definition.instance_of?(Regexp))
result = get_method_names(baseclass, definition)
elsif (definition.instance_of?(Symbol))
result = get_method_names(baseclass, /^#{Regexp.escape(definition.id2name)}$/)
else
raise ObjectTeam::TeamException, "How to handle type >#{definition.class.name}< in #{baseclass.name} callin source?", caller
end
return result
end
# Get all matching method names out of definition.
# A definition is a string or a regexp.
def get_method_names(baseclass, methodfilter)
result = Hash.new
#methodfilter = /^#{methodfilter}$/
delegatefilter = /^#{Interceptor::PREFIX}/
#use all methodnames defined by the class and by callin-bindings
while (baseclass!=Object)
#baseclass.public_instance_methods(false).concat(baseclass.callins.keys).each { |m|
baseclass.public_instance_methods(false).each { |m|
if (!delegatefilter.match(m) and methodfilter.match(m))
result[m] = true
end
}
baseclass = baseclass.superclass
end
#check for ctor
#result["initialize"]=true if (methodfilter.match("initialize"))
return result.keys
end
end
class WeakReferenceError < StandardError
end
class WeakReference
# the object id of the reference
attr :oid
# Construct a weak ref: reference by id not by pointer
def initialize(obj)
@oid = obj.__id__
ObjectSpace.define_finalizer(obj, @@final)
OIDS[@oid] = true
end
# Indicates, if this reference is alive.
def alive?
return OIDS[@oid]
end
# Get reference by pointer.
def ref
if alive?
return ObjectSpace._id2ref(@oid)
else
raise WeakReferenceError, "Already recycled Object"
end
end
# Static map of all weak reference.
# GC will remove the relation.
OIDS = {}
@@final = lambda{ |id|
old_status = Thread.critical
Thread.critical = true
begin
OIDS.delete(id)
ensure
Thread.critical = old_status
end
}
end
# This class is an ordinary hash where no direct references are hold to the key.
# An entry in a WeakHash will automatically be removed when its key is no
# longer in ordinary use and finalized by the garbage collector.
class WeakHash
# encapsulate a real hash
attr :hash
# Create a new Weak hash.
def initialize()
@hash = {}
# GC will remove the relation.
@final = lambda{ |id|
old_status = Thread.critical
Thread.critical = true
begin
self.hash.delete(id)
ensure
Thread.critical = old_status
end
}
end
#Return len of hash.
def length
@hash.length
end
alias_method(:size, :length)
# Iterate over all valid key, value pairs.
# [block] the block to execute
def each(&block)
@hash.each{ |key, val|
block.call(ObjectSpace._id2ref(key), val)
}
end
# Get value of the given key
# [key] the key to lookup for a value
# [return] the stored value or nil, if not found.
def fetch(key)
@hash[key.__id__]
end
alias_method(:[], :fetch)
# Store a key => value pair.
# This hash do not hold a direct reference to the key.
# The pair gets lost, if the key gets finalized.
# [key] the key to lookup the stored value
# [value] the value to store
def store(key, value)
ObjectSpace.define_finalizer(key, @final)
@hash.store(key.__id__, value)
end
alias_method(:[]=, :store)
# Implement equality operator.
def ==(other)
if (other.instance_of?(WeakHash))
return (@hash == other.hash)
else
return (@hash == other)
end
end
end
if (__FILE__ == $0)
def test(whash)
whash.each { |key, val|
puts "Have key #{key} => #{val}"
}
end
weakhash = WeakHash.new
#create some keys
key1 = "One Test"
key2 = "Another Test"
key3 = "The ultimate Test"
#fill hash
weakhash[key1] = "check"
weakhash[key2] = "check"
weakhash[key3] = "check"
#first check => behave as usual hash
ObjectSpace.garbage_collect
print "\n\nthree items should be visible:\n"
test(weakhash)
#second check => perhaps three items should be visible
key1 = nil
key2 = nil
key3 = nil
print "\n\n__perhaps__! three items could be visible (with respect to GC):\n"
test(weakhash)
#third check => no item should be visible!
ObjectSpace.garbage_collect
print "\n\nall items should be finalized!\n"
test(weakhash)
end
syntax highlighted by Code2HTML, v. 0.9.1