All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Classes | Public Types | Public Member Functions | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
util::ArtHandleTrackerManager< Event > Class Template Reference

Manages handle trackers for an easy call of removeCachedProduct(). More...

#include <ArtHandleTrackerManager.h>

Classes

struct  Config_t
 Configuration record. More...
 

Public Types

using Event_t = Event
 Type of data viewer object to operate with. More...
 

Public Member Functions

 ArtHandleTrackerManager (Config_t config={})
 Constructs a handle manager. More...
 
 ArtHandleTrackerManager (Event_t const &event, Config_t config={})
 Constructs a handle manager covering event. More...
 
template<typename Handle >
auto registerHandle (Handle &&handle) -> decltype(auto)
 
Queries
unsigned int nTrackedHandles () const
 Returns the number of handles currently tracked. More...
 
bool hasEvent () const
 Returns whether the object is associated to an event. More...
 
Registration of data products
template<typename T , typename... Args>
art::Handle< T > getHandle (Args &&...args)
 Retrieves an handle from the event, and registers it. More...
 
template<typename T , typename... Args>
art::ValidHandle< T > getValidHandle (Args &&...args)
 Retrieves a valid handle from the event, and registers it. More...
 
template<typename Handle >
decltype(auto) registerHandle (Handle &&handle)
 Registers an existing handle. More...
 
Operations
void useEvent (Event_t const &event)
 Changes the event being served. More...
 
unsigned int removeCachedProducts ()
 Clears the cached data products for all tracked handles. More...
 
void forgetAllHandles ()
 Stops tracking any handle, without removing their cache first. More...
 
unsigned int doneWithEvent (bool removeCache=true, art::Event const *event=nullptr)
 Completes the work on the associated event. More...
 

Private Types

using TrackerPtr = std::unique_ptr< util::ArtHandleTrackerInterface< Event_t >>
 Type of pointer to any handle tracker. More...
 

Private Member Functions

template<typename Handle >
Handle const * findHandle (Handle const &like) const
 Returns the pointer to an handle equivalent to like. More...
 
void canOperate (const char *where) const
 

Static Private Member Functions

template<typename Handle >
static bool handleSameProduct (TrackerPtr tracker, Handle const &handle)
 Returns whether tracker tracks the same product that handle handles. More...
 

Private Attributes

Event_t const * fEvent = nullptr
 Event being manager. Must be present! More...
 
Config_t const fConfig
 Configuration. More...
 
std::vector< TrackerPtrfTrackers
 List of managed handle trackers. More...
 

Detailed Description

template<typename Event>
class util::ArtHandleTrackerManager< Event >

Manages handle trackers for an easy call of removeCachedProduct().

Template Parameters
Eventthe type of data product source (the "principal") to serve

This handle manager is designed to simplify the usage of art::Event::removeCachedProduct() on multiple data products.

