openMSX
PreCacheFile.cc
Go to the documentation of this file.
1#include "PreCacheFile.hh"
2
3#include "FileOperations.hh"
4
5#include "narrow.hh"
6
7#include <array>
8#include <cstdio>
9#include <sys/types.h>
10
11namespace openmsx {
12
13// TODO when available use:
14// posix_fadvise(int fd, off_t offset, off_t len, int advise)
15// with advise = POSIX_FADV_WILLNEED
16
18 : name(std::move(name_))
19{
20 thread = std::thread([this]() { run(); });
21}
22
24{
25 exitLoop = true;
26 thread.join();
27}
28
29void PreCacheFile::run() const
30{
32 // don't pre-cache non regular files (e.g. /dev/fd0)
33 return;
34 }
35
36 auto file = FileOperations::openFile(name, "rb");
37 if (!file) return;
38
39 fseek(file.get(), 0, SEEK_END);
40 auto size = ftell(file.get());
41 if (size < 1024L * 1024L) {
42 // only pre-cache small files
43
44 const size_t BLOCK_SIZE = 4096;
45 unsigned block = 0;
46 unsigned repeat = 0;
47 while (true) {
48 if (exitLoop) break;
49
50 std::array<char, BLOCK_SIZE> buf;
51 if (fseek(file.get(), narrow_cast<long>(block * BLOCK_SIZE), SEEK_SET)) break;
52 if (size_t read = fread(buf.data(), 1, BLOCK_SIZE, file.get());
53 read != BLOCK_SIZE) {
54 // error or end-of-file reached,
55 // in both cases stop pre-caching
56 break;
57 }
58
59 // Just reading a file linearly from front to back
60 // makes Linux classify the read as a 'streaming read'.
61 // Linux doesn't cache those. To avoid this we read
62 // some of the blocks twice.
63 if (repeat != 0) {
64 --repeat; ++block;
65 } else {
66 repeat = 5;
67 }
68 }
69 }
70}
71
72} // namespace openmsx
PreCacheFile(std::string name)
bool isRegularFile(const Stat &st)
FILE_t openFile(zstring_view filename, zstring_view mode)
Call fopen() in a platform-independent manner.
This file implemented 3 utility functions:
Definition Autofire.cc:11
STL namespace.
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
Definition xrange.hh:147