private void flushRequests() { _m.Lock(); try { Debug.Assert(_connection != null && !_initialized); while (_batchRequestInProgress) { _m.Wait(); } // // We set the _flushing flag to true to prevent any additional queuing. Callers // might block for a little while as the queued requests are being sent but this // shouldn't be an issue as the request sends are non-blocking. // _flushing = true; } finally { _m.Unlock(); } LinkedList <Request> sentCallbacks = new LinkedList <Request>(); try { LinkedListNode <Request> p = _requests.First; // _requests is immutable when _flushing = true while (p != null) { Request request = p.Value; if (request.@out != null) { if (_connection.sendAsyncRequest(request.@out, _compress, _response, out request.sentCallback)) { if (request.sentCallback != null) { sentCallbacks.AddLast(request); } } } else if (request.batchOut != null) { if (_connection.flushAsyncBatchRequests(request.batchOut, out request.sentCallback)) { if (request.sentCallback != null) { sentCallbacks.AddLast(request); } } } else { BasicStream os = new BasicStream(request.os.instance(), Ice.Util.currentProtocolEncoding); _connection.prepareBatchRequest(os); try { request.os.pos(0); os.writeBlob(request.os.readBlob(request.os.size())); } catch (Ice.LocalException) { _connection.abortBatchRequest(); throw; } _connection.finishBatchRequest(os, _compress); } LinkedListNode <Request> tmp = p; p = p.Next; _requests.Remove(tmp); } } catch (LocalExceptionWrapper ex) { _m.Lock(); try { Debug.Assert(_exception == null && _requests.Count > 0); _exception = ex.get(); _reference.getInstance().clientThreadPool().dispatch(delegate() { flushRequestsWithException(ex); }); } finally { _m.Unlock(); } } catch (Ice.LocalException ex) { _m.Lock(); try { Debug.Assert(_exception == null && _requests.Count > 0); _exception = ex; _reference.getInstance().clientThreadPool().dispatch(delegate() { flushRequestsWithException(ex); }); } finally { _m.Unlock(); } } if (sentCallbacks.Count > 0) { Instance instance = _reference.getInstance(); instance.clientThreadPool().dispatch(delegate() { foreach (Request r in sentCallbacks) { if (r.@out != null) { [email protected]__(r.sentCallback); } else if (r.batchOut != null) { r.batchOut.sent__(r.sentCallback); } } }); } // // We've finished sending the queued requests and the request handler now send // the requests over the connection directly. It's time to substitute the // request handler of the proxy with the more efficient connection request // handler which does not have any synchronization. This also breaks the cyclic // reference count with the proxy. // // NOTE: _updateRequestHandler is immutable once _flushing = true // if (_updateRequestHandler && _exception == null) { _proxy.setRequestHandler__(_delegate, new ConnectionRequestHandler(_reference, _connection, _compress)); } _m.Lock(); try { Debug.Assert(!_initialized); if (_exception == null) { _initialized = true; _flushing = false; } _proxy = null; // Break cyclic reference count. _delegate = null; // Break cyclic reference count. _m.NotifyAll(); } finally { _m.Unlock(); } }