|
| 1 | +/** |
| 2 | + * Test runtime behavior when throwing a plain C++ pointer in recursion |
| 3 | + */ |
| 4 | + |
| 5 | +#include "test_config.h" |
| 6 | +#include <cstdio> |
| 7 | +#include <vector> |
| 8 | +#include <memory> |
| 9 | + |
| 10 | +namespace DynamicAny { |
| 11 | + struct DynAny { virtual ~DynAny() = default; }; |
| 12 | + struct DynValue : virtual DynAny {}; |
| 13 | + struct DynValueCommon : virtual DynAny {}; |
| 14 | +} |
| 15 | + |
| 16 | +struct TAO_DynCommon : virtual DynamicAny::DynAny { |
| 17 | + virtual ~TAO_DynCommon() |
| 18 | + { |
| 19 | + ACE_DEBUG ((LM_DEBUG, ACE_TEXT("~TAO_DynCommon %@\n"), this)); |
| 20 | + } |
| 21 | +}; |
| 22 | +struct TAO_DynAny_i : virtual TAO_DynCommon, virtual DynamicAny::DynAny { |
| 23 | + virtual ~TAO_DynAny_i() { ACE_DEBUG ((LM_DEBUG, ACE_TEXT("~TAO_DynAny_i %@\n"), this)); } |
| 24 | +}; |
| 25 | +struct TAO_DynValueCommon_i : virtual TAO_DynAny_i, virtual DynamicAny::DynValueCommon { |
| 26 | + virtual ~TAO_DynValueCommon_i() { ACE_DEBUG ((LM_DEBUG, ACE_TEXT("~TAO_DynValueCommon_i %@\n"), this)); } |
| 27 | +}; |
| 28 | +// ============================================================ |
| 29 | +// CreateDynAnyUtils<T> |
| 30 | +// ============================================================ |
| 31 | +template<typename DA_IMPL> |
| 32 | +struct CreateDynAnyUtils { |
| 33 | + static DA_IMPL* create(bool trigger, int depth = 0) { |
| 34 | + ACE_DEBUG ((LM_DEBUG, ACE_TEXT("[Create depth=%d] new DA_IMPL\n"), depth)); |
| 35 | + DA_IMPL* p = new DA_IMPL(); |
| 36 | + std::unique_ptr<DA_IMPL> guard(p); |
| 37 | + try { |
| 38 | + p->from_inputCDR(trigger, depth); |
| 39 | + } |
| 40 | + catch (DA_IMPL* original) { |
| 41 | + ACE_DEBUG ((LM_DEBUG, ACE_TEXT("!!! CAUGHT pointer %@ at depth %d (destroying blank %@) !!!\n"), |
| 42 | + original, depth, p)); |
| 43 | + return original; |
| 44 | + } |
| 45 | + return guard.release(); |
| 46 | + } |
| 47 | +}; |
| 48 | +// ============================================================ |
| 49 | +// TAO_DynValue_i |
| 50 | +// ============================================================ |
| 51 | +struct TAO_DynValue_i : virtual DynamicAny::DynValue, virtual TAO_DynValueCommon_i { |
| 52 | + TAO_DynValue_i() { ACE_DEBUG ((LM_DEBUG, ACE_TEXT("TAO_DynValue_i ctor %@\n"), this)); } |
| 53 | + ~TAO_DynValue_i() override { ACE_DEBUG ((LM_DEBUG, ACE_TEXT("~TAO_DynValue_i dtor %@\n"), this)); } |
| 54 | + static TAO_DynValue_i* cached ; |
| 55 | + std::vector<void*> da_members_; |
| 56 | + void from_inputCDR(bool trigger_indirection, int depth) { |
| 57 | + ACE_DEBUG ((LM_DEBUG, ACE_TEXT(" from_inputCDR depth=%d this=%@\n"), depth, this)); |
| 58 | + // Simulates deep recursion of ACE_TAO (exactly like in the real DynValue_i) |
| 59 | + if (depth < 3) { |
| 60 | + ACE_DEBUG ((LM_DEBUG, ACE_TEXT(" Creating nested member at depth %d\n"), depth + 1)); |
| 61 | + try { |
| 62 | + auto* member = CreateDynAnyUtils<TAO_DynValue_i>::create(trigger_indirection, depth + 1); |
| 63 | + da_members_.push_back(member); |
| 64 | + } |
| 65 | + catch (TAO_DynValue_i* orig) { |
| 66 | + ACE_DEBUG ((LM_DEBUG,ACE_TEXT(" Nested member threw indirection %@\n"), orig)); |
| 67 | + da_members_.push_back(orig); |
| 68 | + } |
| 69 | + } |
| 70 | + if (trigger_indirection && cached && depth >= 2) { |
| 71 | + ACE_DEBUG ((LM_DEBUG,ACE_TEXT("*** INDIRECTION - THROWING CACHED POINTER %@ ***\n"), cached)); |
| 72 | + cached->_add_ref(); |
| 73 | + throw cached; // throw of the raw pointer |
| 74 | + } |
| 75 | + if (!cached) cached = this; |
| 76 | + } |
| 77 | + void _add_ref() { ACE_DEBUG ((LM_DEBUG, ACE_TEXT(" _add_ref on %@\n"), this)); } |
| 78 | +}; |
| 79 | +TAO_DynValue_i* TAO_DynValue_i::cached = nullptr; |
| 80 | + |
| 81 | +int run_main (int, ACE_TCHAR*[]) |
| 82 | +{ |
| 83 | + ACE_START_TEST (ACE_TEXT ("Compiler_Features_43_Test")); |
| 84 | + |
| 85 | + int res = {}; |
| 86 | + |
| 87 | + TAO_DynValue_i::cached = nullptr; |
| 88 | + try |
| 89 | + { |
| 90 | + auto* result = CreateDynAnyUtils<TAO_DynValue_i>::create(true, 0); |
| 91 | + ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Success - returned %@\n"), result)); |
| 92 | + delete result; |
| 93 | + } |
| 94 | + catch (...) { |
| 95 | + ACE_ERROR ((LM_ERROR, ACE_TEXT("In outer catch\n"))); |
| 96 | + res = -1; |
| 97 | + } |
| 98 | + |
| 99 | + ACE_END_TEST; |
| 100 | + |
| 101 | + return res; |
| 102 | +} |
0 commit comments