Merge pull request #756 from jpcima/new-alignment-issue
Implement a substitute for aligned-new
This commit is contained in:
commit
1ade3d5f5d
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)
|
||||
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")
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
add_compile_options(/Zc:__cplusplus)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ set(SFIZZ_HEADERS
|
|||
sfizz/utility/Debug.h
|
||||
sfizz/utility/LeakDetector.h
|
||||
sfizz/utility/Macros.h
|
||||
sfizz/utility/MemoryHelpers.h
|
||||
sfizz/utility/NumericId.h
|
||||
sfizz/utility/StringViewHelpers.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_include_directories(sfizz_internal PUBLIC "." "sfizz")
|
||||
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
|
||||
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)
|
||||
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::atomic)
|
||||
if(SFIZZ_USE_SNDFILE)
|
||||
target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_USE_SNDFILE=1")
|
||||
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)
|
||||
: logger(logger), threadPool(globalThreadPool())
|
||||
: logger(logger),
|
||||
filesToLoad(alignedNew<FileQueue>()),
|
||||
threadPool(globalThreadPool())
|
||||
{
|
||||
loadingJobs.reserve(config::maxVoices);
|
||||
lastUsedFiles.reserve(config::maxVoices);
|
||||
|
|
@ -350,8 +352,8 @@ sfz::FileDataHolder sfz::FilePool::getFilePromise(const std::shared_ptr<FileId>&
|
|||
return {};
|
||||
}
|
||||
QueuedFileData queuedData { fileId, &preloaded->second, std::chrono::high_resolution_clock::now() };
|
||||
if (!filesToLoad.try_push(queuedData)) {
|
||||
DBG("[sfizz] Could not enqueue the file to load for " << fileId << " (queue capacity " << filesToLoad.capacity() << ")");
|
||||
if (!filesToLoad->try_push(queuedData)) {
|
||||
DBG("[sfizz] Could not enqueue the file to load for " << fileId << " (queue capacity " << filesToLoad->capacity() << ")");
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -498,7 +500,7 @@ void sfz::FilePool::dispatchingJob() noexcept
|
|||
while (dispatchBarrier.wait(), dispatchFlag) {
|
||||
std::lock_guard<std::mutex> guard { loadingJobsMutex };
|
||||
|
||||
if (filesToLoad.try_pop(queuedData)) {
|
||||
if (filesToLoad->try_pop(queuedData)) {
|
||||
if (queuedData.id.expired()) {
|
||||
// file ID was nulled, it means the region was deleted, ignore
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "Logger.h"
|
||||
#include "SpinMutex.h"
|
||||
#include "utility/LeakDetector.h"
|
||||
#include "utility/MemoryHelpers.h"
|
||||
#include <ghc/fs_std.hpp>
|
||||
#include <absl/container/flat_hash_map.h>
|
||||
#include <absl/types/optional.h>
|
||||
|
|
@ -43,6 +44,7 @@
|
|||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
class ThreadPool;
|
||||
|
||||
namespace sfz {
|
||||
|
|
@ -348,7 +350,10 @@ private:
|
|||
FileData* data { nullptr };
|
||||
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 garbageJob() noexcept;
|
||||
void loadingJob(QueuedFileData data) noexcept;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ void printStatistics(std::vector<T>& data)
|
|||
}
|
||||
|
||||
sfz::Logger::Logger()
|
||||
: callbackTimeQueue(alignedNew<CallbackTimeQueue>()),
|
||||
fileTimeQueue(alignedNew<FileTimeQueue>())
|
||||
{
|
||||
keepRunning.test_and_set();
|
||||
clearFlag.test_and_set();
|
||||
|
|
@ -106,7 +108,7 @@ void sfz::Logger::logCallbackTime(const CallbackBreakdown& breakdown, int numVoi
|
|||
callbackTime.breakdown = breakdown;
|
||||
callbackTime.numVoices = numVoices;
|
||||
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)
|
||||
|
|
@ -119,7 +121,7 @@ void sfz::Logger::logFileTime(std::chrono::duration<double> waitDuration, std::c
|
|||
fileTime.loadDuration = loadDuration;
|
||||
fileTime.fileSize = fileSize;
|
||||
fileTime.filename = filename;
|
||||
fileTimeQueue.try_push(fileTime);
|
||||
fileTimeQueue->try_push(fileTime);
|
||||
}
|
||||
|
||||
void sfz::Logger::setPrefix(absl::string_view prefix)
|
||||
|
|
@ -136,11 +138,11 @@ void sfz::Logger::moveEvents() noexcept
|
|||
{
|
||||
while(keepRunning.test_and_set()) {
|
||||
CallbackTime callbackTime;
|
||||
while (callbackTimeQueue.try_pop(callbackTime))
|
||||
while (callbackTimeQueue->try_pop(callbackTime))
|
||||
callbackTimes.push_back(callbackTime);
|
||||
|
||||
FileTime fileTime;
|
||||
while (fileTimeQueue.try_pop(fileTime))
|
||||
while (fileTimeQueue->try_pop(fileTime))
|
||||
fileTimes.push_back(fileTime);
|
||||
|
||||
if (!clearFlag.test_and_set()) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
#include "Config.h"
|
||||
#include "utility/LeakDetector.h"
|
||||
#include "utility/MemoryHelpers.h"
|
||||
#include <atomic_queue/atomic_queue.h>
|
||||
#include <absl/strings/string_view.h>
|
||||
#include <vector>
|
||||
|
|
@ -14,6 +15,7 @@
|
|||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
|
||||
namespace sfz
|
||||
{
|
||||
|
|
@ -131,8 +133,11 @@ private:
|
|||
bool loggingEnabled { config::loggingEnabled };
|
||||
std::string prefix { "" };
|
||||
|
||||
atomic_queue::AtomicQueue2<CallbackTime, config::loggerQueueSize, true, true, false, true> callbackTimeQueue;
|
||||
atomic_queue::AtomicQueue2<FileTime, config::loggerQueueSize, true, true, false, true> fileTimeQueue;
|
||||
using CallbackTimeQueue = atomic_queue::AtomicQueue2<CallbackTime, config::loggerQueueSize, true, true, false, true>;
|
||||
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<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(1) };
|
||||
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) {
|
||||
allocator().destroy(ptr);
|
||||
allocator().deallocate(ptr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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