Implement a substitute for aligned-new
This commit is contained in:
parent
e7aecec06b
commit
0041432d83
7 changed files with 86 additions and 17 deletions
|
|
@ -51,10 +51,6 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
add_compile_options(-mfloat-abi=hard)
|
add_compile_options(-mfloat-abi=hard)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
check_cxx_compiler_flag(-faligned-new SFIZZ_HAVE_FALIGNED_NEW)
|
|
||||||
if(SFIZZ_HAVE_FALIGNED_NEW)
|
|
||||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-faligned-new>)
|
|
||||||
endif()
|
|
||||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
add_compile_options(/Zc:__cplusplus)
|
add_compile_options(/Zc:__cplusplus)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ set(SFIZZ_HEADERS
|
||||||
sfizz/utility/Debug.h
|
sfizz/utility/Debug.h
|
||||||
sfizz/utility/LeakDetector.h
|
sfizz/utility/LeakDetector.h
|
||||||
sfizz/utility/Macros.h
|
sfizz/utility/Macros.h
|
||||||
|
sfizz/utility/MemoryHelpers.h
|
||||||
sfizz/utility/NumericId.h
|
sfizz/utility/NumericId.h
|
||||||
sfizz/utility/StringViewHelpers.h
|
sfizz/utility/StringViewHelpers.h
|
||||||
sfizz/utility/SwapAndPop.h
|
sfizz/utility/SwapAndPop.h
|
||||||
|
|
@ -285,8 +286,8 @@ add_library(sfizz::internal ALIAS sfizz_internal)
|
||||||
target_sources(sfizz_internal PRIVATE ${SFIZZ_HEADERS} ${SFIZZ_SOURCES} ${FAUST_FILES})
|
target_sources(sfizz_internal PRIVATE ${SFIZZ_HEADERS} ${SFIZZ_SOURCES} ${FAUST_FILES})
|
||||||
target_include_directories(sfizz_internal PUBLIC "." "sfizz")
|
target_include_directories(sfizz_internal PUBLIC "." "sfizz")
|
||||||
target_link_libraries(sfizz_internal
|
target_link_libraries(sfizz_internal
|
||||||
PUBLIC absl::strings absl::span sfizz::filesystem sfizz::atomic_queue sfizz::spin_mutex sfizz::bit_array sfizz::simde sfizz::hiir
|
PUBLIC absl::strings absl::span sfizz::filesystem sfizz::atomic_queue sfizz::spin_mutex sfizz::bit_array sfizz::simde sfizz::hiir sfizz::jsl
|
||||||
PRIVATE sfizz::parser sfizz::messaging absl::flat_hash_map Threads::Threads st_audiofile sfizz::pugixml sfizz::spline sfizz::tunings sfizz::kissfft sfizz::cephes sfizz::cpuid sfizz::threadpool sfizz::jsl sfizz::atomic)
|
PRIVATE sfizz::parser sfizz::messaging absl::flat_hash_map Threads::Threads st_audiofile sfizz::pugixml sfizz::spline sfizz::tunings sfizz::kissfft sfizz::cephes sfizz::cpuid sfizz::threadpool sfizz::atomic)
|
||||||
if(SFIZZ_USE_SNDFILE)
|
if(SFIZZ_USE_SNDFILE)
|
||||||
target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_USE_SNDFILE=1")
|
target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_USE_SNDFILE=1")
|
||||||
target_link_libraries(sfizz_internal PUBLIC st_audiofile)
|
target_link_libraries(sfizz_internal PUBLIC st_audiofile)
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,9 @@ void streamFromFile(sfz::AudioReader& reader, uint32_t numFrames, sfz::Oversampl
|
||||||
}
|
}
|
||||||
|
|
||||||
sfz::FilePool::FilePool(sfz::Logger& logger)
|
sfz::FilePool::FilePool(sfz::Logger& logger)
|
||||||
: logger(logger), threadPool(globalThreadPool())
|
: logger(logger),
|
||||||
|
filesToLoad(alignedNew<FileQueue>()),
|
||||||
|
threadPool(globalThreadPool())
|
||||||
{
|
{
|
||||||
loadingJobs.reserve(config::maxVoices);
|
loadingJobs.reserve(config::maxVoices);
|
||||||
lastUsedFiles.reserve(config::maxVoices);
|
lastUsedFiles.reserve(config::maxVoices);
|
||||||
|
|
@ -350,8 +352,8 @@ sfz::FileDataHolder sfz::FilePool::getFilePromise(const std::shared_ptr<FileId>&
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
QueuedFileData queuedData { fileId, &preloaded->second, std::chrono::high_resolution_clock::now() };
|
QueuedFileData queuedData { fileId, &preloaded->second, std::chrono::high_resolution_clock::now() };
|
||||||
if (!filesToLoad.try_push(queuedData)) {
|
if (!filesToLoad->try_push(queuedData)) {
|
||||||
DBG("[sfizz] Could not enqueue the file to load for " << fileId << " (queue capacity " << filesToLoad.capacity() << ")");
|
DBG("[sfizz] Could not enqueue the file to load for " << fileId << " (queue capacity " << filesToLoad->capacity() << ")");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -498,7 +500,7 @@ void sfz::FilePool::dispatchingJob() noexcept
|
||||||
while (dispatchBarrier.wait(), dispatchFlag) {
|
while (dispatchBarrier.wait(), dispatchFlag) {
|
||||||
std::lock_guard<std::mutex> guard { loadingJobsMutex };
|
std::lock_guard<std::mutex> guard { loadingJobsMutex };
|
||||||
|
|
||||||
if (filesToLoad.try_pop(queuedData)) {
|
if (filesToLoad->try_pop(queuedData)) {
|
||||||
if (queuedData.id.expired()) {
|
if (queuedData.id.expired()) {
|
||||||
// file ID was nulled, it means the region was deleted, ignore
|
// file ID was nulled, it means the region was deleted, ignore
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "SpinMutex.h"
|
#include "SpinMutex.h"
|
||||||
#include "utility/LeakDetector.h"
|
#include "utility/LeakDetector.h"
|
||||||
|
#include "utility/MemoryHelpers.h"
|
||||||
#include <ghc/fs_std.hpp>
|
#include <ghc/fs_std.hpp>
|
||||||
#include <absl/container/flat_hash_map.h>
|
#include <absl/container/flat_hash_map.h>
|
||||||
#include <absl/types/optional.h>
|
#include <absl/types/optional.h>
|
||||||
|
|
@ -43,6 +44,7 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <memory>
|
||||||
class ThreadPool;
|
class ThreadPool;
|
||||||
|
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
|
|
@ -348,7 +350,10 @@ private:
|
||||||
FileData* data { nullptr };
|
FileData* data { nullptr };
|
||||||
TimePoint queuedTime {};
|
TimePoint queuedTime {};
|
||||||
};
|
};
|
||||||
atomic_queue::AtomicQueue2<QueuedFileData, config::maxVoices> filesToLoad;
|
|
||||||
|
using FileQueue = atomic_queue::AtomicQueue2<QueuedFileData, config::maxVoices>;
|
||||||
|
aligned_unique_ptr<FileQueue> filesToLoad;
|
||||||
|
|
||||||
void dispatchingJob() noexcept;
|
void dispatchingJob() noexcept;
|
||||||
void garbageJob() noexcept;
|
void garbageJob() noexcept;
|
||||||
void loadingJob(QueuedFileData data) noexcept;
|
void loadingJob(QueuedFileData data) noexcept;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ void printStatistics(std::vector<T>& data)
|
||||||
}
|
}
|
||||||
|
|
||||||
sfz::Logger::Logger()
|
sfz::Logger::Logger()
|
||||||
|
: callbackTimeQueue(alignedNew<CallbackTimeQueue>()),
|
||||||
|
fileTimeQueue(alignedNew<FileTimeQueue>())
|
||||||
{
|
{
|
||||||
keepRunning.test_and_set();
|
keepRunning.test_and_set();
|
||||||
clearFlag.test_and_set();
|
clearFlag.test_and_set();
|
||||||
|
|
@ -106,7 +108,7 @@ void sfz::Logger::logCallbackTime(const CallbackBreakdown& breakdown, int numVoi
|
||||||
callbackTime.breakdown = breakdown;
|
callbackTime.breakdown = breakdown;
|
||||||
callbackTime.numVoices = numVoices;
|
callbackTime.numVoices = numVoices;
|
||||||
callbackTime.numSamples = numSamples;
|
callbackTime.numSamples = numSamples;
|
||||||
callbackTimeQueue.try_push(callbackTime);
|
callbackTimeQueue->try_push(callbackTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Logger::logFileTime(std::chrono::duration<double> waitDuration, std::chrono::duration<double> loadDuration, uint32_t fileSize, absl::string_view filename)
|
void sfz::Logger::logFileTime(std::chrono::duration<double> waitDuration, std::chrono::duration<double> loadDuration, uint32_t fileSize, absl::string_view filename)
|
||||||
|
|
@ -119,7 +121,7 @@ void sfz::Logger::logFileTime(std::chrono::duration<double> waitDuration, std::c
|
||||||
fileTime.loadDuration = loadDuration;
|
fileTime.loadDuration = loadDuration;
|
||||||
fileTime.fileSize = fileSize;
|
fileTime.fileSize = fileSize;
|
||||||
fileTime.filename = filename;
|
fileTime.filename = filename;
|
||||||
fileTimeQueue.try_push(fileTime);
|
fileTimeQueue->try_push(fileTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Logger::setPrefix(absl::string_view prefix)
|
void sfz::Logger::setPrefix(absl::string_view prefix)
|
||||||
|
|
@ -136,11 +138,11 @@ void sfz::Logger::moveEvents() noexcept
|
||||||
{
|
{
|
||||||
while(keepRunning.test_and_set()) {
|
while(keepRunning.test_and_set()) {
|
||||||
CallbackTime callbackTime;
|
CallbackTime callbackTime;
|
||||||
while (callbackTimeQueue.try_pop(callbackTime))
|
while (callbackTimeQueue->try_pop(callbackTime))
|
||||||
callbackTimes.push_back(callbackTime);
|
callbackTimes.push_back(callbackTime);
|
||||||
|
|
||||||
FileTime fileTime;
|
FileTime fileTime;
|
||||||
while (fileTimeQueue.try_pop(fileTime))
|
while (fileTimeQueue->try_pop(fileTime))
|
||||||
fileTimes.push_back(fileTime);
|
fileTimes.push_back(fileTime);
|
||||||
|
|
||||||
if (!clearFlag.test_and_set()) {
|
if (!clearFlag.test_and_set()) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "utility/LeakDetector.h"
|
#include "utility/LeakDetector.h"
|
||||||
|
#include "utility/MemoryHelpers.h"
|
||||||
#include <atomic_queue/atomic_queue.h>
|
#include <atomic_queue/atomic_queue.h>
|
||||||
#include <absl/strings/string_view.h>
|
#include <absl/strings/string_view.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -14,6 +15,7 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz
|
||||||
{
|
{
|
||||||
|
|
@ -131,8 +133,11 @@ private:
|
||||||
bool loggingEnabled { config::loggingEnabled };
|
bool loggingEnabled { config::loggingEnabled };
|
||||||
std::string prefix { "" };
|
std::string prefix { "" };
|
||||||
|
|
||||||
atomic_queue::AtomicQueue2<CallbackTime, config::loggerQueueSize, true, true, false, true> callbackTimeQueue;
|
using CallbackTimeQueue = atomic_queue::AtomicQueue2<CallbackTime, config::loggerQueueSize, true, true, false, true>;
|
||||||
atomic_queue::AtomicQueue2<FileTime, config::loggerQueueSize, true, true, false, true> fileTimeQueue;
|
using FileTimeQueue = atomic_queue::AtomicQueue2<FileTime, config::loggerQueueSize, true, true, false, true>;
|
||||||
|
|
||||||
|
aligned_unique_ptr<CallbackTimeQueue> callbackTimeQueue;
|
||||||
|
aligned_unique_ptr<FileTimeQueue> fileTimeQueue;
|
||||||
std::vector<CallbackTime> callbackTimes;
|
std::vector<CallbackTime> callbackTimes;
|
||||||
std::vector<FileTime> fileTimes;
|
std::vector<FileTime> fileTimes;
|
||||||
|
|
||||||
|
|
|
||||||
58
src/sfizz/utility/MemoryHelpers.h
Normal file
58
src/sfizz/utility/MemoryHelpers.h
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||||
|
// license. You should have receive a LICENSE.md file along with the code.
|
||||||
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <jsl/allocator>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace sfz {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate and initialize an object of type T, using sufficient
|
||||||
|
* alignment for the type.
|
||||||
|
* This provides compatibility with systems which do not support aligned-new.
|
||||||
|
*/
|
||||||
|
template <class T, size_t A = alignof(T), class... Args>
|
||||||
|
T* alignedNew(Args&& ...args)
|
||||||
|
{
|
||||||
|
using allocator = jsl::aligned_allocator<T, A>;
|
||||||
|
struct deleter {
|
||||||
|
void operator()(T* x) const noexcept { allocator().deallocate(x, sizeof(T)); }
|
||||||
|
};
|
||||||
|
std::unique_ptr<T, deleter> ptr { allocator().allocate(sizeof(T)) };
|
||||||
|
allocator().construct(ptr.get(), std::forward<Args>(args)...);
|
||||||
|
return ptr.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize and deallocate the aligned object of type T. It must have
|
||||||
|
* been previously instantiated by alignedNew.
|
||||||
|
*/
|
||||||
|
template <class T, size_t A = alignof(T)>
|
||||||
|
void alignedDelete(T* ptr)
|
||||||
|
{
|
||||||
|
using allocator = jsl::aligned_allocator<T, A>;
|
||||||
|
if (ptr) {
|
||||||
|
ptr->~T();
|
||||||
|
allocator().deallocate(ptr, sizeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deletes an object using alignedDelete.
|
||||||
|
*/
|
||||||
|
template <class T, size_t A = alignof(T)>
|
||||||
|
struct aligned_deleter {
|
||||||
|
void operator()(T* x) const noexcept { alignedDelete<T, A>(x); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unique pointer which uses alignedDelete as the cleanup function.
|
||||||
|
*/
|
||||||
|
template <class T, size_t A = alignof(T)>
|
||||||
|
using aligned_unique_ptr = std::unique_ptr<T, aligned_deleter<T, A>>;
|
||||||
|
|
||||||
|
} // namespace sfz
|
||||||
Loading…
Add table
Reference in a new issue