diff options
author | Benoit Foucher <benoit@zeroc.com> | 2014-09-05 13:17:45 +0200 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2014-09-05 13:17:45 +0200 |
commit | 65d91832bd0f6bf55bfefd1244582cec2e5139dc (patch) | |
tree | e8aa359587a3605a5c6fa79f0842321554449c0b /cpp/src/Ice/OutgoingAsync.cpp | |
parent | JS minor fix, remove unused variables (diff) | |
download | ice-65d91832bd0f6bf55bfefd1244582cec2e5139dc.tar.bz2 ice-65d91832bd0f6bf55bfefd1244582cec2e5139dc.tar.xz ice-65d91832bd0f6bf55bfefd1244582cec2e5139dc.zip |
Added back to optmization to not call connection dispatch if not necessary
Diffstat (limited to 'cpp/src/Ice/OutgoingAsync.cpp')
-rw-r--r-- | cpp/src/Ice/OutgoingAsync.cpp | 83 |
1 files changed, 55 insertions, 28 deletions
diff --git a/cpp/src/Ice/OutgoingAsync.cpp b/cpp/src/Ice/OutgoingAsync.cpp index c9d0ac28234..509ba18ad06 100644 --- a/cpp/src/Ice/OutgoingAsync.cpp +++ b/cpp/src/Ice/OutgoingAsync.cpp @@ -608,12 +608,7 @@ IceInternal::OutgoingAsync::__finished(const Ice::Exception& exc) // try { - if(!handleException(exc)) // This will throw if the invocation can't be retried. - { - return; // Can't be retried immediately. - } - - __invoke(false); // Retry the invocation + handleException(exc); } catch(const Ice::Exception& ex) { @@ -640,9 +635,14 @@ IceInternal::OutgoingAsync::__invokeExceptionAsync(const Ice::Exception& ex) AsyncResult::__invokeExceptionAsync(ex); } -void +bool IceInternal::OutgoingAsync::__finished() { + // + // NOTE: this method is called from ConnectionI.parseMessage + // with the connection locked. Therefore, it must not invoke + // any user callbacks. + // assert(_proxy->ice_isTwoway()); // Can only be called for twoways. Ice::Byte replyStatus; @@ -789,15 +789,43 @@ IceInternal::OutgoingAsync::__finished() _state |= OK; } _monitor.notifyAll(); + + if(!_callback) + { + _observer.detach(); + return false; + } + return true; } - catch(const LocalException& ex) + catch(const LocalException& exc) { - __finished(ex); - return; - } + // + // We don't call finished(exc) here because we don't want + // to invoke the completion callback. The completion + // callback is invoked by the connection is this method + // returns true. + // + try + { + handleException(exc); + return false; // Invocation will be retried. + } + catch(const Ice::Exception& ex) + { + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor); + _state |= Done; + _os.resize(0); // Clear buffer now, instead of waiting for AsyncResult deallocation + _exception.reset(ex.ice_clone()); + _monitor.notifyAll(); - assert(replyStatus == replyOK || replyStatus == replyUserException); - __invokeCompleted(); + if(!_callback) + { + _observer.detach(); + return false; + } + return true; + } + } } bool @@ -851,39 +879,38 @@ IceInternal::OutgoingAsync::__invoke(bool synchronous) } } } - break; } catch(const RetryException&) { _proxy->__setRequestHandler(_handler, 0); // Clear request handler and retry. + continue; } catch(const Ice::Exception& ex) { - if(!handleException(ex)) // This will throw if the invocation can't be retried. - { - break; // Can't be retried immediately. - } + handleException(ex); } + break; } return _sentSynchronously; } -bool +void IceInternal::OutgoingAsync::handleException(const Ice::Exception& exc) { try { int interval = _proxy->__handleException(exc, _handler, _mode, _sent, _cnt); _observer.retried(); // Invocation is being retried. - if(interval > 0) - { - _instance->retryQueue()->add(this, interval); - return false; // Don't retry immediately, the retry queue will take care of the retry. - } - else - { - return true; // Retry immediately. - } + + // + // Schedule the retry. Note that we always schedule the retry + // on the retry queue even if the invocation can be retried + // immediately. This is required because it might not be safe + // to retry from this thread (this is for instance called by + // finished(BasicStream) which is called with the connection + // locked. + // + _instance->retryQueue()->add(this, interval); } catch(const Ice::Exception& ex) { |