Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Oleg Andreev <oleganza@gmail.com>
- # November 3, 2008
- require 'thread'
- module DataMapper
- class Repository
- # Original context returns new context stack for the current thread:
- # Thread.current[:dm_repository_contexts] ||= []
- # This is not cool because there might be new thread creation on each request,
- # what turns into tons of stacks and repositories generated for each request.
- class ContextsPool
- THREAD_VAR = :dm_repository_contexts
- # Ensures that THREAD_VAR is used.
- module OverrideContext
- def context
- Thread.current[THREAD_VAR]
- end
- end
- def initialize(options = {})
- options = options.merge(:size => 2, :clean_interval => 120)
- size = options[:size]
- int = options[:clean_interval]
- @queue = Queue.new
- size.times{ @queue.push([]) }
- Repository.extend(OverrideContext)
- @cleaner = Thread.new(size, int) do |s, i|
- sleep i
- q = Queue.new
- s.times { q.push([]) }
- @queue = q
- end
- end
- # Merb Usage:
- #
- # CTX_POOL_SIZE = 10 # number of IdentityMaps per process
- # CTX_POOL = DataMapper::Repository:ContextsPool.new(CTX_POOL_SIZE)
- #
- # def _call_action(*args)
- # CTX_POOL.wrap do
- # repository do
- # # time out the action if it takes longer than 1 second
- # SystemTimer.timeout(1) do
- # super
- # end
- # end
- # end
- # end
- #
- def wrap
- prev = Thread.current[THREAD_VAR]
- q = @queue # @queue can be changed by @cleaner, therefore we use local reference
- Thread.current[THREAD_VAR] = q.pop
- yield
- ensure
- q.push(Thread.current[THREAD_VAR])
- Thread.current[THREAD_VAR] = prev
- end
- end
- end
- end
Add Comment
Please, Sign In to add comment