ywkaras commented on PR #9482:
URL: https://github.com/apache/trafficserver/pull/9482#issuecomment-1611644462

   I suggest using this alternate approach.  It only requires each 
NetVConnection object to have an additional pointer, rather than an array of 
pointers:
   ```
   #include <cstdint>
   
   namespace ts
   {
   
   // Returns offset from Base1 to Base2 in any instance of Derived.
   //
   template <class Derived, class Base1, class Base2>
   std::ptrdiff_t base_to_base_offset()
   {
     // Don't use 0 for dummy address of derived, since compiler may treat null 
address specially.
     //
     auto addr = reinterpret_cast<Derived *>(0x100);
   
     return reinterpret_cast<char *>(static_cast<Base2 *>(addr)) - 
reinterpret_cast<char *>(static_cast<Base1 *>(addr));
   }
   
   } // end namespace ts
   
   enum class X_SERVICE {
     Y1, Y2, Y3, NUM
   };
   
   template <class>
   struct X_Service;
   
   static std::ptrdiff_t const X_SERVICE_NONE{PTRDIFF_MIN};
   
   class X
   {
   public:
     X(std::ptrdiff_t const *service_ofs) : _service_ofs(service_ofs) {}
   
     template <class C>
     C const * get_service() const
     {
       auto ofs = _service_ofs[std::size_t(X_Service<C>::value)];
       if (X_SERVICE_NONE == ofs) {
         return nullptr;
       } else {
         return reinterpret_cast<C const *>(reinterpret_cast<char const 
*>(this) + ofs);
       }
     }
   
     template <class C>
     C * get_service()
     {
       std::ptrdiff_t ofs = _service_ofs[std::size_t(X_Service<C>::value)];
       if (X_SERVICE_NONE == ofs) {
         return nullptr;
       } else {
         return reinterpret_cast<C *>(reinterpret_cast<char *>(this) + ofs);
       }
     }
   
   private:
     // Indexed by service (S), where _service_ofs[S] is the offset from base 
class X to the base class for service
     // S in the same object, or NO_SERVICE if there is no base class in the 
object for service S.
     //
     std::ptrdiff_t const * const _service_ofs;
   
     int dummy_data;
   };
   
   struct Y1
   {
     int dummy_data;
   };
   
   template <>
   struct X_Service<Y1>
   {
     static X_SERVICE const value{X_SERVICE::Y1};
   };
   
   struct Y2
   {
     int dummy_data;
   };
   
   template <>
   struct X_Service<Y2>
   {
     static X_SERVICE const value{X_SERVICE::Y2};
   };
   
   struct Y3
   {
     int dummy_data;
   };
   
   template <>
   struct X_Service<Y3>
   {
     static X_SERVICE const value{X_SERVICE::Y3};
   };
   
   class D1 : public X, public Y1, public Y3
   {
   public:
     D1() : X(_service_ofs_table) {}
   
   private:
     static std::ptrdiff_t const * const _service_ofs_table;
   
     int dummy_data;
   };
   
   std::ptrdiff_t const * const D1::_service_ofs_table{[]() -> std::ptrdiff_t *
   {
     static std::ptrdiff_t tbl[std::size_t(X_SERVICE::NUM)];
   
     tbl[std::size_t(X_SERVICE::Y1)] = ts::base_to_base_offset<D1, X, Y1>();
     tbl[std::size_t(X_SERVICE::Y2)] = X_SERVICE_NONE;
     tbl[std::size_t(X_SERVICE::Y3)] = ts::base_to_base_offset<D1, X, Y3>();
   
     return tbl;
   }()};
   
   #include <cassert>
   
   int main()
   {
     D1 d1;
     X *xp = &d1;
   
     assert(xp->get_service<Y1>() == static_cast<Y1 *>(&d1));
     assert(xp->get_service<Y2>() == nullptr);
     assert(xp->get_service<Y3>() == static_cast<Y3 *>(&d1));
   
     return 0;
   }
   ```
   This performance test indicates the performance would be the same or 
slightly better:
   ```
   wkaras ~/STUFF/IF_VS_ARR
   $ cat scr2
   cat x2.cc
   echo ==============
   gcc -O3 -Wall -Wextra -pedantic -std=c++17 x2.cc -lstdc++
   time ./a.out
   echo ==============
   gcc -DWALT -O3 -Wall -Wextra -pedantic -std=c++17 x2.cc -lstdc++
   time ./a.out
   wkaras ~/STUFF/IF_VS_ARR
   $ . scr2
   int const Dim = 7;
   int const Idx = 4;
   int const Num_s = 1 << 14;
   int const Iters = 1 << 17;
   
   using Ofs_t = long long;
   
   char dummy;
   
   Ofs_t the_ofs_arr[Dim];
   
   struct S
   {
     char * volatile arr[Dim];
   
     Ofs_t volatile * volatile ofs_arr{the_ofs_arr};
   };
   
   S s[Num_s];
   
   S * volatile sp[Num_s];
   
   char * volatile cp;
   
   int main()
   {
     for (int i{0}; i < Num_s; ++i) {
       s[i].arr[Idx] = &dummy + i;
       sp[i] = s + i;
     }
   
     the_ofs_arr[Idx] = 42;
   
     #ifndef WALT
   
     for (int i{Iters}; i; --i) {
       for (int j{0}; j < Num_s; ++j) {
         char *p = sp[j]->arr[Idx];
         if (p) {
           cp = p;
         }
       }
     }
   
     #else
   
     char *dp = &dummy;
     for (int i{Iters}; i; --i) {
       for (int j{0}; j < Num_s; ++j) {
         Ofs_t ofs = sp[j]->ofs_arr[Idx];
         if (666 != ofs) {
           cp = dp + ofs;
         }
       }
     }
   
     #endif
   
     return 0;
   }
   ==============
   
   real 0m2.657s
   user 0m2.653s
   sys  0m0.004s
   ==============
   
   real 0m2.541s
   user 0m2.541s
   sys  0m0.000s
   wkaras ~/STUFF/IF_VS_ARR
   $ 
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to