Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite SimActivityRegistryEnroller with variadic types #33202

Merged
merged 6 commits into from
Mar 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions SimG4Core/Notification/interface/SimActivityRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
// Created: Sun Nov 13 11:43:40 EST 2005
//

// system include files
#include "boost/bind.hpp"
#include "boost/mem_fn.hpp"

// user include files
#include "SimG4Core/Notification/interface/Signaler.h"

Expand Down
60 changes: 19 additions & 41 deletions SimG4Core/Notification/interface/SimActivityRegistryEnroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,6 @@
// Original Author: Chris Jones
// Created: Sun Nov 13 15:08:12 EST 2005
//

// system include files
#include "boost/mpl/pop_back.hpp"
#include "boost/mpl/begin_end.hpp"
#include "boost/mpl/copy_if.hpp"
#include "boost/mpl/deref.hpp"
#include "boost/mpl/prior.hpp"
#include "boost/mpl/vector.hpp"
#include "boost/mpl/eval_if.hpp"
#include "boost/mpl/empty.hpp"

// user include files
#include "SimG4Core/Notification/interface/Observer.h"
#include "SimG4Core/Notification/interface/SimActivityRegistry.h"
Expand All @@ -40,47 +29,36 @@ namespace enroller_helper {
static void enroll(SimActivityRegistry&, void*) {}
};

//this class is used to terminate our recursion
template <class T>
struct LastEnrollerHelper {
static void enroll(SimActivityRegistry&, T*) {}
};

template <class T, class TVector>
struct EnrollerHelper {
typedef typename boost::mpl::pop_back<TVector>::type RemainingVector;
static void enroll(SimActivityRegistry& iReg, T* iT) {
//Try to enroll the object if it inherits from the class at the
// end of TVector
Enrollment<typename boost::mpl::deref<
typename boost::mpl::prior<typename boost::mpl::end<TVector>::type>::type>::type>::enroll(iReg, iT);
static void enroll(SimActivityRegistry& iReg, T* iT) {}

//If TVector is not at its end, call EnrollerHelper with a vector
// that had our last type 'popped off' the end
typedef typename boost::mpl::eval_if<
boost::mpl::empty<TVector>,
boost::mpl::identity<LastEnrollerHelper<T> >,
boost::mpl::identity<EnrollerHelper<T, typename boost::mpl::pop_back<TVector>::type> > >::type NextEnroller;
NextEnroller::enroll(iReg, iT);
}
};
template <class T, class F, class... TVector>
static void enroll(SimActivityRegistry& iReg, T* iT) {
//Try to enroll the object if it inherits from the class at the
// start of TVector
Enrollment<F>::enroll(iReg, iT);
enroll<T, TVector...>(iReg, iT);
}

} // namespace enroller_helper

class SimActivityRegistryEnroller {
public:
SimActivityRegistryEnroller() {}
//virtual ~SimActivityRegistryEnroller();
typedef boost::mpl::
vector<BeginOfJob, DDDWorld, BeginOfRun, BeginOfEvent, BeginOfTrack, BeginOfStep, G4Step, EndOfTrack, EndOfEvent, EndOfRun>
Signals;

// ---------- const member functions ---------------------

// ---------- static member functions --------------------
template <class T>
static void enroll(SimActivityRegistry& iReg, T* iObj) {
enroller_helper::EnrollerHelper<T, Signals>::enroll(iReg, iObj);
enroller_helper::enroll<T,
BeginOfJob,
DDDWorld,
BeginOfRun,
BeginOfEvent,
BeginOfTrack,
BeginOfStep,
G4Step,
EndOfTrack,
EndOfEvent,
EndOfRun>(iReg, iObj);
}

// stop default
Expand Down
1 change: 0 additions & 1 deletion SimG4Core/Notification/test/BuildFile.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<use name="boost"/>
<use name="cppunit"/>
<use name="SimG4Core/Notification"/>
<bin name="testSimG4CoreNotifications" file="simactivityregistry_t.cppunit.cpp">
Expand Down
159 changes: 159 additions & 0 deletions SimG4Core/Notification/test/simactivityregistryNew_t.cppunit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* serviceregistry_t.cppunit.cc
* CMSSW
*
* Created by Chris Jones on 9/7/05.
*
*/

//need to open a 'back door' to be able to setup the SimActivityRegistry
#include "SimG4Core/Notification/interface/SimActivityRegistry.h"
#include "SimG4Core/Notification/interface/SimActivityRegistryEnrollerNew.h"
#include "SimG4Core/Notification/interface/Observer.h"

#include <cppunit/extensions/HelperMacros.h>

class testSimActivityRegistry : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(testSimActivityRegistry);

CPPUNIT_TEST(signalTest);
CPPUNIT_TEST(signalForwardingTest);
CPPUNIT_TEST(enrollerTest);

CPPUNIT_TEST_SUITE_END();

public:
void setUp() override {}
void tearDown() override {}

void signalTest();
void signalForwardingTest();
void enrollerTest();
};

