Merge bitcoin/bitcoin#16195: util: Use void* throughout support/lockedpool.h

f36d1d5b8934aac60d3097047ecedeb58bae2185 Use void* throughout support/lockedpool.h (Jeffrey Czyz)

Pull request description:

  Replace uses of char* with void* in Arena's member variables. Instead,
  cast to char* where needed in the implementation.

  Certain compiler environments disallow std::hash<char*> specializations
  to prevent hashing the pointer's value instead of the string contents.
  Thus, compilation fails when std::unordered_map is keyed by char*.

  Explicitly using void* is a workaround in such environments. For
  consistency, void* is used throughout all member variables similarly to
  the public interface.

  Changes to this code are covered by src/test/allocator_tests.cpp.

ACKs for top commit:
  achow101:
    ACK f36d1d5b8934aac60d3097047ecedeb58bae2185
  theStack:
    Code-review ACK f36d1d5b8934aac60d3097047ecedeb58bae2185
  jonatack:
    ACK f36d1d5b8934aac60d3097047ecedeb58bae2185 review, debug build, unit tests, checked clang 15 raises "error: arithmetic on a pointer to void"  without the conversions here from the generic void* pointer back to char*

Tree-SHA512: f9074e6d29ef78c795a512a6e00e9b591e2ff34165d09b73eae9eef25098c59e543c194346fcd4e83185a39c430d43744b6f7f9d1728a132843c67bd27ea5189
This commit is contained in:
Andrew Chow 2023-02-23 15:33:07 -05:00 committed by pasta
parent c66c0fdbf8
commit f5b4cc7e32
No known key found for this signature in database
GPG Key ID: E2F3D7916E722D38
2 changed files with 15 additions and 13 deletions

View File

@ -27,6 +27,7 @@
#include <iomanip>
#include <iostream>
#endif
#include <utility>
LockedPoolManager* LockedPoolManager::_instance = nullptr;
@ -43,12 +44,12 @@ static inline size_t align_up(size_t x, size_t align)
// Implementation: Arena
Arena::Arena(void *base_in, size_t size_in, size_t alignment_in):
base(static_cast<char*>(base_in)), end(static_cast<char*>(base_in) + size_in), alignment(alignment_in)
base(base_in), end(static_cast<char*>(base_in) + size_in), alignment(alignment_in)
{
// Start with one free chunk that covers the entire arena
auto it = size_to_free_chunk.emplace(size_in, base);
chunks_free.emplace(base, it);
chunks_free_end.emplace(base + size_in, it);
chunks_free_end.emplace(static_cast<char*>(base) + size_in, it);
}
Arena::~Arena()
@ -74,8 +75,9 @@ void* Arena::alloc(size_t size)
// Create the used-chunk, taking its space from the end of the free-chunk
const size_t size_remaining = size_ptr_it->first - size;
auto allocated = chunks_used.emplace(size_ptr_it->second + size_remaining, size).first;
chunks_free_end.erase(size_ptr_it->second + size_ptr_it->first);
char* const free_chunk = static_cast<char*>(size_ptr_it->second);
auto allocated = chunks_used.emplace(free_chunk + size_remaining, size).first;
chunks_free_end.erase(free_chunk + size_ptr_it->first);
if (size_ptr_it->first == size) {
// whole chunk is used up
chunks_free.erase(size_ptr_it->second);
@ -83,11 +85,11 @@ void* Arena::alloc(size_t size)
// still some memory left in the chunk
auto it_remaining = size_to_free_chunk.emplace(size_remaining, size_ptr_it->second);
chunks_free[size_ptr_it->second] = it_remaining;
chunks_free_end.emplace(size_ptr_it->second + size_remaining, it_remaining);
chunks_free_end.emplace(free_chunk + size_remaining, it_remaining);
}
size_to_free_chunk.erase(size_ptr_it);
return reinterpret_cast<void*>(allocated->first);
return allocated->first;
}
void Arena::free(void *ptr)
@ -98,11 +100,11 @@ void Arena::free(void *ptr)
}
// Remove chunk from used map
auto i = chunks_used.find(static_cast<char*>(ptr));
auto i = chunks_used.find(ptr);
if (i == chunks_used.end()) {
throw std::runtime_error("Arena: invalid or double free");
}
std::pair<char*, size_t> freed = *i;
auto freed = std::make_pair(static_cast<char*>(i->first), i->second);
chunks_used.erase(i);
// coalesce freed with previous chunk

View File

@ -89,23 +89,23 @@ public:
*/
bool addressInArena(void *ptr) const { return ptr >= base && ptr < end; }
private:
typedef std::multimap<size_t, char*> SizeToChunkSortedMap;
typedef std::multimap<size_t, void*> SizeToChunkSortedMap;
/** Map to enable O(log(n)) best-fit allocation, as it's sorted by size */
SizeToChunkSortedMap size_to_free_chunk;
typedef std::unordered_map<char*, SizeToChunkSortedMap::const_iterator> ChunkToSizeMap;
typedef std::unordered_map<void*, SizeToChunkSortedMap::const_iterator> ChunkToSizeMap;
/** Map from begin of free chunk to its node in size_to_free_chunk */
ChunkToSizeMap chunks_free;
/** Map from end of free chunk to its node in size_to_free_chunk */
ChunkToSizeMap chunks_free_end;
/** Map from begin of used chunk to its size */
std::unordered_map<char*, size_t> chunks_used;
std::unordered_map<void*, size_t> chunks_used;
/** Base address of arena */
char* base;
void* base;
/** End address of arena */
char* end;
void* end;
/** Minimum chunk alignment */
size_t alignment;
};