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);
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
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.
TDirectory::TContext keeps track and restore the current directory.
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)