<commit_before># Alex's Ruby threading utilities - taken from https://github.com/alexdowad/showcase

require 'thread'
require 'zeevex_proxy'
require 'zeevex_concurrency'

# Wraps an object, synchronizes all method calls
# The wrapped object can also be set and read out
#   which means this can also be used as a thread-safe reference
#   (like a 'volatile' variable in Java)
class ZeevexConcurrency::Synchronized < ZeevexProxy::Base
  def initialize(obj)
    super
    @mutex = ::Mutex.new
  end

  def _set_synchronized_object(val)
    @mutex.synchronize { @obj = val }
  end
  def _get_synchronized_object
    @mutex.synchronize { @obj }
  end

  def respond_to?(method)
    if [:_set_synchronized_object, :_get_synchronized_object].include?(method.to_sym)
      true
    else
      @obj.respond_to?(method)
    end
  end

  def method_missing(method, *args, &block)
    result = @mutex.synchronize { @obj.__send__(method, *args, &block) }
    # result.__id__ == @obj.__id__ ? self : result
  end
end

#
# make object synchronized unless already synchronized
#
def ZeevexConcurrency.Synchronized(obj)
  if obj.respond_to?(:_get_synchronized_object)
    obj
  else
    ZeevexConcurrency::Synchronized.new(obj)
  end
end<commit_msg>accept mutex-duck as optional 2nd argument perform self-replacement on proxied method result slightly optimize respond_to?<commit_after># Alex's Ruby threading utilities - taken from https://github.com/alexdowad/showcase

require 'thread'
require 'zeevex_proxy'
require 'zeevex_concurrency'

# Wraps an object, synchronizes all method calls
# The wrapped object can also be set and read out
#   which means this can also be used as a thread-safe reference
#   (like a 'volatile' variable in Java)
class ZeevexConcurrency::Synchronized < ZeevexProxy::Base
  def initialize(obj, mutex = nil)
    super(obj)
    @mutex = mutex || ::Mutex.new
    freeze
  end

  def _get_synchronized_object
    @mutex.synchronize { @obj }
  end

  def respond_to?(method)
    @obj.respond_to?(method) ||
        [:_get_synchronized_object].include?(method.to_sym)
  end

  def method_missing(method, *args, &block)
    result = @mutex.synchronize { @obj.__send__(method, *args, &block) }
    result.__id__ == @obj.__id__ ? self : result
  end
end

#
# make object synchronized unless already synchronized
#
def ZeevexConcurrency.Synchronized(obj, mutex = nil)
  if obj.respond_to?(:_get_synchronized_object)
    obj
  else
    ZeevexConcurrency::Synchronized.new(obj, mutex)
  end
end
{'fraction_non_alphanumeric': 0.09247397918334668, 'fraction_numerical': 0.00040032025620496394, 'mean_word_length': 4.2280334728033475, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '360350', 'n_tokens_mistral': 835, 'n_tokens_neox': 818, 'n_words': 225}