vadviktor
11/4/2015 - 4:23 PM

dRuby example why a mutex needed per resource

dRuby example why a mutex needed per resource

require 'drb/drb'

class Vault

  # vault has it's own URI stored
  SOCK = '/tmp/drb-prototype_vault.sock'
  URI  = "drbunix:#{SOCK}"

  def initialize
    @mutex = Mutex.new
    @mutex2 = Mutex.new

    @shared_value = 0
    @shared_value2 = 0

    puts 'Vault initialized'
  end

  def inc i
    @mutex.synchronize {
      puts "I[#{i}]  \xF0\x9F\x94\x92"
      sleep 2
      @shared_value += 1
      puts "I[#{i}]    \xF0\x9F\x94\x93"
    }
  end

  def val
    @shared_value
  end

  def inc2 i
    # @mutex2.synchronize {
    @mutex.synchronize {
      puts "II[#{i}] \xF0\x9F\x94\x92"
      @shared_value2 += 1
      puts "II[#{i}]   \xF0\x9F\x94\x93"
    }
  end

  def val2
    @shared_value2
  end

end
require 'drb/drb'

class Function

  def initialize
    @vault = DRbObject.new_with_uri Vault::URI
  end

  def perform
    pids = []

    (1..2).each do |i|

      pids << fork {
        v = DRbObject.new_with_uri Vault::URI
        (1..20).each {
          sleep 0.1
          # puts "[#{i}] value: #{v.val}"
          v.inc i
        }
        exit 0
      }

    end

    puts 'Waiting processing forks to finish'
    pids.each do |p|
      Process.waitpid(p)
    end

    puts "Final value: #{@vault.val}"
  end

end
require 'fileutils'
require 'timeout'
require 'drb/drb'
require 'pry'

require_relative 'vault'
require_relative 'function'
require_relative 'another_function'

class Controller

  def initialize
    puts 'Start'

    @vault_pid = fork do
      # init vault's process
      puts 'Booting Vault'
      FileUtils.rm_f Vault::SOCK
      DRb.start_service Vault::URI, Vault.new
      DRb.thread.join
    end
    Process.detach @vault_pid

    # guard the boot process
    puts 'Make sure Vault is up and running'
    Timeout::timeout(10) {
      until File.exists? Vault::SOCK do
        sleep 0.1
      end
      true
    }

  end

  def perform
    f1 = fork { Function.new.perform }
    f2 = fork { AnotherFunction.new.perform }
    Process.waitpid f1
    Process.waitpid f2
  ensure
    puts 'Shutting down vault'
    Process.kill 'HUP', @vault_pid
    puts 'All finished'
  end

end

Controller.new.perform
require 'drb/drb'

class AnotherFunction

  def initialize
    @vault = DRbObject.new_with_uri Vault::URI
  end

  def perform
    pids = []

    (1..2).each do |i|

      pids << fork {
        v = DRbObject.new_with_uri Vault::URI
        (1..20).each {
          sleep 0.1
          # puts "[#{i}] value: #{v.val2}"
          v.inc2 i
        }
        exit 0
      }

    end

    puts 'Waiting processing forks to finish'
    pids.each do |p|
      Process.waitpid(p)
    end

    puts "Final value2: #{@vault.val2}"
  end

end