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++) +
"_";
116 namespace TThreadedObjectUtils {
123 void MergeTObjects(std::shared_ptr<T> target, std::vector<std::shared_ptr<T>> &objs)
128 for (
auto obj : objs) {
129 if (obj && obj != target) objTList.
Add(obj.get());
131 target->Merge(&objTList);
165 template <
class...
ARGS>
168 const auto nSlots = initSlots.
fVal;
173 for (
auto i = 1u; i < nSlots; ++i)
182 template<
class ...ARGS>
192 std::lock_guard<ROOT::TSpinMutex> lg(
fSpinMutex);
203 std::size_t nAvailableSlots;
206 std::lock_guard<ROOT::TSpinMutex> lg(
fSpinMutex);
210 if (i >= nAvailableSlots) {
211 Warning(
"TThreadedObject::GetAtSlot",
"This slot does not exist.");
228 std::size_t nAvailableSlots;
231 std::lock_guard<ROOT::TSpinMutex> lg(
fSpinMutex);
235 if (i >= nAvailableSlots) {
236 Warning(
"TThreadedObject::SetAtSlot",
"This slot does not exist, doing nothing.");
297 Warning(
"TThreadedObject::Merge",
"This object was already merged. Returning the previous result.");
314 Warning(
"TThreadedObject::SnapshotMerge",
"This object was already merged. Returning the previous result.");
318 std::shared_ptr<T> targetPtrShared(targetPtr, [](T *) {});
321 mergeFunction(targetPtrShared, vecOfObjPtrs);
322 return std::unique_ptr<T>(targetPtr);
339 const auto thisThreadID = std::this_thread::get_id();
340 std::lock_guard<ROOT::TSpinMutex> lg(
fSpinMutex);
343 return thisSlotNumIt->second;
346 R__ASSERT(newIndex <=
fObjPointers.size() &&
"This should never happen, we should create new slots as needed");
367 auto model = ((std::unique_ptr<T>*)(val))->get();
368 std::ostringstream ret;
369 ret <<
"A wrapper to make object instances thread private, lazily. "
370 <<
"The model which is replicated is " << printValue(model);
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
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.
static constexpr const TNumSlots fgMaxSlots
The initial number of empty processing slots that a TThreadedObject is constructed with by default.
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.
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 TDirectory * mkdir(const char *name, const char *title="", Bool_t returnExistingDirectory=kFALSE)
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
TH1 is the base class of all histogram classes in ROOT.
virtual void Add(TObject *obj)
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()
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)