summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/OutgoingAsync.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/Ice/OutgoingAsync.cpp')
-rw-r--r--cpp/src/Ice/OutgoingAsync.cpp60
1 files changed, 55 insertions, 5 deletions
diff --git a/cpp/src/Ice/OutgoingAsync.cpp b/cpp/src/Ice/OutgoingAsync.cpp
index f3b0f4046f4..13640e70677 100644
--- a/cpp/src/Ice/OutgoingAsync.cpp
+++ b/cpp/src/Ice/OutgoingAsync.cpp
@@ -35,7 +35,8 @@ void IceInternal::decRef(AMI_Object_ice_invoke* p) { p->__decRef(); }
IceInternal::OutgoingAsync::OutgoingAsync() :
__is(0),
- __os(0)
+ __os(0),
+ _state(StateUnsent)
{
}
@@ -50,6 +51,17 @@ IceInternal::OutgoingAsync::~OutgoingAsync()
void
IceInternal::OutgoingAsync::__finished(BasicStream& is)
{
+ //
+ // Wait until sending has completed.
+ //
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ while(_state < StateSent)
+ {
+ _monitor.wait();
+ }
+ }
+
assert(_reference);
assert(_connection);
assert(__is);
@@ -158,6 +170,17 @@ IceInternal::OutgoingAsync::__finished(BasicStream& is)
void
IceInternal::OutgoingAsync::__finished(const LocalException& exc)
{
+ //
+ // Wait until sending has completed.
+ //
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ while(_state < StateSent)
+ {
+ _monitor.wait();
+ }
+ }
+
assert(_reference);
assert(_connection);
assert(__is);
@@ -168,6 +191,8 @@ IceInternal::OutgoingAsync::__finished(const LocalException& exc)
_reference->locatorInfo->clearObjectCache(_reference);
}
+ bool doRetry = false;
+
//
// A CloseConnectionException indicates graceful server shutdown,
// and is therefore always repeatable without violating
@@ -176,10 +201,7 @@ IceInternal::OutgoingAsync::__finished(const LocalException& exc)
// can safely be repeated. Otherwise, we can also retry if the
// operation mode Nonmutating or Idempotent.
//
- bool canRetry = _mode == Nonmutating || _mode == Idempotent || dynamic_cast<const CloseConnectionException*>(&exc);
- bool doRetry = false;
-
- if(canRetry)
+ if(_mode == Nonmutating || _mode == Idempotent || dynamic_cast<const CloseConnectionException*>(&exc))
{
try
{
@@ -202,6 +224,11 @@ IceInternal::OutgoingAsync::__finished(const LocalException& exc)
if(doRetry)
{
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ assert(_state == StateSent);
+ _state = StateUnsent;
+ }
_connection = 0;
__send();
}
@@ -248,6 +275,7 @@ IceInternal::OutgoingAsync::__prepare(const ReferencePtr& ref, const string& ope
assert(!_connection);
assert(!__is);
assert(!__os);
+ assert(_state == StateUnsent);
_reference = ref;
_connection = _reference->getConnection();
@@ -280,6 +308,7 @@ IceInternal::OutgoingAsync::__send()
//assert(_connection); // Might be 0, in case we retry from __finished().
assert(__is);
assert(__os);
+ assert(_state == StateUnsent);
try
{
@@ -323,7 +352,22 @@ IceInternal::OutgoingAsync::__send()
}
catch(const LocalException& ex)
{
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ assert(_state == StateUnsent);
+ _state = StateSent;
+ _monitor.notify();
+ }
+
__finished(ex);
+ return;
+ }
+
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ assert(_state == StateUnsent);
+ _state = StateSent;
+ _monitor.notify();
}
}
@@ -341,6 +385,12 @@ IceInternal::OutgoingAsync::__cleanup()
__is = 0;
delete __os;
__os = 0;
+
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ assert(_state == StateSent);
+ _state = StateUnsent;
+ }
}
void