ATLAS Offline Software
Public Member Functions | Private Attributes | List of all members
CaloRecGPU::Helpers::separate_thread_holder< T > Class Template Reference

Manages objects of type T in a thread-safe way, ensuring that there's an object available for each separate thread while minimizing the number of allocations. More...

#include <Helpers.h>

Collaboration diagram for CaloRecGPU::Helpers::separate_thread_holder< T >:

Public Member Functions

T & get_one ()
 
T & get_for_thread () const
 
void release_one ()
 
void resize (const size_t new_size)
 
template<class F , class ... Args>
void operate_on_all (F &&f, Args &&... args)
 
size_t held_size () const
 
size_t available_size () const
 
size_t filled_size () const
 

Private Attributes

std::vector< std::unique_ptr< T > > m_held
 
std::vector< typename std::thread::idm_thread_equivs
 
std::mutex m_mutex
 

Detailed Description

template<class T>
class CaloRecGPU::Helpers::separate_thread_holder< T >

Manages objects of type T in a thread-safe way, ensuring that there's an object available for each separate thread while minimizing the number of allocations.

Internally uses a std::vector of std::thread::id to manage the different threads, thus it is especially efficient for relatively small numbers of concurrent threads (which matches the use case, e. g. 64 threads )

Definition at line 1474 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

Member Function Documentation

◆ available_size()

template<class T >
size_t CaloRecGPU::Helpers::separate_thread_holder< T >::available_size ( ) const
inline

Definition at line 1576 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1577  {
1578  size_t count = 0;
1579  const std::thread::id invalid_id{};
1580  for (const auto & id : m_thread_equivs)
1581  {
1582  if (id == invalid_id)
1583  {
1584  ++count;
1585  }
1586  }
1587  return count;
1588  }

◆ filled_size()

template<class T >
size_t CaloRecGPU::Helpers::separate_thread_holder< T >::filled_size ( ) const
inline

Definition at line 1590 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1591  {
1592  return this->held_size() - this->available_size();
1593  }

◆ get_for_thread()

template<class T >
T& CaloRecGPU::Helpers::separate_thread_holder< T >::get_for_thread ( ) const
inline
Precondition
Assumes the thread already has an allocated object (through get_one).

Definition at line 1512 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1513  {
1514  std::thread::id this_id = std::this_thread::get_id();
1515  for (size_t i = 0; i < m_thread_equivs.size(); ++i)
1516  {
1517  if (m_thread_equivs[i] == this_id)
1518  {
1519  return *(m_held[i]);
1520  }
1521  }
1522  //Here would be a good place for an unreachable.
1523  //C++23?
1524  return *(m_held.back());
1525  }

◆ get_one()

template<class T >
T& CaloRecGPU::Helpers::separate_thread_holder< T >::get_one ( )
inline

Definition at line 1493 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1494  {
1495  std::lock_guard<std::mutex> lock_guard(m_mutex);
1496  std::thread::id this_id = std::this_thread::get_id();
1497  const std::thread::id invalid_id{};
1498  for (size_t i = 0; i < m_thread_equivs.size(); ++i)
1499  {
1500  if (m_thread_equivs[i] == invalid_id)
1501  {
1502  m_thread_equivs[i] = this_id;
1503  return *(m_held[i]);
1504  }
1505  }
1506  m_held.emplace_back(std::make_unique<T>());
1507  m_thread_equivs.emplace_back(this_id);
1508  return *(m_held.back());
1509  }

◆ held_size()

template<class T >
size_t CaloRecGPU::Helpers::separate_thread_holder< T >::held_size ( ) const
inline

Definition at line 1571 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1572  {
1573  return m_held.size();
1574  }

◆ operate_on_all()

template<class T >
template<class F , class ... Args>
void CaloRecGPU::Helpers::separate_thread_holder< T >::operate_on_all ( F &&  f,
Args &&...  args 
)
inline

Definition at line 1562 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1563  {
1564  std::lock_guard<std::mutex> lock_guard(m_mutex);
1565  for (std::unique_ptr<T> & obj : m_held)
1566  {
1567  f(*obj, std::forward<Args>(args)...);
1568  }
1569  }

◆ release_one()

template<class T >
void CaloRecGPU::Helpers::separate_thread_holder< T >::release_one ( )
inline

Definition at line 1527 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1528  {
1529  std::lock_guard<std::mutex> lock_guard(m_mutex);
1530  std::thread::id this_id = std::this_thread::get_id();
1531  const std::thread::id invalid_id{};
1532  for (size_t i = 0; i < m_thread_equivs.size(); ++i)
1533  {
1534  if (m_thread_equivs[i] == this_id)
1535  {
1536  m_thread_equivs[i] = invalid_id;
1537  }
1538  }
1539  }

◆ resize()

template<class T >
void CaloRecGPU::Helpers::separate_thread_holder< T >::resize ( const size_t  new_size)
inline

Definition at line 1541 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1542  {
1543  std::lock_guard<std::mutex> lock_guard(m_mutex);
1544  if (new_size < m_held.size())
1545  {
1546  m_held.resize(new_size);
1547  m_thread_equivs.resize(new_size);
1548  }
1549  else if (new_size > m_held.size())
1550  {
1551  const size_t to_add = new_size - m_held.size();
1552  const std::thread::id invalid_id{};
1553  for (size_t i = 0; i < to_add; ++i)
1554  {
1555  m_held.emplace_back(std::make_unique<T>());
1556  m_thread_equivs.emplace_back(invalid_id);
1557  }
1558  }
1559  }

Member Data Documentation

◆ m_held

template<class T >
std::vector< std::unique_ptr<T> > CaloRecGPU::Helpers::separate_thread_holder< T >::m_held
private

◆ m_mutex

template<class T >
std::mutex CaloRecGPU::Helpers::separate_thread_holder< T >::m_mutex
private

◆ m_thread_equivs

template<class T >
std::vector< typename std::thread::id > CaloRecGPU::Helpers::separate_thread_holder< T >::m_thread_equivs
private

The documentation for this class was generated from the following file:
python.CaloRecoConfig.f
f
Definition: CaloRecoConfig.py:127
CaloRecGPU::Helpers::separate_thread_holder::m_held
std::vector< std::unique_ptr< T > > m_held
Definition: Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h:1477
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
lumiFormat.i
int i
Definition: lumiFormat.py:92
CaloRecGPU::Helpers::separate_thread_holder::m_thread_equivs
std::vector< typename std::thread::id > m_thread_equivs
Definition: Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h:1478
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:191
CaloRecGPU::Helpers::separate_thread_holder::m_mutex
std::mutex m_mutex
Definition: Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h:1490
python.PyAthena.obj
obj
Definition: PyAthena.py:135
CaloRecGPU::Helpers::separate_thread_holder::available_size
size_t available_size() const
Definition: Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h:1576
python.CaloScaleNoiseConfig.args
args
Definition: CaloScaleNoiseConfig.py:80
CaloRecGPU::Helpers::separate_thread_holder::held_size
size_t held_size() const
Definition: Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h:1571