The envisioned usage model in a single-thread module is the following:

  1. The manager is a data member of the module (in alternative, it should be passed down to the places where data products are read, and at a minimum it needs to register all the handles it is supposed to "manage").
  2. The manager can ask the event to read a data product anew, and get an handle for it. It will register the handle, and return it.
    • The manager can also register an existing handle.
  3. The manager can deliver a stored handle (but that's a slow process in the current implementation and it requires the input tag to resolve ambiguities).
  4. Upon request, all handles are asked to remove their cached products. This request presumably happens at the end of the event-processing function (produce(), filter(), analyze()). Note that after an handle has its cached data removed, it's clear()'ed.

An handle manager can serve only one art event at a time. All handles come from that event (or are assumed to).

Example:

class MyModule: public art::EDAnalyzer {
art::InputTag const fTag;
// ...
void analyze(art::Event const & event) override
{
fDataCacheRemover.useEvent(event);
auto const& handle = fDataCacheRemover.getHandle<MyDataProduct>(fTag);
auto results = processData(*handle); // ... or whatever
fDataCacheRemover.removeCachedProducts(); // free caches after use
results.Write(); // ... or another portion of whatever
}
};

Or one can create the handle as preferred, and then register it:

class MyModule: public art::EDAnalyzer {
art::InputTag const fTag;
// ...
void analyze(art::Event const & event) override
{
fDataCacheRemover.useEvent(event);
auto const& handle = event.getValidHandle<MyDataProduct>(fTag);
fDataCacheRemover.registerHandle(handle);
auto results = processData(*handle); // ... or whatever
fDataCacheRemover.removeCachedProducts(); // free caches after use
results.Write(); // ... or another portion of whatever
}
};

Technical notes

Support for different types of handles

Currently, both art::Handle and art::ValidHandle (and nothing else) can be created by ArtHandleTrackerManager. The code can be extended to support any object that can be passed to art::Event::removeCachedProduct() (e.g. art::ProductID, if it will ever happen).

The current implementation is expected to be able to recognize handles pointing to the same data product even if they are of different type (e.g. art::Handle<T> and art::ValidHandle<T>). The manager stores a copy of the first type of handle registered for a given data product; then, if another handle of any type to the same data product is requested or registered, registerHandle() will return the same handle in argument, and the getHandle() family of functions will get and return a new handle. In both cases, no new registration will happen.

Multithreading

The current implementation is inherently not safe for art multithreading. While the inner data structure don't need global state, and the interface can easily be extended to allow for no global state as well, the operations are still performed on all the registered handles at once (meaning, when one thread asks for removeCachedProduct() or forgetAllHandles(), data from all events is affected). This can be overcome by changing the internal storage (to be reentrant and possibly by event) and a bit of the interface.

The object as it is now can be implemented on top of such object, preserving the current event information and delivering it to the new manager under the hood, with minimal overhead.

If such feature is needed, ask the author (and be prepared to test it).

Definition at line 32 of file ArtHandleTrackerManager.h.

Member Typedef Documentation

template<typename Event>
using util::ArtHandleTrackerManager< Event >::Event_t = Event

Type of data viewer object to operate with.

Definition at line 163 of file ArtHandleTrackerManager.h.

template<typename Event>
using util::ArtHandleTrackerManager< Event >::TrackerPtr = std::unique_ptr<util::ArtHandleTrackerInterface<Event_t>>
private

Type of pointer to any handle tracker.

Definition at line 322 of file ArtHandleTrackerManager.h.

Constructor & Destructor Documentation

template<typename Event >
util::ArtHandleTrackerManager< Event >::ArtHandleTrackerManager ( Config_t  config = {})

Constructs a handle manager.

Parameters
config(optional) the configuration to be used
See Also
useEvent()

An event must be later assigned to it (useEvent()) to make it functional.

Definition at line 783 of file ArtHandleTrackerManager.h.

784  : fConfig{ std::move(config) }
785 {}
Config_t const fConfig
Configuration.
template<typename Event >
util::ArtHandleTrackerManager< Event >::ArtHandleTrackerManager ( Event_t const &  event,
Config_t  config = {} 
)

Constructs a handle manager covering event.

Parameters
eventthe first data viewer (event) object to operate on

Definition at line 791 of file ArtHandleTrackerManager.h.

792  : fEvent{ &event }, fConfig{ std::move(config) }
793 {}
Config_t const fConfig
Configuration.
Event_t const * fEvent
Event being manager. Must be present!

Member Function Documentation

template<typename Event >
void util::ArtHandleTrackerManager< Event >::canOperate ( const char *  where) const
private

Checks that the object is in a state where it can perform operations.

Parameters
whereidentification of the calling function for error messages
Exceptions
art::Exception(code: art::errors::LogicError) on failure

Definition at line 981 of file ArtHandleTrackerManager.h.

981  {
982 
983  if (fEvent) return;
984 
985  throw art::Exception(art::errors::LogicError)
986  << "util::ArtHandleTrackerManager attempted an operation without a valid"
987  " event.\nThe operation was: " << where << "\n";
988 
989 } // util::ArtHandleTrackerManager<Event>::canOperate()
Event_t const * fEvent
Event being manager. Must be present!
template<typename Event>
unsigned int util::ArtHandleTrackerManager< Event >::doneWithEvent ( bool  removeCache = true,
art::Event const *  event = nullptr 
)

Completes the work on the associated event.

Parameters
removeCache(default: true) removes tracked data product caches
eventif specified, only acts on cache from this event
Returns
the number of cleared data product caches

This is a shortcut for having optional release of cache in a single call, depending on the value of removeCache:

In addition, the object is disassociated from the event, and a call to useEvent() will be needed before this object can be operative again.

If the event parameter is not null, a check is done that the event being currently used matches event, and if not no operation happens (0 is returned, but the object is not disassociated from its current event).

Definition at line 920 of file ArtHandleTrackerManager.h.

921 {
922  if (event && (fEvent != event)) return 0;
923 
924  unsigned int count = 0;
925  if (removeCache) count = removeCachedProducts();
926  else count = forgetAllHandles();
927 
928  fEvent = nullptr;
929 
930  return count;
931 } // util::ArtHandleTrackerManager<Event>::doneWithEvent()
void forgetAllHandles()
Stops tracking any handle, without removing their cache first.
Event_t const * fEvent
Event being manager. Must be present!
unsigned int removeCachedProducts()
Clears the cached data products for all tracked handles.
std::size_t count(Cont const &cont)
template<typename Event >
template<typename Handle >
Handle const * util::ArtHandleTrackerManager< Event >::findHandle ( Handle const &  like) const
private

Returns the pointer to an handle equivalent to like.

Template Parameters
Handlethe type of the handle being queried
Returns
a pointer to the handle, or nullptr if not found

This is an half-assed method since it needs to know already the exact type of the handle being queried (it's not even agnostic to the difference between art::Handle and art::ValidHandle). For this reason, it's not really useful to the users, who would probably want to know if the data product is cached, via any mean.

Technical note

Delegating the matching to util::ArtHandleTrackerInterface is not possible (like is a template parameter and can't be passed via virtual interface) and even working around that and finding the match, the returned value needs to be of type Handle, which is not necessarily the type of handle stored in the tracker.

For the full functionality of knowing if a data product is tracked, a separate registry may be kept, still complicated by the fact that part of the registry entry is a C++ type (we may need to store a sanitized std::type_info for that).

Definition at line 938 of file ArtHandleTrackerManager.h.

939 {
940 
941  // look for it, one by one
942  for (TrackerPtr const& tracker: fTrackers) {
943 
944 
945 
946  std::any anyHandlePtr = tracker->handlePtr();
947  Handle const** handlePtr = std::any_cast<Handle const*>(&anyHandlePtr);
948  if (!handlePtr) continue; // not the right type
949 
950  if ((*handlePtr)->provenance()->inputTag() != like.provenance()->inputTag())
951  continue; // different tag
952 
953  return *handlePtr;
954  } // for
955 
956  return nullptr; // failed
957 
958 } // util::ArtHandleTrackerManager<Event>::findTracker()
std::vector< TrackerPtr > fTrackers
List of managed handle trackers.
std::unique_ptr< util::ArtHandleTrackerInterface< Event_t >> TrackerPtr
Type of pointer to any handle tracker.
template<typename Event >
void util::ArtHandleTrackerManager< Event >::forgetAllHandles ( )

Stops tracking any handle, without removing their cache first.

Definition at line 911 of file ArtHandleTrackerManager.h.

912  { fTrackers.clear(); }
std::vector< TrackerPtr > fTrackers
List of managed handle trackers.
template<typename Event >
template<typename T , typename... Args>
art::Handle< T > util::ArtHandleTrackerManager< Event >::getHandle ( Args &&...  args)

Retrieves an handle from the event, and registers it.

Template Parameters
Ttype of data product to retrieve
Argstypes of the arguments needed by art::getHandle()
Parameters
argsall the arguments that art::getHandle() requires
Returns
the handle just read and being managed
See Also
getValidHandle(), registerHandle()

This function wraps art::Event::getHandle(), calling it to obtain the handle and then registering it (like with registerHandle()).

Definition at line 818 of file ArtHandleTrackerManager.h.

819 {
820  canOperate("getHandle()");
821  return registerHandle
822  (fEvent->template getHandle<T>(std::forward<Args>(args)...));
823 }
decltype(auto) registerHandle(Handle &&handle)
Registers an existing handle.
void canOperate(const char *where) const
Event_t const * fEvent
Event being manager. Must be present!
template<typename Event >
template<typename T , typename... Args>
art::ValidHandle< T > util::ArtHandleTrackerManager< Event >::getValidHandle ( Args &&...  args)

Retrieves a valid handle from the event, and registers it.

Template Parameters
Ttype of data product to retrieve
Argstypes of the arguments needed by art::getValidHandle()
Parameters
argsall the arguments that art::getValidHandle() requires
Returns
the handle just read and being managed
See Also
getHandle(), registerHandle()

This is the art::ValidHandle sibling of getHandle(). See that one for details.

Definition at line 830 of file ArtHandleTrackerManager.h.

831 {
832  canOperate("getValidHandle()");
833  return registerHandle
834  (fEvent->template getValidHandle<T>(std::forward<Args>(args)...));
835 }
decltype(auto) registerHandle(Handle &&handle)
Registers an existing handle.
void canOperate(const char *where) const
Event_t const * fEvent
Event being manager. Must be present!
template<typename Event >
template<typename Handle >
bool util::ArtHandleTrackerManager< Event >::handleSameProduct ( TrackerPtr  tracker,
Handle const &  handle 
)
staticprivate

Returns whether tracker tracks the same product that handle handles.

Definition at line 965 of file ArtHandleTrackerManager.h.

966 {
968 
969  if (!tracker) return false;
970  if (ProvenanceGetter<Handle>::productType() != tracker->productType())
971  return false;
972  if (ProvenanceGetter<Handle>::inputTag() != tracker->inputTag())
973  return false;
974 
975  return true;
976 } // util::ArtHandleTrackerManager<>::handleSameProduct()
template<typename Event >
bool util::ArtHandleTrackerManager< Event >::hasEvent ( ) const

Returns whether the object is associated to an event.

Definition at line 889 of file ArtHandleTrackerManager.h.

890  { return fEvent; }
Event_t const * fEvent
Event being manager. Must be present!
template<typename Event >
unsigned int util::ArtHandleTrackerManager< Event >::nTrackedHandles ( ) const

Returns the number of handles currently tracked.

Definition at line 883 of file ArtHandleTrackerManager.h.

884  { return fTrackers.size(); }
std::vector< TrackerPtr > fTrackers
List of managed handle trackers.
template<typename Event>
template<typename Handle >
decltype(auto) util::ArtHandleTrackerManager< Event >::registerHandle ( Handle &&  handle)

Registers an existing handle.

Template Parameters
Handlethe type of handle to register
Parameters
handlethe handle to be registered
Returns
handle (pass through)

This method registers a copy of handle into the manager.

template<typename Event>
template<typename Handle >
auto util::ArtHandleTrackerManager< Event >::registerHandle ( Handle &&  handle) -> decltype(auto)

Definition at line 842 of file ArtHandleTrackerManager.h.

843 {
845 
846  using Handle_t = std::decay_t<Handle>;
847 
848  canOperate("registerHandle()");
849 
851 
852  // if it's already registered, we don't want to have it again
853  if (auto ptr = findHandle(handle)) {
854  auto const& registeredHandle = *ptr;
855  mf::LogDebug msg { fConfig.logCategory };
856  msg
857  << "Handle<" << details::productClassOf(registeredHandle)
858  << ">(" << details::inputTagOf(registeredHandle).encode()
859  << ") was already registered";
860  if (typeid(registeredHandle) != typeid(Handle_t)) {
861  msg << " as a different handle type (" << typeid(registeredHandle).name()
862  << ", now " << typeid(Handle_t).name() << ")";
863  }
864  msg << ".";
865  }
866  else {
867  mf::LogDebug{ fConfig.logCategory }
868  << "Registering handle<" << details::productClassOf(handle)
869  << ">(" << details::inputTagOf(handle).encode()
870  << ") (handle type: " << typeid(Handle_t).name() << ")."
871  ;
872 
873  fTrackers.push_back(std::make_unique<Tracker_t>(*fEvent, handle));
874  }
875 
876  return std::forward<Handle>(handle);
877 
878 } // util::ArtHandleTrackerManager<>::registerHandle()
std::vector< TrackerPtr > fTrackers
List of managed handle trackers.
Config_t const fConfig
Configuration.
std::string logCategory
Name of the output category for messages.
void canOperate(const char *where) const
Handle const * findHandle(Handle const &like) const
Returns the pointer to an handle equivalent to like.
std::string productClassOf(Handle const &handle)
use candy
art::InputTag inputTagOf(Handle const &handle)
Event_t const * fEvent
Event being manager. Must be present!
then echo fcl name
template<typename Event >
unsigned int util::ArtHandleTrackerManager< Event >::removeCachedProducts ( )

Clears the cached data products for all tracked handles.

Returns
the number of tracked handles which had their cache removed

This method calls Event_t::removeCachedProduct() for all tracked handles. This is the core functionality of the manager, which removes the cache of all tracked handles.

The art framework always makes the handles used to remove the cache invalid (Handle::clear()). After the removal, the object stops tracking the handles (like with a call to forgetAllHandles()).

Calling this method when there are no handles registered has no effect.

Definition at line 895 of file ArtHandleTrackerManager.h.

895  {
896 
897  // we remove cache in opposite order to registration: it's a C++ tradition.
898  unsigned int const nRemoved = std::count_if(
899  fTrackers.crbegin(), fTrackers.crend(),
900  [](auto const& tracker){ return tracker->removeCachedProduct(); }
901  );
902 
904 
905  return nRemoved;
906 } // util::ArtHandleTrackerManager<Event>::removeCachedProducts()
std::vector< TrackerPtr > fTrackers
List of managed handle trackers.
void forgetAllHandles()
Stops tracking any handle, without removing their cache first.
template<typename Event >
void util::ArtHandleTrackerManager< Event >::useEvent ( Event_t const &  event)

Changes the event being served.

Parameters
eventthe new event being served
Exceptions
art::Exception(code: art::errors::LogicError) if there are still registered handles

The object starts tracking handles of a new event.

This method requires that any pending handle has been taken care of (even if the new event happens to be the same as the old one). Common options are removeCachedProductsAndForget() if cache removal is desired, or forgetAllHandles() if it's not.

Definition at line 798 of file ArtHandleTrackerManager.h.

798  {
799 
800  if (nTrackedHandles() > 0) {
801  // since fEvent might be invalid, we don't attempt to figure out which ID
802  // that event might have had
803  throw art::Exception{ art::errors::LogicError }
804  << "ArtHandleTrackerManager attempted to change event to "
805  << event.id() << " when " << nTrackedHandles()
806  << " handles are still tracked.\n";
807  }
808 
809  fEvent = &event;
810 
811 } // util::ArtHandleTrackerManager<Event>::useEvent()
unsigned int nTrackedHandles() const
Returns the number of handles currently tracked.
Event_t const * fEvent
Event being manager. Must be present!

Member Data Documentation

template<typename Event>
Config_t const util::ArtHandleTrackerManager< Event >::fConfig
private

Configuration.

Definition at line 328 of file ArtHandleTrackerManager.h.

template<typename Event>
Event_t const* util::ArtHandleTrackerManager< Event >::fEvent = nullptr
private

Event being manager. Must be present!

Definition at line 326 of file ArtHandleTrackerManager.h.

template<typename Event>
std::vector<TrackerPtr> util::ArtHandleTrackerManager< Event >::fTrackers
private

List of managed handle trackers.

Definition at line 331 of file ArtHandleTrackerManager.h.


The documentation for this class was generated from the following file: