Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-07 04:36:26

0001 #include <set>
0002 #include <thread>
0003 #include "FWCore/Utilities/interface/ReusableObjectHolder.h"
0004 
0005 #include <cppunit/extensions/HelperMacros.h>
0006 
0007 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
0008 #define CXX_THREAD_AVAILABLE
0009 #endif
0010 
0011 class reusableobjectholder_test : public CppUnit::TestFixture {
0012   CPPUNIT_TEST_SUITE(reusableobjectholder_test);
0013   CPPUNIT_TEST(testConstruction);
0014   CPPUNIT_TEST(testDeletion);
0015   CPPUNIT_TEST(testSimultaneousUse);
0016   CPPUNIT_TEST_SUITE_END();
0017 
0018 public:
0019   void testConstruction();
0020   void testDeletion();
0021   void testSimultaneousUse();
0022 
0023   void setUp() {}
0024   void tearDown() {}
0025 };
0026 
0027 namespace {
0028   class CustomDeleter {
0029   public:
0030     CustomDeleter() = default;
0031     explicit CustomDeleter(int val) : expectedValue_{val} {}
0032 
0033     void operator()(int* obj) {
0034       CPPUNIT_ASSERT(obj != nullptr);
0035       CPPUNIT_ASSERT(*obj == expectedValue_);
0036       delete obj;
0037     }
0038 
0039   private:
0040     int expectedValue_ = -1;
0041   };
0042 }  // namespace
0043 
0044 void reusableobjectholder_test::testConstruction() {
0045   {
0046     edm::ReusableObjectHolder<int> intHolder;
0047     auto p = intHolder.tryToGet();
0048     CPPUNIT_ASSERT(p.get() == 0);
0049 
0050     intHolder.add(std::make_unique<int>(1));
0051     p = intHolder.tryToGet();
0052     CPPUNIT_ASSERT(p.get() != 0);
0053     CPPUNIT_ASSERT(*p == 1);
0054 
0055     auto p2 = intHolder.tryToGet();
0056     CPPUNIT_ASSERT(p2.get() == 0);
0057   }
0058   {
0059     edm::ReusableObjectHolder<int> intHolder;
0060     auto p = intHolder.makeOrGet([]() -> int* { return new int(1); });
0061     CPPUNIT_ASSERT(p.get() != 0);
0062     CPPUNIT_ASSERT(*p == 1);
0063 
0064     auto p2 = intHolder.tryToGet();
0065     CPPUNIT_ASSERT(p2.get() == 0);
0066   }
0067   {
0068     edm::ReusableObjectHolder<int> intHolder;
0069     auto p = intHolder.makeOrGetAndClear([]() -> int* { return new int(1); }, [](int* iV) { *iV = 0; });
0070     CPPUNIT_ASSERT(p.get() != 0);
0071     CPPUNIT_ASSERT(*p == 0);
0072 
0073     auto p2 = intHolder.tryToGet();
0074     CPPUNIT_ASSERT(p2.get() == 0);
0075   }
0076   {
0077     edm::ReusableObjectHolder<int, CustomDeleter> intHolder;
0078     auto p = intHolder.makeOrGet([]() { return std::unique_ptr<int, CustomDeleter>{new int{1}, CustomDeleter{1}}; });
0079     CPPUNIT_ASSERT(p.get() != nullptr);
0080     CPPUNIT_ASSERT(*p == 1);
0081 
0082     auto p2 = intHolder.tryToGet();
0083     CPPUNIT_ASSERT(p2.get() == nullptr);
0084   }
0085 }
0086 
0087 void reusableobjectholder_test::testDeletion() {
0088   //should also test that makeOrGetAndClear actually does a clear on returned objects
0089   {
0090     edm::ReusableObjectHolder<int> intHolder;
0091     intHolder.add(std::make_unique<int>(1));
0092     {
0093       auto p = intHolder.tryToGet();
0094       CPPUNIT_ASSERT(p.get() != 0);
0095       CPPUNIT_ASSERT(*p == 1);
0096 
0097       auto p2 = intHolder.tryToGet();
0098       CPPUNIT_ASSERT(p2.get() == 0);
0099 
0100       *p = 2;
0101     }
0102     {
0103       auto p = intHolder.tryToGet();
0104       CPPUNIT_ASSERT(p.get() != 0);
0105       CPPUNIT_ASSERT(*p == 2);
0106 
0107       auto p2 = intHolder.tryToGet();
0108       CPPUNIT_ASSERT(p2.get() == 0);
0109     }
0110   }
0111 
0112   {
0113     edm::ReusableObjectHolder<int> intHolder;
0114     {
0115       auto p = intHolder.makeOrGet([]() -> int* { return new int(1); });
0116       CPPUNIT_ASSERT(p.get() != 0);
0117       CPPUNIT_ASSERT(*p == 1);
0118       *p = 2;
0119 
0120       auto p2 = intHolder.tryToGet();
0121       CPPUNIT_ASSERT(p2.get() == 0);
0122     }
0123     {
0124       auto p = intHolder.makeOrGet([]() -> int* { return new int(1); });
0125       CPPUNIT_ASSERT(p.get() != 0);
0126       CPPUNIT_ASSERT(*p == 2);
0127 
0128       auto p2 = intHolder.tryToGet();
0129       CPPUNIT_ASSERT(p2.get() == 0);
0130 
0131       auto p3 = intHolder.makeOrGet([]() -> int* { return new int(1); });
0132       CPPUNIT_ASSERT(p3.get() != 0);
0133       CPPUNIT_ASSERT(*p3 == 1);
0134     }
0135   }
0136 
0137   {
0138     edm::ReusableObjectHolder<int> intHolder;
0139     int* address = 0;
0140     {
0141       auto p = intHolder.makeOrGetAndClear([]() -> int* { return new int(1); }, [](int* iV) { *iV = 0; });
0142       CPPUNIT_ASSERT(p.get() != 0);
0143       CPPUNIT_ASSERT(*p == 0);
0144       address = p.get();
0145       *p = 2;
0146 
0147       auto p2 = intHolder.tryToGet();
0148       CPPUNIT_ASSERT(p2.get() == 0);
0149     }
0150     {
0151       auto p = intHolder.makeOrGetAndClear([]() -> int* { return new int(1); }, [](int* iV) { *iV = 0; });
0152       CPPUNIT_ASSERT(p.get() != 0);
0153       CPPUNIT_ASSERT(*p == 0);
0154       CPPUNIT_ASSERT(address == p.get());
0155     }
0156   }
0157 
0158   {
0159     edm::ReusableObjectHolder<int, CustomDeleter> intHolder;
0160     {
0161       auto p = intHolder.makeOrGet([]() { return std::unique_ptr<int, CustomDeleter>{new int{1}, CustomDeleter{2}}; });
0162       CPPUNIT_ASSERT(p.get() != nullptr);
0163       CPPUNIT_ASSERT(*p == 1);
0164       *p = 2;
0165 
0166       auto p2 = intHolder.tryToGet();
0167       CPPUNIT_ASSERT(p2.get() == nullptr);
0168     }
0169     {
0170       auto p = intHolder.makeOrGet([]() { return std::unique_ptr<int, CustomDeleter>{new int{1}, CustomDeleter{2}}; });
0171       CPPUNIT_ASSERT(p.get() != nullptr);
0172       CPPUNIT_ASSERT(*p == 2);
0173 
0174       auto p2 = intHolder.tryToGet();
0175       CPPUNIT_ASSERT(p2.get() == nullptr);
0176     }
0177     {
0178       auto p = intHolder.makeOrGet([]() { return std::unique_ptr<int, CustomDeleter>{new int{1}, CustomDeleter{2}}; });
0179       CPPUNIT_ASSERT(p.get() != nullptr);
0180       CPPUNIT_ASSERT(*p == 2);
0181 
0182       {
0183         auto p3 =
0184             intHolder.makeOrGet([]() { return std::unique_ptr<int, CustomDeleter>{new int{3}, CustomDeleter{3}}; });
0185         CPPUNIT_ASSERT(p.get() != nullptr);
0186         CPPUNIT_ASSERT(*p3 == 3);
0187 
0188         auto p4 =
0189             intHolder.makeOrGet([]() { return std::unique_ptr<int, CustomDeleter>{new int{4}, CustomDeleter{4}}; });
0190         CPPUNIT_ASSERT(p.get() != nullptr);
0191         CPPUNIT_ASSERT(*p4 == 4);
0192       }
0193 
0194       auto p34 =
0195           intHolder.makeOrGet([]() { return std::unique_ptr<int, CustomDeleter>{new int{3}, CustomDeleter{3}}; });
0196       CPPUNIT_ASSERT(p.get() != nullptr);
0197       CPPUNIT_ASSERT(*p34 == 3 or *p34 == 4);
0198 
0199       auto p43 =
0200           intHolder.makeOrGet([]() { return std::unique_ptr<int, CustomDeleter>{new int{4}, CustomDeleter{4}}; });
0201       CPPUNIT_ASSERT(p.get() != nullptr);
0202       CPPUNIT_ASSERT(*p43 == 3 or *p43 == 4);
0203       CPPUNIT_ASSERT(*p34 != *p43);
0204 
0205       auto p5 = intHolder.makeOrGet([]() { return std::unique_ptr<int, CustomDeleter>{new int{5}, CustomDeleter{5}}; });
0206       CPPUNIT_ASSERT(p.get() != nullptr);
0207       CPPUNIT_ASSERT(*p5 == 5);
0208     }
0209   }
0210 }
0211 void reusableobjectholder_test::testSimultaneousUse() {
0212 #if defined(CXX_THREAD_AVAILABLE)
0213 
0214   std::set<int*> t1ItemsSeen, t2ItemsSeen;
0215   edm::ReusableObjectHolder<int> intHolder;
0216 
0217   const unsigned int kNGets = 10000000;
0218 
0219   std::thread t1([&]() {
0220     for (unsigned int i = 0; i < kNGets; ++i) {
0221       auto p = intHolder.makeOrGet([]() -> int* { return new int(1); });
0222       t1ItemsSeen.insert(p.get());
0223     }
0224   });
0225 
0226   std::thread t2([&]() {
0227     for (unsigned int i = 0; i < kNGets; ++i) {
0228       auto p = intHolder.makeOrGet([]() -> int* { return new int(1); });
0229       t2ItemsSeen.insert(p.get());
0230     }
0231   });
0232 
0233   t1.join();
0234   t2.join();
0235 
0236   std::cout << " # seen: " << t1ItemsSeen.size() << " " << t2ItemsSeen.size() << std::endl;
0237   CPPUNIT_ASSERT(t1ItemsSeen.size() > 0 && t1ItemsSeen.size() < 3);
0238   CPPUNIT_ASSERT(t2ItemsSeen.size() > 0 && t2ItemsSeen.size() < 3);
0239 #endif
0240 }
0241 
0242 CPPUNIT_TEST_SUITE_REGISTRATION(reusableobjectholder_test);