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
Copyright © 2023-2025 Amebis
*/
@ -2222,19 +2222,17 @@ namespace stdex
_Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t 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.
// 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.
size_t
#if defined(_WIN64)
#ifdef _WIN64
block_size = 0x1F80000;
#elif defined(_WIN32)
block_size = 0x3f00000;
#else
block_size = SSIZE_MAX;
block_size = 0x3f00000;
#endif
for (size_t to_read = length;;) {
#ifdef _WIN32
// ReadFile() might raise exception (e.g. STATUS_FILE_BAD_FORMAT/0xE0000002).
BOOL succeeded;
DWORD num_read;
@ -2246,12 +2244,7 @@ namespace stdex
block_size = default_block_size;
continue;
}
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
{
if (!succeeded) _Unlikely_ {
m_state = to_read < length ? state_t::ok : state_t::fail;
return length - to_read;
}
@ -2266,6 +2259,19 @@ namespace stdex
}
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(