mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-12 13:41:48 +00:00
fix for threading bug
This commit is contained in:
parent
45a4ae1e19
commit
7b88f02f0e
@ -107,7 +107,7 @@ void linearize_index(optional_index& out, const A& axis, const axis::index_type
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class S, class A>
|
template <class S, class A>
|
||||||
void grow_storage(S& storage, const A& axes, const axis::index_type* shifts) {
|
void grow_storage(const A& axes, S& storage, const axis::index_type* shifts) {
|
||||||
struct item {
|
struct item {
|
||||||
axis::index_type idx, old_extent;
|
axis::index_type idx, old_extent;
|
||||||
std::size_t new_stride;
|
std::size_t new_stride;
|
||||||
@ -177,8 +177,8 @@ void grow_storage(S& storage, const A& axes, const axis::index_type* shifts) {
|
|||||||
// interface), so we throw at runtime if incompatible argument is passed (e.g.
|
// interface), so we throw at runtime if incompatible argument is passed (e.g.
|
||||||
// 3d tuple)
|
// 3d tuple)
|
||||||
// histogram has only non-growing axes
|
// histogram has only non-growing axes
|
||||||
template <unsigned I, unsigned N, class S, class T, class U>
|
template <unsigned I, unsigned N, class T, class S, class U>
|
||||||
optional_index args_to_index(std::false_type, S&, const T& axes, const U& args) {
|
optional_index to_index(std::false_type, const T& axes, S&, const U& args) {
|
||||||
optional_index idx;
|
optional_index idx;
|
||||||
const auto rank = get_size(axes);
|
const auto rank = get_size(axes);
|
||||||
if (rank == 1 && N > 1)
|
if (rank == 1 && N > 1)
|
||||||
@ -196,13 +196,12 @@ optional_index args_to_index(std::false_type, S&, const T& axes, const U& args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// histogram has growing axes
|
// histogram has growing axes
|
||||||
template <unsigned I, unsigned N, class S, class T, class U>
|
template <unsigned I, unsigned N, class T, class S, class U>
|
||||||
optional_index args_to_index(std::true_type, S& storage_and_mutex, T& axes,
|
optional_index to_index(std::true_type, T& axes, S& storage, const U& args) {
|
||||||
const U& args) {
|
|
||||||
optional_index idx;
|
optional_index idx;
|
||||||
axis::index_type shifts[buffer_size<T>::value];
|
constexpr unsigned M = buffer_size<T>::value;
|
||||||
|
axis::index_type shifts[M];
|
||||||
const auto rank = get_size(axes);
|
const auto rank = get_size(axes);
|
||||||
std::lock_guard<typename S::second_type> lk{storage_and_mutex.second()};
|
|
||||||
bool update_needed = false;
|
bool update_needed = false;
|
||||||
if (rank == 1 && N > 1)
|
if (rank == 1 && N > 1)
|
||||||
update_needed =
|
update_needed =
|
||||||
@ -211,14 +210,13 @@ optional_index args_to_index(std::true_type, S& storage_and_mutex, T& axes,
|
|||||||
if (rank != N)
|
if (rank != N)
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
std::invalid_argument("number of arguments != histogram rank"));
|
std::invalid_argument("number of arguments != histogram rank"));
|
||||||
constexpr unsigned M = buffer_size<remove_cvref_t<decltype(axes)>>::value;
|
|
||||||
mp11::mp_for_each<mp11::mp_iota_c<(N < M ? N : M)>>([&](auto J) {
|
mp11::mp_for_each<mp11::mp_iota_c<(N < M ? N : M)>>([&](auto J) {
|
||||||
update_needed |=
|
update_needed |=
|
||||||
linearize_value(idx, shifts[J], axis_get<J>(axes), std::get<(J + I)>(args));
|
linearize_value(idx, shifts[J], axis_get<J>(axes), std::get<(J + I)>(args));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_needed) grow_storage(storage_and_mutex.first(), axes, shifts);
|
if (update_needed) grow_storage(axes, storage, shifts);
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,57 +255,58 @@ constexpr auto weight_sample_indices() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void fill_storage2(std::true_type, T&& t) {
|
void fill_impl2(std::true_type, T&& t) {
|
||||||
++t;
|
++t;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
void fill_storage2(std::true_type, T&& t, const U& u) {
|
void fill_impl2(std::true_type, T&& t, const U& u) {
|
||||||
t += u;
|
t += u;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class... Us>
|
template <class T, class... Us>
|
||||||
void fill_storage2(std::false_type, T&& t, const Us&... us) {
|
void fill_impl2(std::false_type, T&& t, const Us&... us) {
|
||||||
t(us...);
|
t(us...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
void fill_storage(mp11::mp_int<-1>, mp11::mp_int<-1>, T&& t, const U&) {
|
void fill_impl1(mp11::mp_int<-1>, mp11::mp_int<-1>, T&& t, const U&) {
|
||||||
fill_storage2(has_operator_preincrement<remove_cvref_t<T>>{}, t);
|
fill_impl2(has_operator_preincrement<remove_cvref_t<T>>{}, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class IW, class T, class U>
|
template <class IW, class T, class U>
|
||||||
void fill_storage(IW, mp11::mp_int<-1>, T&& t, const U& u) {
|
void fill_impl1(IW, mp11::mp_int<-1>, T&& t, const U& u) {
|
||||||
fill_storage2(has_operator_preincrement<remove_cvref_t<T>>{}, t,
|
fill_impl2(has_operator_preincrement<remove_cvref_t<T>>{}, t,
|
||||||
std::get<IW::value>(u).value);
|
std::get<IW::value>(u).value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class IS, class T, class U>
|
template <class IS, class T, class U>
|
||||||
void fill_storage(mp11::mp_int<-1>, IS, T&& t, const U& u) {
|
void fill_impl1(mp11::mp_int<-1>, IS, T&& t, const U& u) {
|
||||||
mp11::tuple_apply([&t](auto&&... args) { t(args...); }, std::get<IS::value>(u).value);
|
mp11::tuple_apply([&t](auto&&... args) { t(args...); }, std::get<IS::value>(u).value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class IW, class IS, class T, class U>
|
template <class IW, class IS, class T, class U>
|
||||||
void fill_storage(IW, IS, T&& t, const U& u) {
|
void fill_impl1(IW, IS, T&& t, const U& u) {
|
||||||
mp11::tuple_apply([&](auto&&... args2) { t(std::get<IW::value>(u).value, args2...); },
|
mp11::tuple_apply([&](auto&&... args2) { t(std::get<IW::value>(u).value, args2...); },
|
||||||
std::get<IS::value>(u).value);
|
std::get<IS::value>(u).value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class S, class A, class... Us>
|
template <class A, class SM, class... Us>
|
||||||
auto fill(S& storage_and_mutex, A& axes, const std::tuple<Us...>& args) {
|
typename SM::first_type::iterator fill(A& axes, SM& sm, const std::tuple<Us...>& tus) {
|
||||||
constexpr auto iws = weight_sample_indices<Us...>();
|
constexpr auto iws = weight_sample_indices<Us...>();
|
||||||
constexpr unsigned n = sizeof...(Us) - (iws.first > -1) - (iws.second > -1);
|
constexpr unsigned n = sizeof...(Us) - (iws.first > -1) - (iws.second > -1);
|
||||||
constexpr unsigned i = (iws.first == 0 || iws.second == 0)
|
constexpr unsigned i = (iws.first == 0 || iws.second == 0)
|
||||||
? (iws.first == 1 || iws.second == 1 ? 2 : 1)
|
? (iws.first == 1 || iws.second == 1 ? 2 : 1)
|
||||||
: 0;
|
: 0;
|
||||||
optional_index idx =
|
std::lock_guard<typename SM::second_type> lk{sm.second()};
|
||||||
args_to_index<i, n>(has_growing_axis<A>(), storage_and_mutex, axes, args);
|
auto& storage = sm.first();
|
||||||
|
optional_index idx = to_index<i, n>(has_growing_axis<A>(), axes, storage, tus);
|
||||||
if (idx) {
|
if (idx) {
|
||||||
fill_storage(mp11::mp_int<iws.first>{}, mp11::mp_int<iws.second>{},
|
using mp11::mp_int;
|
||||||
storage_and_mutex.first()[*idx], args);
|
fill_impl1(mp_int<iws.first>{}, mp_int<iws.second>{}, storage[*idx], tus);
|
||||||
return storage_and_mutex.first().begin() + *idx;
|
return storage.begin() + *idx;
|
||||||
}
|
}
|
||||||
return storage_and_mutex.first().end();
|
return storage.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A, typename... Us>
|
template <typename A, typename... Us>
|
||||||
|
@ -181,7 +181,7 @@ public:
|
|||||||
/// Fill histogram with values, an optional weight, and/or a sample from a `std::tuple`.
|
/// Fill histogram with values, an optional weight, and/or a sample from a `std::tuple`.
|
||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
auto operator()(const std::tuple<Ts...>& t) {
|
auto operator()(const std::tuple<Ts...>& t) {
|
||||||
return detail::fill(storage_and_mutex_, axes_, t);
|
return detail::fill(axes_, storage_and_mutex_, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access cell value at integral indices.
|
/// Access cell value at integral indices.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user