///registration of the test so that the runner can find it
CPPUNIT_TEST_SUITE_REGISTRATION(testSimActivityRegistry);

namespace {
template <class T>
struct MyObserver : public Observer<const T*> {
mutable bool saw_;
MyObserver() : saw_(false) {}
void update(const T*) override { saw_ = true; }
};
} // namespace

#define TEST(signal, SIGNAL) \
MyObserver<SIGNAL> watch##SIGNAL; \
registry.connect(&watch##SIGNAL); \
const SIGNAL* p##SIGNAL = 0; \
registry.signal##Signal_(p##SIGNAL); \
CPPUNIT_ASSERT(watch##SIGNAL.saw_);

void testSimActivityRegistry::signalTest() {
SimActivityRegistry registry;

for (int i = 0; i < 1000; i++) {
TEST(beginOfRun, BeginOfRun);
TEST(beginOfJob, BeginOfJob);
TEST(beginOfEvent, BeginOfEvent);
TEST(beginOfTrack, BeginOfTrack);
TEST(dddWorld, DDDWorld);
TEST(g4Step, G4Step);

TEST(endOfRun, EndOfRun);
TEST(endOfEvent, EndOfEvent);
TEST(endOfTrack, EndOfTrack);
}
}

#define TESTF(signal, SIGNAL) \
MyObserver<SIGNAL> watch##SIGNAL; \
registry2.connect(&watch##SIGNAL); \
const SIGNAL* p##SIGNAL = 0; \
registry.signal##Signal_(p##SIGNAL); \
CPPUNIT_ASSERT(watch##SIGNAL.saw_);

void testSimActivityRegistry::signalForwardingTest() {
SimActivityRegistry registry;
SimActivityRegistry registry2;
registry.connect(registry2);

for (int i = 0; i < 1000; i++) {
TESTF(beginOfRun, BeginOfRun);
TESTF(beginOfJob, BeginOfJob);
TESTF(beginOfEvent, BeginOfEvent);
TESTF(beginOfTrack, BeginOfTrack);
TESTF(dddWorld, DDDWorld);
TESTF(g4Step, G4Step);

TESTF(endOfRun, EndOfRun);
TESTF(endOfEvent, EndOfEvent);
TESTF(endOfTrack, EndOfTrack);
}
}

namespace {

template <class T>
struct Counting : public Observer<const T*> {
int& count_;
Counting(int& iCount) : count_(iCount) {}
void update(const T*) override { ++count_; }
};
struct NoSignal {};

struct OneSignal : public Counting<BeginOfEvent> {
OneSignal(int& iCount) : Counting<BeginOfEvent>(iCount) {}
};

struct TwoSignals : public Counting<BeginOfEvent>, public Counting<EndOfEvent> {
TwoSignals(int& iCount) : Counting<BeginOfEvent>(iCount), Counting<EndOfEvent>(iCount) {}
};

} // namespace

#define TESTREG(signal, SIGNAL) \
int count##SIGNAL = 0; \
Counting<SIGNAL> watch##SIGNAL(count##SIGNAL); \
enroller.enroll(registry, &watch##SIGNAL); \
const SIGNAL* p##SIGNAL = 0; \
registry.signal##Signal_(p##SIGNAL); \
CPPUNIT_ASSERT(1 == watch##SIGNAL.count_);

void testSimActivityRegistry::enrollerTest() {
SimActivityRegistry registry;

NoSignal noSignal;
SimActivityRegistryEnrollerNew enroller;
enroller.enroll(registry, &noSignal);

int int1Signal = 0;
OneSignal oneSignal(int1Signal);
enroller.enroll(registry, &oneSignal);

int int2Signals = 0;
TwoSignals twoSignals(int2Signals);
enroller.enroll(registry, &twoSignals);

const BeginOfEvent* pBegin = nullptr;
registry.beginOfEventSignal_(pBegin);

const EndOfEvent* pEnd = nullptr;
registry.endOfEventSignal_(pEnd);

CPPUNIT_ASSERT(1 == int1Signal);
CPPUNIT_ASSERT(2 == int2Signals);

TESTREG(beginOfRun, BeginOfRun);
TESTREG(beginOfJob, BeginOfJob);
TESTREG(beginOfEvent, BeginOfEvent);
TESTREG(beginOfTrack, BeginOfTrack);
TESTREG(dddWorld, DDDWorld);
TESTREG(g4Step, G4Step);

TESTREG(endOfRun, EndOfRun);
TESTREG(endOfEvent, EndOfEvent);
TESTREG(endOfTrack, EndOfTrack);
}
#include <Utilities/Testing/interface/CppUnit_testdriver.icpp>