12#ifndef ROOT_TThreadedObject
13#define ROOT_TThreadedObject
50 namespace TThreadedObjectUtils {
53 template<typename T, bool ISHISTO = std::is_base_of<TH1,T>::value>
63 obj->SetDirectory(
nullptr);
70 template<class T, bool isCopyConstructible = std::is_copy_constructible<T>::value>
90 clone = (
T*)obj->Clone();
92 clone = (
T*)obj->Clone();
98 template <class T, bool ISHISTO = std::is_base_of<TH1, T>::value>
102 static unsigned dirCounter = 0;
103 const std::string dirName =
"__TThreaded_dir_" + std::to_string(dirCounter++) +
"_";
104 return gROOT->mkdir(dirName.c_str());
115 operator unsigned()
const {
return fVal; }
118 "TThreadedObject now adds new slots as needed, on demand, possibly beyond fgMaxSlots")
128 namespace TThreadedObjectUtils {
135 void MergeTObjects(std::shared_ptr<T> target, std::vector<std::shared_ptr<T>> &objs)
140 for (
auto obj : objs) {
141 if (obj && obj != target) objTList.
Add(obj.get());
143 target->Merge(&objTList);
177 template <
class...
ARGS>
180 const auto nSlots = initSlots.
fVal;
185 for (
auto i = 1u; i < nSlots; ++i)
194 template<
class ...ARGS>
204 std::lock_guard<ROOT::TSpinMutex> lg(
fSpinMutex);
215 std::size_t nAvailableSlots;
218 std::lock_guard<ROOT::TSpinMutex> lg(
fSpinMutex);
222 if (i >= nAvailableSlots) {
223 Warning(
"TThreadedObject::GetAtSlot",
"This slot does not exist.");
240 std::size_t nAvailableSlots;
243 std::lock_guard<ROOT::TSpinMutex> lg(
fSpinMutex);
247 if (i >= nAvailableSlots) {
248 Warning(
"TThreadedObject::SetAtSlot",
"This slot does not exist, doing nothing.");
309 Warning(
"TThreadedObject::Merge",
"This object was already merged. Returning the previous result.");
326 Warning(
"TThreadedObject::SnapshotMerge",
"This object was already merged. Returning the previous result.");
330 std::shared_ptr<T> targetPtrShared(targetPtr, [](
T *) {});
333 mergeFunction(targetPtrShared, vecOfObjPtrs);
334 return std::unique_ptr<T>(targetPtr);
351 const auto thisThreadID = std::this_thread::get_id();
352 std::lock_guard<ROOT::TSpinMutex> lg(
fSpinMutex);
355 return thisSlotNumIt->second;
358 R__ASSERT(newIndex <=
fObjPointers.size() &&
"This should never happen, we should create new slots as needed");
378 auto model = ((std::unique_ptr<T>*)(val))->get();
379 std::ostringstream ret;
380 ret <<
"A wrapper to make object instances thread private, lazily. "
381 <<
"The model which is replicated is " << printValue(model);
#define R__DEPRECATED(MAJOR, MINOR, REASON)
void Warning(const char *location, const char *msgfmt,...)
typedef void((*Func_t)())
A spin mutex class which respects the STL interface for mutexes.
A wrapper to make object instances thread private, lazily.
std::map< std::thread::id, unsigned > fThrIDSlotMap
A mapping between the thread IDs and the slots.
T * operator->()
Access the wrapped object and allow to call its methods.
void SetAtSlot(unsigned i, std::shared_ptr< T > v)
Set the value of a particular slot.
std::shared_ptr< T > Merge(TThreadedObjectUtils::MergeFunctionType< T > mergeFunction=TThreadedObjectUtils::MergeTObjects< T >)
Merge all the thread private objects.
std::deque< TDirectory * > fDirectories
A TDirectory per slot.
std::shared_ptr< T > GetAtSlot(unsigned i)
Access a particular processing slot.
std::shared_ptr< T > Get()
Access the pointer corresponding to the current slot.
ROOT::TSpinMutex fSpinMutex
Protects concurrent access to fThrIDSlotMap, fObjPointers.
TThreadedObject(const TThreadedObject &)=delete
std::unique_ptr< T > fModel
Use to store a "model" of the object.
std::deque< std::shared_ptr< T > > fObjPointers
An object pointer per slot.
std::unique_ptr< T > SnapshotMerge(TThreadedObjectUtils::MergeFunctionType< T > mergeFunction=TThreadedObjectUtils::MergeTObjects< T >)
Merge all the thread private objects.
std::shared_ptr< T > GetAtSlotUnchecked(unsigned i) const
Access a particular slot which corresponds to a single thread.
unsigned GetThisSlotNumber()
Get the slot number for this threadID, make a slot if needed.
static Internal::TThreadedObjectUtils::MaxSlots_t fgMaxSlots
The initial number of empty processing slots that a TThreadedObject is constructed with by default.
TThreadedObject(TNumSlots initSlots, ARGS &&... args)
Construct the TThreadedObject with initSlots empty slots and the "model" of the thread private object...
T * GetAtSlotRaw(unsigned i) const
Access a particular slot which corresponds to a single thread.
unsigned GetNSlots() const
Return the number of currently available slot.
TThreadedObject(ARGS &&... args)
Construct the TThreadedObject and the "model" of the thread private objects.
bool fIsMerged
Remember if the objects have been merged already.
Small helper to keep current directory context.
Describe directory structure in memory.
virtual void Add(TObject *obj)
void function(const Char_t *name_, T fun, const Char_t *docstring=0)
void MergeTObjects(std::shared_ptr< T > target, std::vector< std::shared_ptr< T > > &objs)
Merge TObjects.
std::function< void(std::shared_ptr< T >, std::vector< std::shared_ptr< T > > &)> MergeFunctionType
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
static T * Clone(const T *obj, TDirectory *d=nullptr)
Return a copy of the object or a "Clone" if the copy constructor is not implemented.
static T * Clone(const T *obj, TDirectory *d=nullptr)
static T * Detach(T *obj)
static T * Detach(T *obj)
static TDirectory * Create()
static TDirectory * Create()
MaxSlots_t & operator=(unsigned val) R__DEPRECATED(6
Defines the number of threads in some of ROOT's interfaces.
friend bool operator!=(TNumSlots lhs, TNumSlots rhs)
friend bool operator==(TNumSlots lhs, TNumSlots rhs)