[Win32utils-devel] Pure win32-thread library?

Daniel Berger djberg96 at gmail.com
Sun May 18 00:33:10 EDT 2008


Hi all,

Here's my initial stab at a pure Ruby win32-thread library that doesn't 
work at all. I'm not sure how to pass the start address of the arguments 
to the callback. I thought about Marshal, but you can't marshal a proc.

BTW, the CreateThread method in windows-pr needs to be updated for this 
to have any hope of success.

Any ideas?

Thanks,

Dan

# win32/thread.rb
require 'windows/thread'
require 'windows/synchronize'
require 'windows/error'
include Windows

module Win32
    class Thread
       include Windows::Thread
       include Windows::Synchronize
       include Windows::Error
       extend Windows::Synchronize

       class Error < StandardError; end

       @@mutex = CreateMutex(nil, false, nil)

       ABOVE_NORMAL = THREAD_PRIORITY_ABOVE_NORMAL
       BELOW_NORMAL = THREAD_PRIORITY_BELOW_NORMAL
       HIGHEST      = THREAD_PRIORITY_HIGHEST
       IDLE         = THREAD_PRIORITY_IDLE
       LOWEST       = THREAD_PRIORITY_LOWEST
       NORMAL       = THREAD_PRIORITY_NORMAL
       CRITICAL     = THREAD_PRIORITY_TIME_CRITICAL

       VERSION = '0.1.0'

       WinThreadFunc = API::Callback.new('L', 'L'){ |args|
          block = args.pop
          block.call(args)
          ReleaseMutex(@@mutex)
       }

       attr_reader :thread_id

       def initialize(*args, &block)
          raise ArgumentError, 'block must be provided' unless block_given?
          args.push(block)

          thread_id = [0].pack('L')
          dwArgs    = nil # What should this be?

          @thread = CreateThread(
             nil,           # Handle cannot be inherited
             0,             # Default stack size
             WinThreadFunc, # Pointer to thread func
             dwArgs,        # Arguments passed to thread func
             0,             # Execute immediately, i.e. not suspended
             thread_id      # Stores the thread id
          )

          if @thread == 0
             raise Error, get_last_error
          end

          @thread_id = thread_id.unpack('L')[0]
       end

       def join(limit = INFINITE)
          limit = limit * 1000 unless limit == INFINITE
          WaitForSingleObject(@thread, limit)
          ReleaseMutex(@@mutex)
       end

       def terminate
          exit_code = [0].pack('L')
          return nil unless TerminateThread(@thread, exit_code)
       end

       def exit
          ExitThread(0)
       end

       def priority
          GetThreadPriority(@thread)
       end

       def priority=(value)
          unless SetThreadPriority(@thread, value)
             raise Error, get_last_error
          end
       end
    end
end

if $0 == __FILE__
    t = Win32::Thread.new('a', 'b'){ |x, y| puts "Hello: #{x}, #{y}" }
    t.join
end


More information about the win32utils-devel mailing list