PolymorphicTransactionUsingMultipleInheritance

Polymorphic Transaction Using Multiple Inheritance

TLM 2.0 presents extension abilities using a vector of extensions inside the request structure. Another idea is to make the struct that is passed through the channel be polymorphic and use multiple inheritance to agregate each extension. When doing the communication, this big struct with extensions is downcasted to a simpler generic struct. Everyone know the generic struct, and can work with it. But the slave can try to cast the struct to get some known extension from it.

Some code to show this idea is bellow. Note that the target function representing the slave can use the default transaction struct directly, without any added cost. But some tests can be done to see if it "hides" some known extensions, in this case there is a cost.

  1. #include <iostream>
  2. using namespace std;
  3.  
  4.  
  5. // a generic transaction
  6. class A {
  7. public:
  8.   int a;
  9.   virtual ~A() {};
  10. };
  11.  
  12. // extension 1
  13. class B {
  14. public:
  15.   int b;
  16.   virtual ~B() {};
  17. };
  18.  
  19. // extension 2
  20. class C {
  21. public:
  22.   int c;
  23.   virtual ~C() {};
  24. };
  25.  
  26.  
  27.  
  28. // class used by initiator (the BIG transaction)
  29. class D: public B, public A, public C {
  30. public:
  31.   int d;
  32.   virtual ~D() {};
  33. };
  34.  
  35.  
  36. // This function represents a slave that is compatible with a generic transaction
  37. void target(A *AA)
  38. {
  39.   // use generic fields directly
  40.   cout << AA->a << endl;
  41.  
  42.   // try to find an extension (works!)
  43.   C *CC = dynamic_cast<C *>(AA);
  44.   if (CC) {
  45.     cout << "cast C ok. member c is " << CC->c << endl;
  46.   }
  47.  
  48.   // try to cast to the BIG transaction (works too!)
  49.   D *DD = dynamic_cast<D *>(AA);
  50.   if (DD) {
  51.     cout << "cast D ok. member d is " << DD->d << endl;
  52.   }
  53. }
  54.  
  55.  
  56. int main() {
  57.  
  58.   cout << hex;
  59.  
  60.   // Fill up a BIG transaction
  61.   D *DD = new D();
  62.   DD->a = 0xa;
  63.   DD->b = 0xb;
  64.   DD->c = 0xc;
  65.   DD->d = 0xd;
  66.  
  67.   // Send to slave (the BIG transaction is automatically casted to the base generic transaction)
  68.   target(DD);
  69. }