Module: Winipc
- Defined in:
- lib/winipc.rb,
lib/winipc/version.rb,
ext/winipc/winipc.c
Overview
winipc — Windows local IPC for Ruby: named pipes, shared memory, and named synchronization objects, with a safe-by-default API.
# named pipe, server side
Winipc::Pipe.listen("myapp/control") do |server|
conn = server.accept
puts conn.read(1024)
conn.write("ack")
conn.close
end
# client side (another process)
Winipc::Pipe.connect("myapp/control") do |c|
c.write("hello")
c.read(1024)
end
Defined Under Namespace
Classes: Abandoned, AccessDenied, BrokenPipe, Canceled, Closed, Error, Event, Exists, ModeError, Mutex, NotFound, NotOwner, OSError, Pipe, PipeBusy, RangeError, Semaphore, SharedMemory, TimeoutError, WouldExceedMax
Constant Summary collapse
- PIPE_ACCESS_INBOUND =
—- Win32 flag values (verified) ————————————–
0x00000001- PIPE_ACCESS_OUTBOUND =
0x00000002- PIPE_ACCESS_DUPLEX =
0x00000003- FILE_FLAG_OVERLAPPED =
0x40000000- PIPE_TYPE_MESSAGE =
0x00000004- PIPE_READMODE_MESSAGE =
0x00000002- PIPE_WAIT =
0x00000000- PIPE_REJECT_REMOTE_CLIENTS =
0x00000008- PIPE_UNLIMITED_INSTANCES =
255- GENERIC_READ =
0x80000000- GENERIC_WRITE =
0x40000000- VERSION =
"0.1.0"- K_MUTEX =
Sync objects share the C constructors; subclasses pass their kind.
INT2FIX(K_MUTEX)
- K_EVENT =
INT2FIX(K_EVENT)
- K_SEM =
INT2FIX(K_SEM)
Class Method Summary collapse
- .ms_for(timeout) ⇒ Object
-
.obj_path(name, scope) ⇒ Object
Map a bare object name into the Local\ (default) or Global\ namespace.
-
.pipe_path(name) ⇒ Object
Normalize a bare pipe name to the \.pipe\ namespace (pass a full \serverpipename through unchanged).
-
.run_blocking ⇒ Object
Run a blocking native call cooperatively.
Class Method Details
.ms_for(timeout) ⇒ Object
112 113 114 115 116 117 118 119 120 121 |
# File 'lib/winipc.rb', line 112 def ms_for(timeout) return -1 if timeout.nil? # INFINITE (block until signaled / connected) t = Float(timeout) raise ArgumentError, "timeout must be non-negative, got #{timeout.inspect}" if t.negative? ms = (t * 1000).round # Never collapse a tiny-but-positive wait into a non-blocking poll. ms.zero? && t.positive? ? 1 : ms end |
.obj_path(name, scope) ⇒ Object
Map a bare object name into the Local\ (default) or Global\ namespace.
83 84 85 86 87 88 89 90 |
# File 'lib/winipc.rb', line 83 def obj_path(name, scope) prefix = case scope when :local then "Local\\" when :global then "Global\\" else raise ArgumentError, "scope must be :local or :global, got #{scope.inspect}" end "#{prefix}#{name}" end |
.pipe_path(name) ⇒ Object
Normalize a bare pipe name to the \.pipe\ namespace (pass a full \serverpipename through unchanged).
77 78 79 80 |
# File 'lib/winipc.rb', line 77 def pipe_path(name) s = name.to_s s.start_with?("\\\\") ? s : "\\\\.\\pipe\\#{s}" end |
.run_blocking ⇒ Object
Run a blocking native call cooperatively. Under a Fiber scheduler (e.g. winloop) the call is offloaded to a worker Thread so the calling fiber parks (Thread#value routes through the scheduler) and the event loop keeps serving other fibers; with no scheduler it runs inline (the C call already releases the GVL). On fiber unwind the worker is killed+joined so it can’t leak or consume data destined for a later op.
Caveat: if the fiber is unwound (e.g. Timeout) in the instant after the worker acquired a resource but before the value was delivered, that acquisition is lost — there is no generic way to hand it back (the same inherent limitation as a cancelled read that already pulled bytes).
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/winipc.rb', line 57 def run_blocking sched = Fiber.scheduler return yield unless sched worker = Thread.new do Thread.current.report_on_exception = false yield end begin worker.value ensure if worker.alive? worker.kill worker.join end end end |