/*!
* @class EnumerableThreadLocal
*
* @headerfile <seqan/parallel.h>
*
* @brief Manages thread local storage.
*
* @signature template <typename TValue, typename TManager, typename TSpec>
* class ThreadPool;
*
* @tparam TValue The type of the stored value.
* @tparam TManager A policy used to manage the thread local storage. Defaults
* to @link SimpleThreadLocalManager @endlink.
* @tparam TSpec Specialization of the <tt>EnumerableThreadLocal</tt> class.
* Defaults to <tt>void</tt>.
*
* The enumerable thread local class can be used to manage thread local storage
* using a map as internal buffer. The class offers an iterator interface, such
* that the thread specific values can be enumerated allowing to apply reduce
* operations at the end of the parallel execution. Creating thread local
* storage happens via a lazy evaluation using the <tt>local</tt> function. If a
* thread, identified by its <a
* href="https://en.cppreference.com/w/cpp/thread/get_id">thread id</a>,
* requests storage for the first time a new thread specific storage will be
* created and a lvalue reference pointing to this storage is returned. If the
* thread id was already registered, then a lvalue reference to the associated
* storage will be returned. The access to the <tt>local</tt> function is thread
* safe and can be called concurrently.
*
* A thread local manager can be selected via template argument. This manager
* ensures safe access from concurrent invocations. The manager can further be
* replaced to change the behavior of storing the thread local data.
*
* @see SimpleThreadLocalManager
* @see CountingThreadLocalManager
*
* @fn EnumerableThreadLocal::EnumerableThreadLocal
*
* @brief Constructing an instance of this class.
*
* @note The class is not @link CopyConstructibleConcept copy constructible
* @endlink and not <a href="https://en.cppreference.com/w/cpp/named_req/M
* oveConstructible">move constructible</a>.
*
* @signature EnumerableThreadLocal::EnumerableThreadLocal() = default;
* @signature EnumerableThreadLocal::EnumerableThreadLocal(TValue init);
*
* @param[in] init An optional value used to initialize the newly created
* storage.
*
* @mfn EnumerableThreadLocal#Iterator
*
* @headerfile <seqan/parallel.h>
*
* @brief Constructing an instance of this class.
*
* @signature Iterator<TEnumerableThreadLocal>::Type;
*
* @tparam TEnumerableThreadLocal The type of the enumerable thread local class.
*
* @return Type The type of the iterator.
*
* @fn EnumerableThreadLocal#storageManager
*
* @headerfile <seqan/parallel.h>
*
* @brief Constructing an instance of this class.
*
* @signature TManager & storageManager(etl);
*
* @param[in] etl An instance of @link EnumerableThreadLocal @endlink.
*
* @return TManager& A lvalue reference to the associated storage manager.
*
* @datarace not thread-safe.
*
* @fn EnumerableThreadLocal#local
*
* @headerfile <seqan/parallel.h>
*
* @brief Constructing an instance of this class.
*
* @signature auto & local(etl);
* @signature auto & local(etl, b);
*
* @param[in,out] etl An instance of @link EnumerableThreadLocal @endlink.
* @param[in,out] b A boolean to indicate successful creation.
*
* @return auto& A lvalue reference to the associated thread specific storage.
*
* @datarace thread-safe. Concurrent invocations of this function are
* synchronized via the storage manager.
*
* Calls the internal <tt>local</tt> member function of the associated storage
* manager. If the thread-id was used for the first time <tt>b</tt> will be set
* to <tt>true</tt> to indicate successful creation of the storage. If the
* storage was already created for the given thread-id, then <tt>b</tt> is set
* to <tt>false</tt>.
*
* @fn EnumerableThreadLocal#begin
*
* @headerfile <seqan/parallel.h>
*
* @brief Returns a bidirectional iterator to the thread specific storage.
*
* @signature TIteator begin(etl, tag);
*
* @param[in] etl An instance of @link EnumerableThreadLocal @endlink.
* @param[in] tag A tag to choose the type of the iterator. One of @link
* ContainerIteratorTags @endlink.
*
* @return TIteator Iterator to the begin of the thread stores.
*
* @datarace thread-safe.
*
* @fn EnumerableThreadLocal#end
*
* @headerfile <seqan/parallel.h>
*
* @brief Returns a bidirectional iterator to the thread specific storage.
*
* @signature TIteator end(etl, tag);
*
* @param[in] etl An instance of @link EnumerableThreadLocal @endlink.
* @param[in] tag A tag to choose the type of the iterator. One of @link
* ContainerIteratorTags @endlink.
*
* @return TIteator Iterator to the end of the thread stores.
*
* @datarace thread-safe.
*
* @fn EnumerableThreadLocal#combineEach
*
* @headerfile <seqan/parallel.h>
*
* @brief Enumerates thread local stores and applies an unary functor for each
* store.
*
* @signature void combineEach(etl, f);
*
* @param[in] etl An instance of @link EnumerableThreadLocal @endlink.
* @param[in] f An unary functor called on each thread local storage.
*
* @datarace not thread-safe.
*
* @section Possible implementation:
*
* @code{.cpp}
* std::for_each(begin(etl), end(etl), f);
* @endcode
*
*
* @see EnumerableThreadLocal#combine
*
* @fn EnumerableThreadLocal#combine
*
* @headerfile <seqan/parallel.h>
*
* @brief Enumerates thread local stores and applies a binary functor for each
* store.
*
* @signature void combine(etl, f);
*
* @param[in] etl An instance of @link EnumerableThreadLocal @endlink.
* @param[in] f A binary combinator called on each thread local storage.
*
* @datarace not thread-safe.
*
* @section Possible implementation:
*
* @code{.cpp}
* std::accumulate(begin(etl), end(etl), TValue{}, f);
* @endcode
*
*
* @see EnumerableThreadLocal#combineEach
*/