mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
[os2]: Implement pipe_has_data procedure
This commit is contained in:
@@ -55,13 +55,15 @@ _get_platform_error :: proc() -> Error {
|
|||||||
case win32.ERROR_NEGATIVE_SEEK:
|
case win32.ERROR_NEGATIVE_SEEK:
|
||||||
return .Invalid_Offset
|
return .Invalid_Offset
|
||||||
|
|
||||||
|
case win32.ERROR_BROKEN_PIPE:
|
||||||
|
return .Broken_Pipe
|
||||||
|
|
||||||
case
|
case
|
||||||
win32.ERROR_BAD_ARGUMENTS,
|
win32.ERROR_BAD_ARGUMENTS,
|
||||||
win32.ERROR_INVALID_PARAMETER,
|
win32.ERROR_INVALID_PARAMETER,
|
||||||
win32.ERROR_NOT_ENOUGH_MEMORY,
|
win32.ERROR_NOT_ENOUGH_MEMORY,
|
||||||
win32.ERROR_NO_MORE_FILES,
|
win32.ERROR_NO_MORE_FILES,
|
||||||
win32.ERROR_LOCK_VIOLATION,
|
win32.ERROR_LOCK_VIOLATION,
|
||||||
win32.ERROR_BROKEN_PIPE,
|
|
||||||
win32.ERROR_CALL_NOT_IMPLEMENTED,
|
win32.ERROR_CALL_NOT_IMPLEMENTED,
|
||||||
win32.ERROR_INSUFFICIENT_BUFFER,
|
win32.ERROR_INSUFFICIENT_BUFFER,
|
||||||
win32.ERROR_INVALID_NAME,
|
win32.ERROR_INVALID_NAME,
|
||||||
|
|||||||
@@ -1,6 +1,43 @@
|
|||||||
package os2
|
package os2
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create an anonymous pipe.
|
||||||
|
|
||||||
|
This procedure creates an anonymous pipe, returning two ends of the pipe, `r`
|
||||||
|
and `w`. The file `r` is the readable end of the pipe. The file `w` is a
|
||||||
|
writeable end of the pipe.
|
||||||
|
|
||||||
|
Pipes are used as an inter-process communication mechanism, to communicate
|
||||||
|
between a parent and a child process. The child uses one end of the pipe to
|
||||||
|
write data, and the parent uses the other end to read from the pipe
|
||||||
|
(or vice-versa). When a parent passes one of the ends of the pipe to the child
|
||||||
|
process, that end of the pipe needs to be closed by the parent, before any data
|
||||||
|
is attempted to be read.
|
||||||
|
|
||||||
|
Although pipes look like files and is compatible with most file APIs in package
|
||||||
|
os2, the way it's meant to be read is different. Due to asynchronous nature of
|
||||||
|
the communication channel, the data may not be present at the time of a read
|
||||||
|
request. The other scenario is when a pipe has no data because the other end
|
||||||
|
of the pipe was closed by the child process.
|
||||||
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
pipe :: proc() -> (r, w: ^File, err: Error) {
|
pipe :: proc() -> (r, w: ^File, err: Error) {
|
||||||
return _pipe()
|
return _pipe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if the pipe has any data.
|
||||||
|
|
||||||
|
This procedure checks whether a read-end of the pipe has data that can be
|
||||||
|
read, and returns `true`, if the pipe has readable data, and `false` if the
|
||||||
|
pipe is empty. This procedure does not block the execution of the current
|
||||||
|
thread.
|
||||||
|
|
||||||
|
**Note**: If the other end of the pipe was closed by the child process, the
|
||||||
|
`.Broken_Pipe`
|
||||||
|
can be returned by this procedure. Handle these errors accordingly.
|
||||||
|
*/
|
||||||
|
@(require_results)
|
||||||
|
pipe_has_data :: proc(r: ^File) -> (ok: bool, err: Error) {
|
||||||
|
return _pipe_has_data(r)
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,3 +15,29 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(require_results)
|
||||||
|
_pipe_has_data :: proc(r: ^File) -> (ok: bool, err: Error) {
|
||||||
|
if r == nil || r.impl == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
fd := linux.Fd((^File_Impl)(r.impl).fd)
|
||||||
|
poll_fds := []linux.Poll_Fd {
|
||||||
|
linux.Poll_Fd {
|
||||||
|
fd = fd,
|
||||||
|
events = {.IN, .HUP},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
n, errno := linux.poll(poll_fds, 0)
|
||||||
|
if n != 1 || errno != nil {
|
||||||
|
return false, _get_platform_error(errno)
|
||||||
|
}
|
||||||
|
pipe_events := poll_fds[0].revents
|
||||||
|
if pipe_events >= {.IN} {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
if pipe_events >= {.HUP} {
|
||||||
|
return false, .Broken_Pipe
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
@@ -44,3 +44,28 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(require_results)
|
||||||
|
_pipe_has_data :: proc(r: ^File) -> (ok: bool, err: Error) {
|
||||||
|
if r == nil || r.impl == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
fd := posix.FD((^File_Impl)(r.impl).fd)
|
||||||
|
poll_fds := []posix.pollfd {
|
||||||
|
posix.pollfd {
|
||||||
|
fd = fd,
|
||||||
|
events = {.IN, .HUP},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
n := posix.poll(raw_data(poll_fds), u32(len(poll_fds)), 0)
|
||||||
|
if n != 1 {
|
||||||
|
return false, _get_platform_error()
|
||||||
|
}
|
||||||
|
pipe_events := poll_fds[0].revents
|
||||||
|
if pipe_events >= {.IN} {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
if pipe_events >= {.HUP} {
|
||||||
|
return false, .Broken_Pipe
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
@@ -15,3 +15,15 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
|
|||||||
return new_file(uintptr(p[0]), ""), new_file(uintptr(p[1]), ""), nil
|
return new_file(uintptr(p[0]), ""), new_file(uintptr(p[1]), ""), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(require_results)
|
||||||
|
_pipe_has_data :: proc(r: ^File) -> (ok: bool, err: Error) {
|
||||||
|
if r == nil || r.impl == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
handle := win32.HANDLE((^File_Impl)(r.impl).fd)
|
||||||
|
bytes_available: u32
|
||||||
|
if !win32.PeekNamedPipe(handle, nil, 0, nil, &bytes_available, nil) {
|
||||||
|
return false, _get_platform_error()
|
||||||
|
}
|
||||||
|
return bytes_available > 0, nil
|
||||||
|
}
|
||||||
@@ -381,6 +381,14 @@ foreign kernel32 {
|
|||||||
nDefaultTimeOut: DWORD,
|
nDefaultTimeOut: DWORD,
|
||||||
lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
|
lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
|
||||||
) -> HANDLE ---
|
) -> HANDLE ---
|
||||||
|
PeekNamedPipe :: proc(
|
||||||
|
hNamedPipe: HANDLE,
|
||||||
|
lpBuffer: rawptr,
|
||||||
|
nBufferSize: u32,
|
||||||
|
lpBytesRead: ^u32,
|
||||||
|
lpTotalBytesAvail: ^u32,
|
||||||
|
lpBytesLeftThisMessage: ^u32,
|
||||||
|
) -> BOOL ---
|
||||||
CancelIo :: proc(handle: HANDLE) -> BOOL ---
|
CancelIo :: proc(handle: HANDLE) -> BOOL ---
|
||||||
GetOverlappedResult :: proc(
|
GetOverlappedResult :: proc(
|
||||||
hFile: HANDLE,
|
hFile: HANDLE,
|
||||||
|
|||||||
Reference in New Issue
Block a user