# * George Moschovitis # (c) 2004-2005 Navel, all rights reserved. # $Id: hash.rb 1 2005-04-11 11:04:30Z gmosx $ require 'sync' module Glue # A thread-safe hash. We use a sync object instead of a mutex, # because it is re-entrant. An exclusive lock is needed when # writing, a shared lock IS NEEDED when reading # uses the delegator pattern to allow for multiple # implementations! class SafeHash < Hash attr :sync # gmosx: delegator is not used. # def initialize(delegator = nil) @sync = ::Sync.new end def [](key) @sync.synchronize(::Sync::SH) { super } end def []=(key, value) @sync.synchronize(::Sync::EX) { super } end def delete(key) @sync.synchronize(::Sync::EX) { super } end def clear @sync.synchronize(::Sync::EX) { super } end def size @sync.synchronize(::Sync::SH) { super } end def values @sync.synchronize(::Sync::SH) { super } end def keys @sync.synchronize(::Sync::SH) { super } end end # A thread-safe hash. We use a sync object instead of a mutex, # because it is re-entrant. An exclusive lock is needed when # writing, a shared lock IS NEEDED when reading. # # === Design # # This class uses the delegator pattern. However we dont use rubys # delegation facilities, they are more general and powerfull than we # need here (and slower). Instead a custom (but simple) solution is # used. # # === Example # # hash = SafeHashDelegator.new(Hash.new) # hash = SafeHashDelegator.new(Hash.new) class SafeHashDelegator < Hash attr :delegate, :sync def initialize(delegate) @delegate = delegate @sync = ::Sync.new end def [](key) @sync.synchronize(::Sync::SH) { @delegate[key] } end def []=(key, value) @sync.synchronize(::Sync::EX) { @delegate[key] = value } end def delete(key) @sync.synchronize(::Sync::EX) { @delegate.delete(key) } end def clear @sync.synchronize(::Sync::EX) { @delegate.clear } end def size @sync.synchronize(::Sync::SH) { @delegate.size() } end def values @sync.synchronize(::Sync::SH) { @delegate.values() } end def keys @sync.synchronize(::Sync::SH) { @delegate.keys() } end end end