Are there equivalents to pread on different platforms?

后端 未结 3 370
梦毁少年i
梦毁少年i 2021-01-19 11:20

I am writing a concurrent, persistent message queue in C++, which requires concurrent read access to a file without using memory mapped io. Short story is that several threa

相关标签:
3条回答
  • 2021-01-19 11:32

    On Windows, the ReadFile() function can do it, see the lpOverlapped parameter and this info on async IO.

    0 讨论(0)
  • 2021-01-19 11:42

    With NIO, java.nio.channels.FileChannel has a read(ByteBuffer dst, long position) method, which internally uses pread.

    Oh wait, your question is about C++, not Java. Well, I just looked at the JDK source code to see how it does it for Windows, but unfortunately on Windows it isn't atomic: it simply seeks, then reads, then seeks back.

    For Unix platforms, the punchline is that pread is standard for any XSI-supporting (X/Open System Interface, apparently) operating system: http://www.opengroup.org/onlinepubs/009695399/functions/pread.html

    0 讨论(0)
  • 2021-01-19 11:46

    Based on another answer, the closest I could come up with is this. However, there is a bug: ReadFile will change the file offset, and pread is guaranteed to not change the file offset. There's no real way to fix this, because code can do normal read() and write() concurrently with no lock. Anybody found a call that will not change the offset?

    unsigned int FakePRead(int fd, void *to, std::size_t size, uint64_offset) {
      // size_t might be 64-bit.  DWORD is always 32.
      const std::size_t kMax = static_cast<std::size_t>(1UL << 31);
      DWORD reading = static_cast<DWORD>(std::min<std::size_t>(kMax, size));
      DWORD ret;
      OVERLAPPED overlapped;
      memset(&overlapped, 0, sizeof(OVERLAPPED));
      overlapped.Offset = static_cast<DWORD>(off);
      overlapped.OffsetHigh = static_cast<DWORD>(off >> 32);
      if (!ReadFile((HANDLE)_get_osfhandle(fd), to, reading, &ret, &overlapped)) {
        // TODO: set errno to something?
        return -1;
      }
      // Note the limit to 1 << 31 before.
      return static_cast<unsigned int>(ret);
    }
    
    0 讨论(0)
提交回复
热议问题