#pragma once #include <stdint.h> #include <stdlib.h> #include <stddef.h> #include <stdio.h> #include <string.h> #include "../common/compat.hpp" #include "../threading/threadlocal.hpp" #ifndef _WIN32 # include <unistd.h> # include <sys/mman.h> #endif #ifndef SPRAWL_MEMORY_NO_FREE # define SPRAWL_MEMORY__RELEASE_EMPTY_BLOCKS 0 #endif #ifndef SPRAWL_FORCE_MALLOC # define SPRAWL_FORCE_MALLOC 0 #endif namespace sprawl { namespace memory { #if !SPRAWL_FORCE_MALLOC template<size_t sizeOfType> struct MemoryBit { void* allocType; MemoryBit* next; unsigned char data[sizeOfType]; }; #endif template<size_t sizeOfType> class PoolAllocator { public: static void* alloc(); static void* alloc(size_t count); static void free(void* addr); template<typename T> struct rebind { typedef PoolAllocator<sizeof(T)> otherAllocator; }; private: #if !SPRAWL_FORCE_MALLOC #if SPRAWL_MULTITHREADED static sprawl::threading::ThreadLocal<MemoryBit<sizeOfType>*> ms_firstBit; #else static MemoryBit<sizeOfType>* ms_firstBit; #endif static inline constexpr size_t max_(size_t a, size_t b) { return a < b ? b : a; } static inline constexpr size_t getPageSize_() { // TODO HACK: Assuming page size is 4096 because otherwise this gets into initialization order problems with global vars. return PoolAllocator::max_(4096, sizeOfType); } static constexpr size_t ms_blocksPerAlloc = PoolAllocator<sizeOfType>::max_(PoolAllocator<sizeOfType>::getPageSize_() / sizeof(MemoryBit<sizeOfType>), 32); static constexpr size_t ms_allocSize = ms_blocksPerAlloc * sizeof(MemoryBit<sizeOfType>); #endif }; #if !SPRAWL_FORCE_MALLOC #if SPRAWL_MULTITHREADED template<size_t sizeOfType> sprawl::threading::ThreadLocal<MemoryBit<sizeOfType>*> PoolAllocator<sizeOfType>::ms_firstBit; #else template<size_t sizeOfType> MemoryBit<sizeOfType>* PoolAllocator<sizeOfType>::ms_firstBit = nullptr; #endif #endif template<size_t sizeOfType> void* PoolAllocator<sizeOfType>::alloc(size_t count) { #if SPRAWL_FORCE_MALLOC return malloc(count*sizeOfType); #else void* ret = malloc(count*sizeOfType + (sizeof(intptr_t) * 2)); memset(ret, 1, sizeof(intptr_t) * 2); return reinterpret_cast<unsigned char*>(ret) + (sizeof(intptr_t) * 2); #endif } template<size_t sizeOfType> void* PoolAllocator<sizeOfType>::alloc() { #if SPRAWL_FORCE_MALLOC return malloc(sizeOfType); #else #if SPRAWL_MULTITHREADED MemoryBit<sizeOfType>* bit = *ms_firstBit; #else MemoryBit<sizeOfType>* bit = ms_firstBit; #endif if(bit) { ms_firstBit = bit->next; return bit->data; } MemoryBit<sizeOfType>* newBits = (MemoryBit<sizeOfType>*) #ifdef _WIN32 VirtualAlloc(nullptr, ms_allocSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); #else mmap(nullptr, ms_allocSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); #endif size_t const maxBlock = ms_blocksPerAlloc - 1; for(size_t i = 1; i < maxBlock; ++i) { newBits[i].allocType = 0; newBits[i].next = &newBits[i+1]; } newBits[maxBlock].allocType = 0; newBits[maxBlock].next = nullptr; newBits[0].allocType = 0; ms_firstBit = &newBits[1]; return newBits[0].data; #endif } template<size_t sizeOfType> void PoolAllocator<sizeOfType>::free(void* addr) { #if SPRAWL_FORCE_MALLOC ::free(addr); #else void* allocType = reinterpret_cast<void*>(reinterpret_cast<intptr_t*>(addr)[-2]); if(allocType == 0) { MemoryBit<sizeOfType>* bit = reinterpret_cast<MemoryBit<sizeOfType>*>(reinterpret_cast<intptr_t*>(addr)-2); #if SPRAWL_MULTITHREADED bit->next = *ms_firstBit; #else bit->next = ms_firstBit; #endif ms_firstBit = bit; } else { ::free(reinterpret_cast<intptr_t*>(addr)-2); } #endif } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 20951 | ShadauxCat |
- Reworked ConcurrentQueue::Dequeue to be a lot faster and wait-free - Added constexpr constructor for sprawl tag - Added support for specifying base for int-to-tag conversion - Added ability to force poolallocator to pass through to malloc - Added a helper class that will eventually be used in StringBuilder for faster int-to-string conversion #review-20952 post-commit |
||
#4 | 16052 | ShadauxCat |
- Changed default block size for concurrent queue to a more reasonable value - Changed some memory orders to memory_order_seq_cst when they don't actually need to be that to get around a bug in visual studio 2013 - debug builds assert when memory_order_acq_rel is used for a compare_exchange_strong (this is a standard library bug and is fixed in VS2015) - Added Event API - events are an alternative to condition variables that do not require a mutex and are guaranteed not to miss any signals, even if the signal comes while the thread is not listening for it. Unlike condition variables, however, they do not support broadcasting (and in fact, in general, are not safe to use with multiple threads listening for the same event simultaneously - though notifying on the same event is fine) - Rewrote ThreadManager around ConcurrentQueue and Event API so it is now lock-free. Also improved some behaviors of the staged thread manager operation so it now supports tasks that can be run on multiple stages via a bitmask. - Fixed an issue where the Coroutine copy constructor was calling the std::function constructor instead and another where initializing with a stack might try to call the wrong constructor and vice-versa - Fixed Coroutine never calling munmap() on its stack in linux and causing a memory leak - Added default arguments to time functions - Attempted to fix some issues with BinaryTree. Fixed some but not all. It's currently not suitable for use, sadly. - Logging Improvements: - - Added thread ID to logging - - Fixed some issues with category handlers - - Added backtraces - - Added the following additional log macros: - - - LOG_IF - - - LOG_EVERY_N - - - LOG_FIRST_N - - - LOG_IF_EVERY_N - - - LOG_IF_FIRST_N - - - LOG_ASSERT - - Added the ability to set extra info callbacks to get data such as script backtraces - - Removed the thread-related handlers and replaced them with RunHandler_Threaded and RunHandler_ThreadManager, which will enable any passed-in handler to be run in a threaded fashion - Removed StaticPoolAllocator and renamed DynamicPoolAllocator to PoolAllocator; adjusted unit tests accordingly - PoolAllocator now allocates its pool with mmap and VirtualAlloc, rather than with malloc - Fixed a bug with Vector copy assignment operator - Improved performance of StringBuilder considerably for cases where there are no modifier strings - Removed Copy-On-Write behavior of JSONToken as it was broken; copies are now performed with explicit DeepCopy() and ShallowCopy() functions - Fixed some parser bugs with JSONToken - Added iteration to JSONToken to iterate its children - Fixed crash when reading a negative number of bytes from a file - Changed StringBuilder to favor speed instead of memory by default - Added some performance unit tests for JSON token #review-16053 |
||
#3 | 13650 | ShadauxCat |
- Windows implementations of thread and time libraries - Added coroutines - Added some more unit tests, fixed some unit tests in windows environments - Fixed an issue where multi threading was not properly detected on Linux - Fixed the makefiles to build with threading by default on linux - Changed the pool allocator to use thread-local pools instead of locking mutexes - Fixed output of sprawl::string in the StringBuilder library to take length into account - Added string builder options for StringLiteral - Added thread local implementation #review |
||
#2 | 12508 | ShadauxCat |
-Added threading library. Currently only functional for Linux; Windows will fail to link. (I will fix this soon.) -Fixed missing move and copy constructors in List and ForwardList -Fixed broken move constructor in HashMap -Fixed missing const get() in HashMap -Fixed broken operator-> in ListIterator -Added sprawl::noncopyable -Added sketch headers for filesystem library -Made StringLiteral hashable, added special hashes for pointers and integers in murmur3 -Fixed compiler warning in async_network -Updated memory allocators to use new threading library for mutexes -Added accessibility to sprawl::StringLiteral to be able toa ccess its pointer and length and perform pointer comparisons #review-12504 |
||
#1 | 11496 | ShadauxCat | Initial checkin: Current states for csbuild and libSprawl |