Changeset View
Changeset View
Standalone View
Standalone View
src/support/lockedpool.cpp
Show First 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
Arena::~Arena() {} | Arena::~Arena() {} | ||||
void *Arena::alloc(size_t size) { | void *Arena::alloc(size_t size) { | ||||
// Round to next multiple of alignment | // Round to next multiple of alignment | ||||
size = align_up(size, alignment); | size = align_up(size, alignment); | ||||
// Don't handle zero-sized chunks | // Don't handle zero-sized chunks | ||||
if (size == 0) return nullptr; | if (size == 0) { | ||||
return nullptr; | |||||
} | |||||
// Pick a large enough free-chunk | // Pick a large enough free-chunk | ||||
auto it = | auto it = | ||||
std::find_if(chunks_free.begin(), chunks_free.end(), | std::find_if(chunks_free.begin(), chunks_free.end(), | ||||
[=](const std::map<char *, size_t>::value_type &chunk) { | [=](const std::map<char *, size_t>::value_type &chunk) { | ||||
return chunk.second >= size; | return chunk.second >= size; | ||||
}); | }); | ||||
if (it == chunks_free.end()) return nullptr; | if (it == chunks_free.end()) { | ||||
return nullptr; | |||||
} | |||||
// Create the used-chunk, taking its space from the end of the free-chunk | // Create the used-chunk, taking its space from the end of the free-chunk | ||||
auto alloced = | auto alloced = | ||||
chunks_used.emplace(it->first + it->second - size, size).first; | chunks_used.emplace(it->first + it->second - size, size).first; | ||||
if (!(it->second -= size)) chunks_free.erase(it); | if (!(it->second -= size)) { | ||||
chunks_free.erase(it); | |||||
} | |||||
return reinterpret_cast<void *>(alloced->first); | return reinterpret_cast<void *>(alloced->first); | ||||
} | } | ||||
/* extend the Iterator if other begins at its end */ | /* extend the Iterator if other begins at its end */ | ||||
template <class Iterator, class Pair> | template <class Iterator, class Pair> | ||||
bool extend(Iterator it, const Pair &other) { | bool extend(Iterator it, const Pair &other) { | ||||
if (it->first + it->second == other.first) { | if (it->first + it->second == other.first) { | ||||
it->second += other.second; | it->second += other.second; | ||||
Show All 15 Lines | void Arena::free(void *ptr) { | ||||
} | } | ||||
auto freed = *i; | auto freed = *i; | ||||
chunks_used.erase(i); | chunks_used.erase(i); | ||||
// Add space to free map, coalescing contiguous chunks | // Add space to free map, coalescing contiguous chunks | ||||
auto next = chunks_free.upper_bound(freed.first); | auto next = chunks_free.upper_bound(freed.first); | ||||
auto prev = | auto prev = | ||||
(next == chunks_free.begin()) ? chunks_free.end() : std::prev(next); | (next == chunks_free.begin()) ? chunks_free.end() : std::prev(next); | ||||
if (prev == chunks_free.end() || !extend(prev, freed)) | if (prev == chunks_free.end() || !extend(prev, freed)) { | ||||
prev = chunks_free.emplace_hint(next, freed); | prev = chunks_free.emplace_hint(next, freed); | ||||
if (next != chunks_free.end() && extend(prev, *next)) | } | ||||
if (next != chunks_free.end() && extend(prev, *next)) { | |||||
chunks_free.erase(next); | chunks_free.erase(next); | ||||
} | } | ||||
} | |||||
Arena::Stats Arena::stats() const { | Arena::Stats Arena::stats() const { | ||||
Arena::Stats r{0, 0, 0, chunks_used.size(), chunks_free.size()}; | Arena::Stats r{0, 0, 0, chunks_used.size(), chunks_free.size()}; | ||||
for (const auto &chunk : chunks_used) | for (const auto &chunk : chunks_used) { | ||||
r.used += chunk.second; | r.used += chunk.second; | ||||
for (const auto &chunk : chunks_free) | } | ||||
for (const auto &chunk : chunks_free) { | |||||
r.free += chunk.second; | r.free += chunk.second; | ||||
} | |||||
r.total = r.used + r.free; | r.total = r.used + r.free; | ||||
return r; | return r; | ||||
} | } | ||||
#ifdef ARENA_DEBUG | #ifdef ARENA_DEBUG | ||||
static void printchunk(char *base, size_t sz, bool used) { | static void printchunk(char *base, size_t sz, bool used) { | ||||
std::cout << "0x" << std::hex << std::setw(16) << std::setfill('0') << base | std::cout << "0x" << std::hex << std::setw(16) << std::setfill('0') << base | ||||
<< " 0x" << std::hex << std::setw(16) << std::setfill('0') << sz | << " 0x" << std::hex << std::setw(16) << std::setfill('0') << sz | ||||
<< " 0x" << used << std::endl; | << " 0x" << used << std::endl; | ||||
} | } | ||||
void Arena::walk() const { | void Arena::walk() const { | ||||
for (const auto &chunk : chunks_used) | for (const auto &chunk : chunks_used) { | ||||
printchunk(chunk.first, chunk.second, true); | printchunk(chunk.first, chunk.second, true); | ||||
} | |||||
std::cout << std::endl; | std::cout << std::endl; | ||||
for (const auto &chunk : chunks_free) | for (const auto &chunk : chunks_free) { | ||||
printchunk(chunk.first, chunk.second, false); | printchunk(chunk.first, chunk.second, false); | ||||
} | |||||
std::cout << std::endl; | std::cout << std::endl; | ||||
} | } | ||||
#endif | #endif | ||||
/*******************************************************************************/ | /*******************************************************************************/ | ||||
// Implementation: Win32LockedPageAllocator | // Implementation: Win32LockedPageAllocator | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | LockedPool::LockedPool(std::unique_ptr<LockedPageAllocator> allocator_in, | ||||
: allocator(std::move(allocator_in)), lf_cb(lf_cb_in), | : allocator(std::move(allocator_in)), lf_cb(lf_cb_in), | ||||
cumulative_bytes_locked(0) {} | cumulative_bytes_locked(0) {} | ||||
LockedPool::~LockedPool() {} | LockedPool::~LockedPool() {} | ||||
void *LockedPool::alloc(size_t size) { | void *LockedPool::alloc(size_t size) { | ||||
std::lock_guard<std::mutex> lock(mutex); | std::lock_guard<std::mutex> lock(mutex); | ||||
// Don't handle impossible sizes | // Don't handle impossible sizes | ||||
if (size == 0 || size > ARENA_SIZE) return nullptr; | if (size == 0 || size > ARENA_SIZE) { | ||||
return nullptr; | |||||
} | |||||
// Try allocating from each current arena | // Try allocating from each current arena | ||||
for (auto &arena : arenas) { | for (auto &arena : arenas) { | ||||
void *addr = arena.alloc(size); | void *addr = arena.alloc(size); | ||||
if (addr) { | if (addr) { | ||||
return addr; | return addr; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 103 Lines • Show Last 20 Lines |