void FlushBatch::invoke() { assert(_proxy || _connection); if(_connection) { if(_connection->flushBatchRequests(this)) { return; } Monitor<Mutex>::Lock sync(_monitor); while(!_exception.get() && !_sent) { _monitor.wait(); } if(_exception.get()) { _exception->ice_throw(); } return; } RequestHandlerPtr handler; try { handler = _proxy->__getRequestHandler(); if(handler->sendRequest(this)) { return; } bool timedOut = false; { Monitor<Mutex>::Lock sync(_monitor); int timeout = _proxy->__reference()->getInvocationTimeout(); if(timeout > 0) { Time now = Time::now(Time::Monotonic); Time deadline = now + Time::milliSeconds(timeout); while(!_exception.get() && !_sent && !timedOut) { _monitor.timedWait(deadline - now); if(!_exception.get() && !_sent) { now = Time::now(Time::Monotonic); timedOut = now >= deadline; } } } else { while(!_exception.get() && !_sent) { _monitor.wait(); } } } if(timedOut) { Ice::InvocationTimeoutException ex(__FILE__, __LINE__); handler->requestCanceled(this, ex); // // Wait for the exception to propagate. It's possible the request handler ignores // the timeout if there was a failure shortly before requestTimedOut got called. // In this case, the exception should be set on the Outgoing. // Monitor<Mutex>::Lock sync(_monitor); while(!_exception.get() && !_sent) { _monitor.wait(); } } if(_exception.get()) { _exception->ice_throw(); } } catch(const RetryException& ex) { _proxy->__setRequestHandler(handler, 0); // Clear request handler ex.get()->ice_throw(); // Throw to notify the user that batch requests were potentially lost. } catch(const Ice::Exception& ex) { _proxy->__setRequestHandler(handler, 0); // Clear request handler _observer.failed(ex.ice_name()); throw; // Throw to notify the user that batch requests were potentially lost. } }