Skip to content
Snippets Groups Projects
Commit cacfae27 authored by Tobias Leibner's avatar Tobias Leibner
Browse files

[threadstorage] old implementation -> UnsafePerThreadValue, use in timer

parent c68113f0
No related branches found
No related tags found
No related merge requests found
......@@ -256,6 +256,118 @@ private:
}; // class PerThreadValue<ValueImp>
/**
* Previous implementation of PerThreadValue. This implementation suffers from the fact that it is not possible (or
* at least we did not find a way yet) to set a hard upper limit on the number of threads TBB uses. Setting max_threads
* via tbb::task_scheduler_init apparently only sets a soft limit on the number of threads. In addition, even if TBB
* uses only N threads at a time, it might be possible that a thread is destroyed and later in the program another
* thread with a different id replaces it, which will then get a number greater than or equal to N in our
* implementation (see ThreadManager::thread()). This occasionally leads to segfaults.
* We keep this implementation around as it is currently used by TimingData (see dune/xt/common/timings.hh) and the
* new implementation can't replace it in that context, as the new implementation based on
* tbb::enumerable_thread_specific lazily initalizes the values in each thread.
* \todo Either fix TimingData and remove this class or fix this class.
**/
template <class ValueImp>
class UnsafePerThreadValue : public boost::noncopyable
{
public:
typedef ValueImp ValueType;
typedef typename std::conditional<std::is_const<ValueImp>::value, ValueImp, const ValueImp>::type ConstValueType;
private:
typedef UnsafePerThreadValue<ValueImp> ThisType;
typedef std::deque<std::unique_ptr<ValueType>> ContainerType;
public:
//! Initialization by copy construction of ValueType
explicit UnsafePerThreadValue(ConstValueType& value)
: values_(threadManager().max_threads())
{
std::generate(values_.begin(), values_.end(), [=]() { return Common::make_unique<ValueType>(value); });
}
//! Initialization by in-place construction ValueType with \param ctor_args
template <class... InitTypes>
explicit UnsafePerThreadValue(InitTypes&&... ctor_args)
: values_(threadManager().max_threads())
{
for (auto&& val : values_)
val = Common::make_unique<ValueType>(ctor_args...);
}
ThisType& operator=(ConstValueType&& value)
{
std::generate(values_.begin(), values_.end(), [=]() { return Common::make_unique<ValueType>(value); });
return *this;
}
operator ValueType() const
{
return this->operator*();
}
ValueType& operator*()
{
return *values_[threadManager().thread()];
}
ConstValueType& operator*() const
{
return *values_[threadManager().thread()];
}
ValueType* operator->()
{
return values_[threadManager().thread()].get();
}
ConstValueType* operator->() const
{
return values_[threadManager().thread()].get();
}
auto& get_pointer()
{
return values_[threadManager().thread()];
}
template <class BinaryOperation>
ValueType accumulate(ValueType init, BinaryOperation op) const
{
typedef const typename ContainerType::value_type ptr;
auto l = [&](ConstValueType& a, ptr& b) { return op(a, *b); };
return std::accumulate(values_.begin(), values_.end(), init, l);
}
ValueType sum() const
{
return accumulate(ValueType(0), std::plus<ValueType>());
}
typename ContainerType::iterator begin()
{
return values_.begin();
}
typename ContainerType::iterator end()
{
return values_.end();
}
typename ContainerType::const_iterator begin() const
{
return values_.begin();
}
typename ContainerType::const_iterator end() const
{
return values_.end();
}
private:
ContainerType values_;
}; // class UnsafePerThreadValue<...>
template <class Imp, typename Result, class Reduction = std::plus<Result>>
class ThreadResultPropagator
{
......
......@@ -98,12 +98,11 @@ void Timings::start(std::string section_name)
if (section != known_timers_map_.end()) {
if (section->second.first) // timer currently running
return;
section->second.first = true; // set active, start with new
section->second.second = PerThreadValue<TimingData>(section_name);
section->second.second = TimingData(section_name);
} else {
// init new section
known_timers_map_[section_name] = std::make_pair(true, PerThreadValue<TimingData>(section_name));
known_timers_map_[section_name] = std::make_pair(true, TimingData(section_name));
}
DXTC_LIKWID_BEGIN_SECTION(section_name)
} // StartTiming
......
......@@ -82,7 +82,7 @@ class Timings
private:
Timings();
typedef std::map<std::string, std::pair<std::atomic<bool>, PerThreadValue<TimingData>>> KnownTimersMap;
typedef std::map<std::string, std::pair<std::atomic<bool>, UnsafePerThreadValue<TimingData>>> KnownTimersMap;
//! section name -> seconds
typedef std::map<std::string, TimingData::DeltaType> DeltaMap;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment