Class: Win32::Semaphore

Inherits:
Ipc
  • Object
show all
Defined in:
lib/win32/semaphore.rb

Overview

The Semaphore class encapsulates semaphore objects on Windows.

Defined Under Namespace

Classes: SecurityAttributes

Constant Summary collapse

VERSION =

The version of the win32-semaphore library

'0.4.1'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(initial_count, max_count, name = nil, inherit = true) ⇒ Semaphore

Creates and returns new Semaphore object. If name is omitted, the Semaphore object is created without a name, i.e. it’s anonymous.

If name is provided and it already exists, then it is opened instead, and the initial_count and max_count parameters are ignored.

The initial_count and max_count parameters set the initial count and maximum count for the Semaphore object, respectively. See the documentation for the corresponding accessor for more information.

The inherit attribute determines whether or not the semaphore can be inherited by child processes.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/win32/semaphore.rb', line 70

def initialize(initial_count, max_count, name=nil, inherit=true)
  @initial_count = initial_count
  @max_count = max_count
  @name      = name
  @inherit   = inherit

  if name && name.encoding.to_s != 'UTF-16LE'
    name = name + 0.chr
    name.encode!('UTF-16LE')
  end

  if inherit
    sec = SecurityAttributes.new
    sec[:nLength] = SecurityAttributes.size
    sec[:bInheritHandle] = true
  else
    sec = nil
  end

  handle = CreateSemaphoreW(sec, initial_count, max_count, name)

  if handle == 0 || handle == INVALID_HANDLE_VALUE
    raise SystemCallError.new("CreateSemaphore", FFI.errno)
  end

  super(handle)

  if block_given?
    begin
      yield self
    ensure
      close
    end
  end
end

Instance Attribute Details

#initial_countObject (readonly)

The initial count for the semaphore object. This value must be greater than or equal to zero and less than or equal to max_count. The state of a semaphore is signaled when its count is greater than zero and nonsignaled when it is zero. The count is decreased by one whenever a wait function releases a thread that was waiting for the semaphore. The count is increased by a specified amount by calling Semaphore#release method.



45
46
47
# File 'lib/win32/semaphore.rb', line 45

def initial_count
  @initial_count
end

#max_countObject (readonly)

The maximum count for the semaphore object. This value must be greater than zero.



50
51
52
# File 'lib/win32/semaphore.rb', line 50

def max_count
  @max_count
end

#nameObject (readonly)

The name of the Semaphore object.



54
55
56
# File 'lib/win32/semaphore.rb', line 54

def name
  @name
end

Class Method Details

.open(name, inherit = true, &block) ⇒ Object

Open an existing Semaphore by name. The inherit argument sets whether or not the object was opened such that a process created by the CreateProcess() function (a Windows API function) can inherit the handle. The default is true.

This method is essentially identical to Semaphore.new, except that the options for initial_count and max_count cannot be set (since they are already set). Also, this method will raise a Semaphore::Error if the semaphore doesn’t already exist.

If you want “open or create” semantics, then use Semaphore.new.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/win32/semaphore.rb', line 118

def self.open(name, inherit=true, &block)
  if name && name.encoding.to_s != 'UTF-16LE'
    name = name + 0.chr
    name.encode!('UTF-16LE')
  end

  begin
    # The OpenSemaphore() call here is strictly to force an error if the
    # user tries to open a semaphore that doesn't already exist.
    handle = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, inherit, name)

    if handle == 0 || handle == INVALID_HANDLE_VALUE
      raise SystemCallError.new("OpenSemaphore", FFI.errno)
    end
  ensure
    CloseHandle(handle)
  end

  self.new(0, 1, name, inherit, &block)
end

Instance Method Details

#inheritable?Boolean

Returns whether or not the object was opened such that a process created by the CreateProcess() function (a Windows API function) can inherit the handle. The default is true.

Returns:

  • (Boolean)


161
162
163
# File 'lib/win32/semaphore.rb', line 161

def inheritable?
  @inherit
end

#release(amount = 1) ⇒ Object

Increases the count of the specified semaphore object by amount. The default is 1. Returns the previous count of the semaphore if successful. If the amount exceeds the max_count specified when the semaphore was created then an error is raised.



144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/win32/semaphore.rb', line 144

def release(amount = 1)
  pcount = FFI::MemoryPointer.new(:long)

  # Ruby doesn't translate error 298, so we treat it as an EINVAL
  unless ReleaseSemaphore(@handle, amount, pcount)
    errno = FFI.errno
    errno = 22 if errno == 298 # 22 is EINVAL
    raise SystemCallError.new("ReleaseSemaphore", errno)
  end

  pcount.read_long
end