stream: read from system stream once on POSIX

Looping ReadFile() system call is Windows-specific. POSIX systems don't
need this. In fact: with pipes using buffered streams, this blocks the
read until one full buffer of data is available.

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2025-06-02 14:22:44 +02:00
parent 7bb614a34f
commit 862c073ca8

View File

@ -1,4 +1,4 @@
/* /*
SPDX-License-Identifier: MIT SPDX-License-Identifier: MIT
Copyright © 2023-2025 Amebis Copyright © 2023-2025 Amebis
*/ */
@ -2222,19 +2222,17 @@ namespace stdex
_Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length) _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
{ {
stdex_assert(data || !length); stdex_assert(data || !length);
#ifdef _WIN32
// Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write. // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
// The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
// it's 63.95 MB. For more information regarding pipes, see the Remarks section. // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
size_t size_t
#if defined(_WIN64) #ifdef _WIN64
block_size = 0x1F80000; block_size = 0x1F80000;
#elif defined(_WIN32)
block_size = 0x3f00000;
#else #else
block_size = SSIZE_MAX; block_size = 0x3f00000;
#endif #endif
for (size_t to_read = length;;) { for (size_t to_read = length;;) {
#ifdef _WIN32
// ReadFile() might raise exception (e.g. STATUS_FILE_BAD_FORMAT/0xE0000002). // ReadFile() might raise exception (e.g. STATUS_FILE_BAD_FORMAT/0xE0000002).
BOOL succeeded; BOOL succeeded;
DWORD num_read; DWORD num_read;
@ -2246,12 +2244,7 @@ namespace stdex
block_size = default_block_size; block_size = default_block_size;
continue; continue;
} }
if (!succeeded) _Unlikely_ if (!succeeded) _Unlikely_ {
#else
auto num_read = ::read(m_h, data, std::min<size_t>(to_read, block_size));
if (num_read < 0) _Unlikely_
#endif
{
m_state = to_read < length ? state_t::ok : state_t::fail; m_state = to_read < length ? state_t::ok : state_t::fail;
return length - to_read; return length - to_read;
} }
@ -2266,6 +2259,19 @@ namespace stdex
} }
reinterpret_cast<uint8_t*&>(data) += num_read; reinterpret_cast<uint8_t*&>(data) += num_read;
} }
#else
auto num_read = ::read(m_h, data, length);
if (num_read < 0) _Unlikely_ {
m_state = state_t::fail;
return 0;
}
if (!num_read) _Unlikely_ {
m_state = !length ? state_t::ok : state_t::eof;
return 0;
}
m_state = state_t::ok;
return num_read;
#endif
} }
virtual _Success_(return != 0) size_t write( virtual _Success_(return != 0) size_t write(