[Win32utils-devel] Pure win32-thread library?

Park Heesob phasis at gmail.com
Sun May 18 02:30:13 EDT 2008


Hi,
----- Original Message ----- 
From: "Daniel Berger" <djberg96 at gmail.com>
To: "Development and ideas for win32utils projects" <win32utils-devel at rubyforge.org>
Sent: Sunday, May 18, 2008 1:33 PM
Subject: [Win32utils-devel] Pure win32-thread library?


> 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?
> 
I think object_id and ObjectSpace._id2ref did the trick.

After modifing CreateThread prototype as like this:
      API.new('CreateThread', 'PLKPLP', 'L')

Here is a working code:

# 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'){ |pargs|
          args = ObjectSpace._id2ref(pargs)
          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 = args.object_id
          @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


Regards,
Park Heesob



More information about the win32utils-devel mailing list