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