//
// Copyright (c) ZeroC, Inc. All rights reserved.
//
namespace Ice
{
///
///
/// Callback that requires the application to down-cast the proxy.
///
///
public delegate void AsyncCallback(AsyncResult r);
///
///
/// Callback for the successful completion of an operation
/// that returns no data.
///
///
public delegate void OnewayCallback();
///
///
/// Callback to inform when a call has been passed to the local
/// transport.
///
///
public delegate void SentCallback(bool sentSynchronously);
///
///
/// Called when an invocation raises an exception.
///
///
public delegate void ExceptionCallback(Ice.Exception ex);
///
///
///
///
public interface AsyncResult : System.IAsyncResult
{
void cancel();
Communicator getCommunicator();
Connection getConnection();
ObjectPrx getProxy();
bool isCompleted_();
void waitForCompleted();
bool isSent();
void waitForSent();
void throwLocalException();
bool sentSynchronously();
string getOperation();
AsyncResult whenSent(AsyncCallback cb);
AsyncResult whenSent(SentCallback cb);
AsyncResult whenCompleted(ExceptionCallback excb);
}
public interface AsyncResult : AsyncResult
{
AsyncResult whenCompleted(T cb, ExceptionCallback excb);
new AsyncResult whenCompleted(ExceptionCallback excb);
new AsyncResult whenSent(SentCallback cb);
}
}
namespace IceInternal
{
using System.Diagnostics;
using System.Threading;
abstract public class AsyncResultI : Ice.AsyncResult
{
public virtual void cancel()
{
Debug.Assert(outgoing_ != null);
outgoing_.cancel();
}
public Ice.Communicator getCommunicator()
{
return _communicator;
}
public virtual Ice.Connection getConnection()
{
return null;
}
public virtual Ice.ObjectPrx getProxy()
{
return null;
}
public bool isCompleted_()
{
lock(this)
{
return (state_ & StateDone) != 0;
}
}
public void waitForCompleted()
{
lock(this)
{
while((state_ & StateDone) == 0)
{
Monitor.Wait(this);
}
}
}
public bool isSent()
{
lock(this)
{
return (state_ & StateSent) != 0;
}
}
public void waitForSent()
{
lock(this)
{
while((state_ & StateSent) == 0 && exception_ == null)
{
Monitor.Wait(this);
}
}
}
public void throwLocalException()
{
lock(this)
{
if(exception_ != null)
{
throw exception_;
}
}
}
public bool sentSynchronously()
{
Debug.Assert(outgoing_ != null);
return outgoing_.sentSynchronously(); // No lock needed
}
//
// Implementation of System.IAsyncResult properties
//
public bool IsCompleted
{
get
{
return isCompleted_();
}
}
public bool CompletedSynchronously
{
get
{
Debug.Assert(outgoing_ != null);
if(getProxy() != null && getProxy().ice_isTwoway())
{
return false;
}
return outgoing_.sentSynchronously();
}
}
public object AsyncState
{
get
{
return _cookie; // No lock needed, cookie is immutable.
}
}
public WaitHandle AsyncWaitHandle
{
get
{
lock(this)
{
if(waitHandle_ == null)
{
waitHandle_ = new EventWaitHandle(false, EventResetMode.ManualReset);
}
if((state_ & StateDone) != 0)
{
waitHandle_.Set();
}
return waitHandle_;
}
}
}
public OutgoingAsyncBase OutgoingAsync
{
get
{
return outgoing_;
}
}
public Ice.AsyncResult whenSent(Ice.AsyncCallback cb)
{
lock(this)
{
if(cb == null)
{
throw new System.ArgumentException("callback is null");
}
if(sentCallback_ != null)
{
throw new System.ArgumentException("sent callback already set");
}
sentCallback_ = cb;
if((state_ & StateSent) == 0)
{
return this;
}
}
if(outgoing_.sentSynchronously())
{
try
{
sentCallback_(this);
}
catch(System.Exception ex)
{
warning(ex);
}
}
else
{
instance_.clientThreadPool().dispatch(() =>
{
try
{
sentCallback_(this);
}
catch(System.Exception ex)
{
warning(ex);
}
}, cachedConnection_);
}
return this;
}
public Ice.AsyncResult whenSent(Ice.SentCallback cb)
{
lock(this)
{
if(cb == null)
{
throw new System.ArgumentException("callback is null");
}
if(sentCallback_ != null)
{
throw new System.ArgumentException("sent callback already set");
}
sentCallback_ = (Ice.AsyncResult r) =>
{
cb(r.sentSynchronously());
};
if((state_ & StateSent) == 0)
{
return this;
}
}
if(outgoing_.sentSynchronously())
{
try
{
cb(true);
}
catch(System.Exception ex)
{
warning(ex);
}
}
else
{
instance_.clientThreadPool().dispatch(() =>
{
try
{
cb(false);
}
catch(System.Exception ex)
{
warning(ex);
}
}, cachedConnection_);
}
return this;
}
public Ice.AsyncResult whenCompleted(Ice.ExceptionCallback cb)
{
if(cb == null)
{
throw new System.ArgumentException("callback is null");
}
lock(this)
{
if(exceptionCallback_ != null)
{
throw new System.ArgumentException("callback already set");
}
exceptionCallback_ = cb;
}
setCompletedCallback(getCompletedCallback());
return this;
}
public string getOperation()
{
return _operation;
}
public bool wait()
{
lock(this)
{
if((state_ & StateEndCalled) != 0)
{
throw new System.ArgumentException("end_ method called more than once");
}
state_ |= StateEndCalled;
while((state_ & StateDone) == 0)
{
Monitor.Wait(this);
}
if(exception_ != null)
{
throw exception_;
}
return (state_ & StateOK) != 0;
}
}
protected AsyncResultI(Ice.Communicator communicator,
Instance instance,
string op,
object cookie,
Ice.AsyncCallback cb)
{
instance_ = instance;
state_ = 0;
_communicator = communicator;
_operation = op;
exception_ = null;
_cookie = cookie;
completedCallback_ = cb;
}
protected void setCompletedCallback(Ice.AsyncCallback cb)
{
lock(this)
{
if(cb == null)
{
throw new System.ArgumentException("callback is null");
}
if(completedCallback_ != null)
{
throw new System.ArgumentException("callback already set");
}
completedCallback_ = cb;
if((state_ & StateDone) == 0)
{
return;
}
else if((getProxy() == null || !getProxy().ice_isTwoway()) && exception_ == null)
{
return;
}
}
instance_.clientThreadPool().dispatch(() =>
{
try
{
try
{
cb(this);
}
catch(System.AggregateException ex)
{
throw ex.InnerException;
}
}
catch(System.Exception ex)
{
warning(ex);
}
}, cachedConnection_);
}
abstract protected Ice.AsyncCallback getCompletedCallback();
public static AsyncResultI check(Ice.AsyncResult r, Ice.ObjectPrx prx, string operation)
{
if(r != null && r.getProxy() != prx)
{
throw new System.ArgumentException("Proxy for call to end_" + operation +
" does not match proxy that was used to call corresponding begin_" +
operation + " method");
}
return check(r, operation);
}
public static AsyncResultI check(Ice.AsyncResult r, string operation)
{
if(r == null)
{
throw new System.ArgumentException("AsyncResult == null");
}
if(r.getOperation() != operation)
{
throw new System.ArgumentException("Incorrect operation for end_" + operation + " method: " +
r.getOperation());
}
if(!(r is AsyncResultI))
{
throw new System.ArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
}
return (AsyncResultI)r;
}
protected void warning(System.Exception ex)
{
if(instance_.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0)
{
instance_.initializationData().logger.warning("exception raised by AMI callback:\n" + ex);
}
}
protected Instance instance_;
protected Ice.Instrumentation.InvocationObserver observer_;
protected Ice.Connection cachedConnection_;
private readonly Ice.Communicator _communicator;
private readonly string _operation;
private readonly object _cookie;
protected Ice.Exception exception_;
protected EventWaitHandle waitHandle_;
protected Ice.AsyncCallback completedCallback_;
protected Ice.AsyncCallback sentCallback_;
protected Ice.ExceptionCallback exceptionCallback_;
protected const int StateOK = 0x1;
protected const int StateDone = 0x2;
protected const int StateSent = 0x4;
protected const int StateEndCalled = 0x8;
protected int state_;
protected OutgoingAsyncBase outgoing_;
}
}