forked from mrkite/minutor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchunkcache.cpp
131 lines (113 loc) · 3.83 KB
/
chunkcache.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/** Copyright (c) 2013, Sean Kasun */
#include "./chunkcache.h"
#include "./chunkloader.h"
#if defined(__unix__) || defined(__unix) || defined(unix)
#include <unistd.h>
#elif defined(_WIN32) || defined(WIN32)
#include <windows.h>
#endif
ChunkID::ChunkID(int cx, int cz) : cx(cx), cz(cz) {
}
bool ChunkID::operator==(const ChunkID &other) const {
return (other.cx == cx) && (other.cz == cz);
}
uint qHash(const ChunkID &c) {
return (c.cx << 16) ^ (c.cz & 0xffff); // safe way to hash a pair of integers
}
ChunkCache::ChunkCache() {
int chunks = 10000; // 10% more than 1920x1200 blocks
#if defined(__unix__) || defined(__unix) || defined(unix)
#ifdef _SC_AVPHYS_PAGES
auto pages = sysconf(_SC_AVPHYS_PAGES);
auto page_size = sysconf(_SC_PAGE_SIZE);
chunks = (pages*page_size) / (sizeof(Chunk) + 16*sizeof(ChunkSection));
#endif
#elif defined(_WIN32) || defined(WIN32)
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
DWORDLONG available = qMin(status.ullAvailPhys, status.ullAvailVirtual);
chunks = available / (sizeof(Chunk) + 16 * sizeof(ChunkSection));
#endif
cache.setMaxCost(chunks);
maxcache = 2 * chunks; // most chunks are less than half filled with sections
// determain optimal thread pool size for "loading"
// as this contains disk access, use less than number of cores
int tmax = loaderThreadPool.maxThreadCount();
loaderThreadPool.setMaxThreadCount(tmax / 2);
qRegisterMetaType<QSharedPointer<GeneratedStructure>>("QSharedPointer<GeneratedStructure>");
}
ChunkCache::~ChunkCache() {
loaderThreadPool.waitForDone();
}
ChunkCache& ChunkCache::Instance() {
static ChunkCache singleton;
return singleton;
}
void ChunkCache::clear() {
QThreadPool::globalInstance()->waitForDone();
mutex.lock();
cache.clear();
mutex.unlock();
}
void ChunkCache::setPath(QString path) {
if (this->path != path)
clear();
this->path = path;
}
QString ChunkCache::getPath() const {
return path;
}
int ChunkCache::getCost() const {
return cache.totalCost();
}
int ChunkCache::getMaxCost() const {
return cache.maxCost();
}
QSharedPointer<Chunk> ChunkCache::fetchCached(int cx, int cz) {
// try to get Chunk from Cache
ChunkID id(cx, cz);
mutex.lock();
QSharedPointer<Chunk> * p_chunk(cache[id]); // const operation
mutex.unlock();
if (p_chunk != NULL )
return QSharedPointer<Chunk>(*p_chunk);
else
return QSharedPointer<Chunk>(NULL); // we're loading this chunk, or it's blank.
}
QSharedPointer<Chunk> ChunkCache::fetch(int cx, int cz) {
// try to get Chunk from Cache
ChunkID id(cx, cz);
mutex.lock();
QSharedPointer<Chunk> * p_chunk(cache[id]); // const operation
mutex.unlock();
if (p_chunk != NULL ) {
QSharedPointer<Chunk> chunk(*p_chunk);
if (chunk->loaded)
return chunk;
return QSharedPointer<Chunk>(NULL); // we're loading this chunk, or it's blank.
}
// launch background process to load this chunk
p_chunk = new QSharedPointer<Chunk>(new Chunk());
connect(p_chunk->data(), SIGNAL(structureFound(QSharedPointer<GeneratedStructure>)),
this, SLOT (routeStructure(QSharedPointer<GeneratedStructure>)));
mutex.lock();
cache.insert(id, p_chunk); // non-const operation !
mutex.unlock();
ChunkLoader *loader = new ChunkLoader(path, cx, cz);
connect(loader, SIGNAL(loaded(int, int)),
this, SLOT(gotChunk(int, int)));
loaderThreadPool.start(loader);
return QSharedPointer<Chunk>(NULL);
}
void ChunkCache::gotChunk(int cx, int cz) {
emit chunkLoaded(cx, cz);
}
void ChunkCache::routeStructure(QSharedPointer<GeneratedStructure> structure) {
emit structureFound(structure);
}
void ChunkCache::adaptCacheToWindow(int wx, int wy) {
int chunks = ((wx + 15) >> 4) * ((wy + 15) >> 4); // number of chunks visible
chunks *= 1.10; // add 10%
cache.setMaxCost(qMin(chunks, maxcache));
}