summaryrefslogtreecommitdiff
path: root/cpp/test/Ice/acm/AllTests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/test/Ice/acm/AllTests.cpp')
-rw-r--r--cpp/test/Ice/acm/AllTests.cpp519
1 files changed, 284 insertions, 235 deletions
diff --git a/cpp/test/Ice/acm/AllTests.cpp b/cpp/test/Ice/acm/AllTests.cpp
index 7eddf04df92..8c7e2f6a268 100644
--- a/cpp/test/Ice/acm/AllTests.cpp
+++ b/cpp/test/Ice/acm/AllTests.cpp
@@ -24,7 +24,9 @@ toString(int value)
return os.str();
}
-class LoggerI : public Ice::Logger, private IceUtil::Mutex
+class LoggerI : public Ice::EnableSharedFromThis<LoggerI>,
+ public Ice::Logger,
+ private IceUtil::Mutex
{
public:
@@ -93,7 +95,7 @@ public:
virtual Ice::LoggerPtr
cloneWithPrefix(const std::string&)
{
- return this;
+ return ICE_SHARED_FROM_THIS;
}
private:
@@ -111,13 +113,20 @@ private:
bool _started;
vector<string> _messages;
};
-typedef IceUtil::Handle<LoggerI> LoggerIPtr;
-
-class TestCase : public IceUtil::Thread, protected Ice::ConnectionCallback, protected IceUtil::Monitor<IceUtil::Mutex>
+ICE_DEFINE_PTR(LoggerIPtr, LoggerI);
+
+class TestCase :
+#ifdef ICE_CPP11_MAPPING
+ public enable_shared_from_this<TestCase>,
+#else
+ public IceUtil::Thread,
+ public Ice::CloseCallback, public Ice::HeartbeatCallback,
+#endif
+ protected IceUtil::Monitor<IceUtil::Mutex>
{
public:
- TestCase(const string& name, const RemoteCommunicatorPrx& com) :
+ TestCase(const string& name, const RemoteCommunicatorPrxPtr& com) :
_name(name), _com(com), _logger(new LoggerI()),
_clientACMTimeout(-1), _clientACMClose(-1), _clientACMHeartbeat(-1),
_serverACMTimeout(-1), _serverACMClose(-1), _serverACMHeartbeat(-1),
@@ -158,12 +167,19 @@ public:
_communicator->destroy();
}
- void
- join()
+#ifdef ICE_CPP11_MAPPING
+ void join(thread& t)
+#else
+ void join()
+#endif
{
cout << "testing " << _name << "... " << flush;
_logger->start();
+#ifdef ICE_CPP11_MAPPING
+ t.join();
+#else
getThreadControl().join();
+#endif
if(_msg.empty())
{
cout << "ok" << endl;
@@ -178,11 +194,26 @@ public:
virtual void
run()
{
- TestIntfPrx proxy = TestIntfPrx::uncheckedCast(_communicator->stringToProxy(
+ TestIntfPrxPtr proxy = ICE_UNCHECKED_CAST(TestIntfPrx, _communicator->stringToProxy(
_adapter->getTestIntf()->ice_toString()));
try
{
- proxy->ice_getConnection()->setCallback(this);
+#ifdef ICE_CPP11_MAPPING
+ auto self = shared_from_this();
+ proxy->ice_getConnection()->setCloseCallback(
+ [self](Ice::ConnectionPtr connection)
+ {
+ self->closed(move(connection));
+ });
+ proxy->ice_getConnection()->setHeartbeatCallback(
+ [self](Ice::ConnectionPtr connection)
+ {
+ self->heartbeat(move(connection));
+ });
+#else
+ proxy->ice_getConnection()->setCloseCallback(ICE_SHARED_FROM_THIS);
+ proxy->ice_getConnection()->setHeartbeatCallback(ICE_SHARED_FROM_THIS);
+#endif
runTestCase(_adapter, proxy);
}
catch(const std::exception& ex)
@@ -225,7 +256,7 @@ public:
}
}
- virtual void runTestCase(const RemoteObjectAdapterPrx&, const TestIntfPrx&) = 0;
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr&, const TestIntfPrxPtr&) = 0;
void
setClientACM(int timeout, int close, int heartbeat)
@@ -246,12 +277,12 @@ public:
protected:
const string _name;
- const RemoteCommunicatorPrx _com;
+ const RemoteCommunicatorPrxPtr _com;
string _msg;
LoggerIPtr _logger;
Ice::CommunicatorPtr _communicator;
- RemoteObjectAdapterPrx _adapter;
+ RemoteObjectAdapterPrxPtr _adapter;
int _clientACMTimeout;
int _clientACMClose;
@@ -263,306 +294,323 @@ protected:
int _heartbeat;
bool _closed;
};
-typedef IceUtil::Handle<TestCase> TestCasePtr;
-
-}
+ICE_DEFINE_PTR(TestCasePtr, TestCase);
-void
-allTests(const Ice::CommunicatorPtr& communicator)
+class InvocationHeartbeatTest : public TestCase
{
- string ref = "communicator:default -p 12010";
- RemoteCommunicatorPrx com = RemoteCommunicatorPrx::uncheckedCast(communicator->stringToProxy(ref));
-
- vector<TestCasePtr> tests;
+public:
- class InvocationHeartbeatTest : public TestCase
+ InvocationHeartbeatTest(const RemoteCommunicatorPrxPtr& com) :
+ TestCase("invocation heartbeat", com)
{
- public:
+ }
- InvocationHeartbeatTest(const RemoteCommunicatorPrx& com) :
- TestCase("invocation heartbeat", com)
- {
- }
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ proxy->sleep(2);
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
- {
- proxy->sleep(2);
+ Lock sync(*this);
+ test(_heartbeat >= 2);
+ }
+};
- Lock sync(*this);
- test(_heartbeat >= 2);
- }
- };
+class InvocationHeartbeatOnHoldTest : public TestCase
+{
+public:
- class InvocationHeartbeatOnHoldTest : public TestCase
+ InvocationHeartbeatOnHoldTest(const RemoteCommunicatorPrxPtr& com) :
+ TestCase("invocation with heartbeat on hold", com)
{
- public:
+ // Use default ACM configuration.
+ }
- InvocationHeartbeatOnHoldTest(const RemoteCommunicatorPrx& com) :
- TestCase("invocation with heartbeat on hold", com)
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ try
{
- // Use default ACM configuration.
+ // When the OA is put on hold, connections shouldn't
+ // send heartbeats, the invocation should therefore
+ // fail.
+ proxy->sleepAndHold(10);
+ test(false);
}
-
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
+ catch(const Ice::ConnectionTimeoutException&)
{
- try
- {
- // When the OA is put on hold, connections shouldn't
- // send heartbeats, the invocation should therefore
- // fail.
- proxy->sleepAndHold(10);
- test(false);
- }
- catch(const Ice::ConnectionTimeoutException&)
- {
- adapter->activate();
- proxy->interruptSleep();
+ adapter->activate();
+ proxy->interruptSleep();
- waitForClosed();
- }
+ waitForClosed();
}
- };
+ }
+};
- class InvocationNoHeartbeatTest : public TestCase
+class InvocationNoHeartbeatTest : public TestCase
+{
+public:
+
+ InvocationNoHeartbeatTest(const RemoteCommunicatorPrxPtr& com) :
+ TestCase("invocation with no heartbeat", com)
{
- public:
+ setServerACM(1, 2, 0); // Disable heartbeat on invocations
+ }
- InvocationNoHeartbeatTest(const RemoteCommunicatorPrx& com) :
- TestCase("invocation with no heartbeat", com)
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ try
{
- setServerACM(1, 2, 0); // Disable heartbeat on invocations
+ // Heartbeats are disabled on the server, the
+ // invocation should fail since heartbeats are
+ // expected.
+ proxy->sleep(10);
+ test(false);
}
-
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
+ catch(const Ice::ConnectionTimeoutException&)
{
- try
- {
- // Heartbeats are disabled on the server, the
- // invocation should fail since heartbeats are
- // expected.
- proxy->sleep(10);
- test(false);
- }
- catch(const Ice::ConnectionTimeoutException&)
- {
- proxy->interruptSleep();
+ proxy->interruptSleep();
- waitForClosed();
+ waitForClosed();
- Lock sync(*this);
- test(_heartbeat == 0);
- }
+ Lock sync(*this);
+ test(_heartbeat == 0);
}
- };
+ }
+};
+
+class InvocationHeartbeatCloseOnIdleTest : public TestCase
+{
+public:
- class InvocationHeartbeatCloseOnIdleTest : public TestCase
+ InvocationHeartbeatCloseOnIdleTest(const RemoteCommunicatorPrxPtr& com) :
+ TestCase("invocation with no heartbeat and close on idle", com)
{
- public:
+ setClientACM(1, 1, 0); // Only close on idle.
+ setServerACM(1, 2, 0); // Disable heartbeat on invocations
+ }
- InvocationHeartbeatCloseOnIdleTest(const RemoteCommunicatorPrx& com) :
- TestCase("invocation with no heartbeat and close on idle", com)
- {
- setClientACM(1, 1, 0); // Only close on idle.
- setServerACM(1, 2, 0); // Disable heartbeat on invocations
- }
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ // No close on invocation, the call should succeed this
+ // time.
+ proxy->sleep(2);
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
- {
- // No close on invocation, the call should succeed this
- // time.
- proxy->sleep(2);
+ Lock sync(*this);
+ test(_heartbeat == 0);
+ test(!_closed);
+ }
+};
- Lock sync(*this);
- test(_heartbeat == 0);
- test(!_closed);
- }
- };
+class CloseOnIdleTest : public TestCase
+{
+public:
- class CloseOnIdleTest : public TestCase
+ CloseOnIdleTest(const RemoteCommunicatorPrxPtr& com) : TestCase("close on idle", com)
{
- public:
+ setClientACM(1, 1, 0); // Only close on idle
+ }
- CloseOnIdleTest(const RemoteCommunicatorPrx& com) : TestCase("close on idle", com)
- {
- setClientACM(1, 1, 0); // Only close on idle
- }
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(1500)); // Idle for 1.5 seconds
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
- {
- IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(1500)); // Idle for 1.5 seconds
+ waitForClosed();
- waitForClosed();
+ Lock sync(*this);
+ test(_heartbeat == 0);
+ }
+};
- Lock sync(*this);
- test(_heartbeat == 0);
- }
- };
+class CloseOnInvocationTest : public TestCase
+{
+public:
- class CloseOnInvocationTest : public TestCase
+ CloseOnInvocationTest(const RemoteCommunicatorPrxPtr& com) : TestCase("close on invocation", com)
{
- public:
+ setClientACM(1, 2, 0); // Only close on invocation
+ }
- CloseOnInvocationTest(const RemoteCommunicatorPrx& com) : TestCase("close on invocation", com)
- {
- setClientACM(1, 2, 0); // Only close on invocation
- }
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(1500)); // Idle for 1.5 seconds
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
- {
- IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(1500)); // Idle for 1.5 seconds
+ Lock sync(*this);
+ test(_heartbeat == 0);
+ test(!_closed);
+ }
+};
- Lock sync(*this);
- test(_heartbeat == 0);
- test(!_closed);
- }
- };
+class CloseOnIdleAndInvocationTest : public TestCase
+{
+public:
- class CloseOnIdleAndInvocationTest : public TestCase
+ CloseOnIdleAndInvocationTest(const RemoteCommunicatorPrxPtr& com) : TestCase("close on idle and invocation", com)
{
- public:
+ setClientACM(1, 3, 0); // Only close on idle and invocation
+ }
- CloseOnIdleAndInvocationTest(const RemoteCommunicatorPrx& com) : TestCase("close on idle and invocation", com)
- {
- setClientACM(1, 3, 0); // Only close on idle and invocation
- }
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ //
+ // Put the adapter on hold. The server will not respond to
+ // the graceful close. This allows to test whether or not
+ // the close is graceful or forceful.
+ //
+ adapter->hold();
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(1500)); // Idle for 1.5 seconds
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
{
- //
- // Put the adapter on hold. The server will not respond to
- // the graceful close. This allows to test whether or not
- // the close is graceful or forceful.
- //
- adapter->hold();
- IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(1500)); // Idle for 1.5 seconds
+ Lock sync(*this);
+ test(_heartbeat == 0);
+ test(!_closed); // Not closed yet because of graceful close.
+ }
- {
- Lock sync(*this);
- test(_heartbeat == 0);
- test(!_closed); // Not closed yet because of graceful close.
- }
+ adapter->activate();
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(500));
- adapter->activate();
- IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(500));
+ waitForClosed();
+ }
+};
- waitForClosed();
- }
- };
+class ForcefulCloseOnIdleAndInvocationTest : public TestCase
+{
+public:
- class ForcefulCloseOnIdleAndInvocationTest : public TestCase
+ ForcefulCloseOnIdleAndInvocationTest(const RemoteCommunicatorPrxPtr& com) :
+ TestCase("forceful close on idle and invocation", com)
{
- public:
+ setClientACM(1, 4, 0); // Only close on idle and invocation
+ }
- ForcefulCloseOnIdleAndInvocationTest(const RemoteCommunicatorPrx& com) :
- TestCase("forceful close on idle and invocation", com)
- {
- setClientACM(1, 4, 0); // Only close on idle and invocation
- }
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ adapter->hold();
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(1500)); // Idle for 1.5 seconds
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
- {
- adapter->hold();
- IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(1500)); // Idle for 1.5 seconds
+ waitForClosed();
- waitForClosed();
+ Lock sync(*this);
+ test(_heartbeat == 0);
+ }
+};
- Lock sync(*this);
- test(_heartbeat == 0);
- }
- };
+class HeartbeatOnIdleTest : public TestCase
+{
+public:
- class HeartbeatOnIdleTest : public TestCase
+ HeartbeatOnIdleTest(const RemoteCommunicatorPrxPtr& com) : TestCase("heartbeat on idle", com)
{
- public:
+ setServerACM(1, -1, 2); // Enable server heartbeats.
+ }
- HeartbeatOnIdleTest(const RemoteCommunicatorPrx& com) : TestCase("heartbeat on idle", com)
- {
- setServerACM(1, -1, 2); // Enable server heartbeats.
- }
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(2000));
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
- {
- IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(2000));
+ Lock sync(*this);
+ test(_heartbeat >= 3);
+ }
+};
- Lock sync(*this);
- test(_heartbeat >= 3);
- }
- };
+class HeartbeatAlwaysTest : public TestCase
+{
+public:
- class HeartbeatAlwaysTest : public TestCase
+ HeartbeatAlwaysTest(const RemoteCommunicatorPrxPtr& com) : TestCase("heartbeat always", com)
{
- public:
+ setServerACM(1, -1, 3); // Enable server heartbeats.
+ }
- HeartbeatAlwaysTest(const RemoteCommunicatorPrx& com) : TestCase("heartbeat always", com)
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ for(int i = 0; i < 12; ++i)
{
- setServerACM(1, -1, 3); // Enable server heartbeats.
+ proxy->ice_ping();
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(200));
}
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
- {
- for(int i = 0; i < 12; ++i)
- {
- proxy->ice_ping();
- IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(200));
- }
+ Lock sync(*this);
+ test(_heartbeat >= 3);
+ }
+};
- Lock sync(*this);
- test(_heartbeat >= 3);
- }
- };
+class SetACMTest : public TestCase
+{
+public:
- class SetACMTest : public TestCase
+ SetACMTest(const RemoteCommunicatorPrxPtr& com) : TestCase("setACM/getACM", com)
{
- public:
+ setClientACM(15, 4, 0);
+ }
- SetACMTest(const RemoteCommunicatorPrx& com) : TestCase("setACM/getACM", com)
- {
- setClientACM(15, 4, 0);
- }
+ virtual void runTestCase(const RemoteObjectAdapterPrxPtr& adapter, const TestIntfPrxPtr& proxy)
+ {
+ Ice::ACM acm;
+ acm = proxy->ice_getCachedConnection()->getACM();
+ test(acm.timeout == 15);
+ test(acm.close == Ice::CloseOnIdleForceful);
+ test(acm.heartbeat == Ice::HeartbeatOff);
- virtual void runTestCase(const RemoteObjectAdapterPrx& adapter, const TestIntfPrx& proxy)
- {
- Ice::ACM acm;
- acm = proxy->ice_getCachedConnection()->getACM();
- test(acm.timeout == 15);
- test(acm.close == Ice::CloseOnIdleForceful);
- test(acm.heartbeat == Ice::HeartbeatOff);
-
- proxy->ice_getCachedConnection()->setACM(IceUtil::None, IceUtil::None, IceUtil::None);
- acm = proxy->ice_getCachedConnection()->getACM();
- test(acm.timeout == 15);
- test(acm.close == Ice::CloseOnIdleForceful);
- test(acm.heartbeat == Ice::HeartbeatOff);
-
- proxy->ice_getCachedConnection()->setACM(1, Ice::CloseOnInvocationAndIdle, Ice::HeartbeatAlways);
- acm = proxy->ice_getCachedConnection()->getACM();
- test(acm.timeout == 1);
- test(acm.close == Ice::CloseOnInvocationAndIdle);
- test(acm.heartbeat == Ice::HeartbeatAlways);
-
- // Make sure the client sends few heartbeats to the server
- proxy->waitForHeartbeat(2);
- }
- };
+ proxy->ice_getCachedConnection()->setACM(IceUtil::None, IceUtil::None, IceUtil::None);
+ acm = proxy->ice_getCachedConnection()->getACM();
+ test(acm.timeout == 15);
+ test(acm.close == Ice::CloseOnIdleForceful);
+ test(acm.heartbeat == Ice::HeartbeatOff);
- tests.push_back(new InvocationHeartbeatTest(com));
- tests.push_back(new InvocationHeartbeatOnHoldTest(com));
- tests.push_back(new InvocationNoHeartbeatTest(com));
- tests.push_back(new InvocationHeartbeatCloseOnIdleTest(com));
+ proxy->ice_getCachedConnection()->setACM(1, Ice::CloseOnInvocationAndIdle, Ice::HeartbeatAlways);
+ acm = proxy->ice_getCachedConnection()->getACM();
+ test(acm.timeout == 1);
+ test(acm.close == Ice::CloseOnInvocationAndIdle);
+ test(acm.heartbeat == Ice::HeartbeatAlways);
- tests.push_back(new CloseOnIdleTest(com));
- tests.push_back(new CloseOnInvocationTest(com));
- tests.push_back(new CloseOnIdleAndInvocationTest(com));
- tests.push_back(new ForcefulCloseOnIdleAndInvocationTest(com));
+ // Make sure the client sends few heartbeats to the server
+ proxy->waitForHeartbeat(2);
+ }
+};
- tests.push_back(new HeartbeatOnIdleTest(com));
- tests.push_back(new HeartbeatAlwaysTest(com));
- tests.push_back(new SetACMTest(com));
+}
+
+void
+allTests(const Ice::CommunicatorPtr& communicator)
+{
+ string ref = "communicator:" + getTestEndpoint(communicator, 0);
+ RemoteCommunicatorPrxPtr com = ICE_UNCHECKED_CAST(RemoteCommunicatorPrx, communicator->stringToProxy(ref));
+
+ vector<TestCasePtr> tests;
+
+ tests.push_back(ICE_MAKE_SHARED(InvocationHeartbeatTest, com));
+ tests.push_back(ICE_MAKE_SHARED(InvocationHeartbeatOnHoldTest, com));
+ tests.push_back(ICE_MAKE_SHARED(InvocationNoHeartbeatTest, com));
+ tests.push_back(ICE_MAKE_SHARED(InvocationHeartbeatCloseOnIdleTest, com));
+
+ tests.push_back(ICE_MAKE_SHARED(CloseOnIdleTest, com));
+ tests.push_back(ICE_MAKE_SHARED(CloseOnInvocationTest, com));
+ tests.push_back(ICE_MAKE_SHARED(CloseOnIdleAndInvocationTest, com));
+ tests.push_back(ICE_MAKE_SHARED(ForcefulCloseOnIdleAndInvocationTest, com));
+
+ tests.push_back(ICE_MAKE_SHARED(HeartbeatOnIdleTest, com));
+ tests.push_back(ICE_MAKE_SHARED(HeartbeatAlwaysTest, com));
+ tests.push_back(ICE_MAKE_SHARED(SetACMTest, com));
for(vector<TestCasePtr>::const_iterator p = tests.begin(); p != tests.end(); ++p)
{
(*p)->init();
}
+
+#ifdef ICE_CPP11_MAPPING
+ vector<pair<thread, TestCasePtr>> threads;
+ for(auto p = tests.begin(); p != tests.end(); ++p)
+ {
+ TestCasePtr testCase = *p;
+ thread t([testCase]()
+ {
+ testCase->run();
+ });
+ threads.push_back(make_pair(move(t), testCase));
+ }
+ for(auto p = threads.begin(); p != threads.end(); ++p)
+ {
+ p->second->join(p->first);
+ }
+#else
for(vector<TestCasePtr>::const_iterator p = tests.begin(); p != tests.end(); ++p)
{
(*p)->start();
@@ -571,6 +619,7 @@ allTests(const Ice::CommunicatorPtr& communicator)
{
(*p)->join();
}
+#endif
for(vector<TestCasePtr>::const_iterator p = tests.begin(); p != tests.end(); ++p)
{
(*p)->destroy();