Compare commits

...

7 commits

8 changed files with 84 additions and 19 deletions

View file

@ -1,8 +1,14 @@
#pragma once #pragma once
#include <psemek/audio/stream.hpp> #include <version>
#include <psemek/audio/stream.hpp>
#ifdef __cpp_lib_atomic_shared_ptr
#include <atomic>
#else
#include <psemek/util/mutexed.hpp>
#endif
#include <atomic>
#include <memory> #include <memory>
namespace psemek::audio namespace psemek::audio
@ -37,7 +43,11 @@ namespace psemek::audio
} }
private: private:
std::atomic<stream_ptr> stream_; #ifdef __cpp_lib_atomic_shared_ptr
std::atomic<stream_ptr> stream_;
#else
util::mutexed<stream_ptr> stream_;
#endif
}; };
using channel_ptr = std::shared_ptr<channel>; using channel_ptr = std::shared_ptr<channel>;

View file

@ -3,6 +3,8 @@
#include <psemek/math/dynamic.hpp> #include <psemek/math/dynamic.hpp>
#include <psemek/util/exception.hpp> #include <psemek/util/exception.hpp>
#include <memory>
namespace psemek::math::detail namespace psemek::math::detail
{ {
@ -43,6 +45,8 @@ namespace psemek::math::detail
T data[N]; T data[N];
type() = default;
type(dynamic_dimensions<N>){} type(dynamic_dimensions<N>){}
dynamic_dimensions<N> dimensions() const { return {}; } dynamic_dimensions<N> dimensions() const { return {}; }
@ -59,6 +63,8 @@ namespace psemek::math::detail
{ {
static constexpr std::size_t size = 0; static constexpr std::size_t size = 0;
type() = default;
type(dynamic_dimensions<0>){} type(dynamic_dimensions<0>){}
dynamic_dimensions<0> dimensions() const { return {}; } dynamic_dimensions<0> dimensions() const { return {}; }

View file

@ -67,7 +67,7 @@ namespace psemek::math::detail
: rows(dimensions.rows.size) : rows(dimensions.rows.size)
{} {}
dynamic_dimensions_2d<dynamic, 0> dimensions() const { return {.rows = rows}; } dynamic_dimensions_2d<dynamic, 0> dimensions() const { return {.rows = {rows}}; }
T const * operator[](std::size_t) const { throw empty_array_exception{}; } T const * operator[](std::size_t) const { throw empty_array_exception{}; }
T * operator[](std::size_t) { throw empty_array_exception{}; } T * operator[](std::size_t) { throw empty_array_exception{}; }
@ -103,7 +103,7 @@ namespace psemek::math::detail
: columns(dimensions.columns.size) : columns(dimensions.columns.size)
{} {}
dynamic_dimensions_2d<0, dynamic> dimensions() const { return {.columns = columns}; } dynamic_dimensions_2d<0, dynamic> dimensions() const { return {.columns = {columns}}; }
T const * operator[](std::size_t) const { throw empty_array_exception{}; } T const * operator[](std::size_t) const { throw empty_array_exception{}; }
T * operator[](std::size_t) { throw empty_array_exception{}; } T * operator[](std::size_t) { throw empty_array_exception{}; }
@ -141,7 +141,7 @@ namespace psemek::math::detail
, data(std::make_unique_for_overwrite<T[]>(rows * columns)) , data(std::make_unique_for_overwrite<T[]>(rows * columns))
{} {}
dynamic_dimensions_2d<R, dynamic> dimensions() const { return {.columns = columns}; } dynamic_dimensions_2d<R, dynamic> dimensions() const { return {.columns = {columns}}; }
T * operator[] (std::size_t row) T * operator[] (std::size_t row)
{ {
@ -178,7 +178,7 @@ namespace psemek::math::detail
, data(std::make_unique_for_overwrite<T[]>(rows * columns)) , data(std::make_unique_for_overwrite<T[]>(rows * columns))
{} {}
dynamic_dimensions_2d<dynamic, C> dimensions() const { return {.rows = rows}; } dynamic_dimensions_2d<dynamic, C> dimensions() const { return {.rows = {rows}}; }
T * operator[] (std::size_t row) T * operator[] (std::size_t row)
{ {
@ -216,7 +216,7 @@ namespace psemek::math::detail
, data(std::make_unique_for_overwrite<T[]>(rows * columns)) , data(std::make_unique_for_overwrite<T[]>(rows * columns))
{} {}
dynamic_dimensions_2d<dynamic, dynamic> dimensions() const { return {.rows = rows, .columns = columns}; } dynamic_dimensions_2d<dynamic, dynamic> dimensions() const { return {.rows = {rows}, .columns = {columns}}; }
T * operator[] (std::size_t row) T * operator[] (std::size_t row)
{ {

View file

@ -26,9 +26,7 @@ namespace psemek::math
: coords(dimensions) : coords(dimensions)
{} {}
point() point() = default;
: coords({})
{}
explicit point(std::size_t size) requires (N == dynamic) explicit point(std::size_t size) requires (N == dynamic)
: coords({.size = size}) : coords({.size = size})
@ -37,7 +35,6 @@ namespace psemek::math
template <typename ... Args> template <typename ... Args>
requires(N != dynamic && sizeof...(Args) == N && detail::all_convertible_to<T, Args...>::value) requires(N != dynamic && sizeof...(Args) == N && detail::all_convertible_to<T, Args...>::value)
point(Args && ... args) point(Args && ... args)
: coords({})
{ {
auto out = values().begin(); auto out = values().begin();
((*out++ = args), ...); ((*out++ = args), ...);

View file

@ -29,9 +29,7 @@ namespace psemek::math
: coords(dimensions) : coords(dimensions)
{} {}
vector() vector() = default;
: coords({})
{}
explicit vector(std::size_t size) requires (N == dynamic) explicit vector(std::size_t size) requires (N == dynamic)
: coords({.size = size}) : coords({.size = size})
@ -40,7 +38,6 @@ namespace psemek::math
template <typename ... Args> template <typename ... Args>
requires(N != dynamic && sizeof...(Args) == N && detail::all_convertible_to<T, Args...>::value) requires(N != dynamic && sizeof...(Args) == N && detail::all_convertible_to<T, Args...>::value)
vector(Args && ... args) vector(Args && ... args)
: coords({})
{ {
auto out = values().begin(); auto out = values().begin();
((*out++ = args), ...); ((*out++ = args), ...);

View file

@ -1,4 +1,6 @@
find_package(Boost COMPONENTS math REQUIRED CONFIG) # Boost.Math is header-only
# Required for statistics.hpp
find_package(Boost REQUIRED CONFIG)
file(GLOB_RECURSE PSEMEK_UTIL_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") file(GLOB_RECURSE PSEMEK_UTIL_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp")
file(GLOB_RECURSE PSEMEK_UTIL_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp") file(GLOB_RECURSE PSEMEK_UTIL_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp")

View file

@ -0,0 +1,53 @@
#pragma once
#include <mutex>
#include <utility>
namespace psemek::util
{
template <typename T, typename Mutex = std::mutex>
struct mutexed
{
mutexed() = default;
mutexed(mutexed const &) = delete;
mutexed(mutexed &&) = delete;
mutexed & operator = (mutexed const &) = delete;
mutexed & operator = (mutexed &&) = delete;
mutexed(T && value)
: value_(std::move(value))
{}
template <typename ... Args>
mutexed(std::in_place_t, Args && ... args)
: value_(std::forward<Args>(args)...)
{}
T load() const
{
std::lock_guard lock{mutex_};
return value_;
}
void store(T && new_value)
{
std::lock_guard lock{mutex_};
value_ = std::move(new_value);
}
T exchange(T && new_value) const
{
std::lock_guard lock{mutex_};
std::swap(value_, new_value);
return new_value;
}
private:
T value_;
mutable Mutex mutex_;
};
}

View file

@ -83,8 +83,8 @@ namespace psemek::util
template <typename Range> template <typename Range>
auto reversed(Range const & r) auto reversed(Range const & r)
{ {
auto it1 = begin(r); auto it1 = xbegin(r);
auto it2 = end(r); auto it2 = xend(r);
using ReverseIterator = std::reverse_iterator<decltype(it1)>; using ReverseIterator = std::reverse_iterator<decltype(it1)>;
return range<ReverseIterator>{std::make_reverse_iterator(it2), std::make_reverse_iterator(it1)}; return range<ReverseIterator>{std::make_reverse_iterator(it2), std::make_reverse_iterator(it1)};