# Web::Persistent::Lock::W32Mutex
# Copyright(c) 2002 MoonWolf <moonwolf@moonwolf.com>
require "Win32API"

module Web
  class Persistent
    module Lock
      class W32Mutex
        CreateMutex  = Win32API.new('kernel32','CreateMutexA','PIP','L')
        OpenMutexA   = Win32API.new('kernel32','OpenMutexA','LIP','L')
        ReleaseMutex = Win32API.new('kernel32','ReleaseMutex','L','I')
        GetLastError = Win32API.new('kernel32','GetLastError','V','L')
        CloseHandle  = Win32API.new('kernel32','CloseHandle','L','I')
        WaitForSingleObject = Win32API.new('kernel32','WaitForSingleObject','LL','L')
        ERROR_ALREADY_EXISTS = 183
        INFINITE = 0xffffffff
        MUTEX_ALL_ACCESS = 0x1f0001
        SYNCHRONIZE = 0x100000
        
        def initialize(persistent_id, options={})
          @persistent_id = persistent_id
          @mutex  = CreateMutex.call(nil, 0, @persistent_id)
          @locked = false
        end
        
        def lock
          @locked = true
          @mutex = OpenMutexA.call(MUTEX_ALL_ACCESS, 0, @persistent_id)
          WaitForSingleObject.call(@mutex, INFINITE)
          if block_given?
            yield
            unlock
          end
        end
        
        def unlock
          raise unless @mutex
          ReleaseMutex.call(@mutex)
          CloseHandle.call(@mutex)
          @mutex = nil
          @locked = false
        end
        
        def delete
          if @mutex
            ReleaseMutex.call(@mutex)
          end
        end
        
      end # W32Mutex
    end # Lock
  end # Persistent
end # Web
