1 // 2 // Copyright (c) ZeroC, Inc. All rights reserved. 3 // 4 5 namespace Ice 6 { 7 /// 8 /// <summary> 9 /// Callback that requires the application to down-cast the proxy. 10 /// </summary> 11 /// AsyncCallback(AsyncResult r)12 public delegate void AsyncCallback(AsyncResult r); 13 14 /// 15 /// <summary> 16 /// Callback for the successful completion of an operation 17 /// that returns no data. 18 /// </summary> 19 /// OnewayCallback()20 public delegate void OnewayCallback(); 21 22 /// 23 /// <summary> 24 /// Callback to inform when a call has been passed to the local 25 /// transport. 26 /// </summary> 27 /// SentCallback(bool sentSynchronously)28 public delegate void SentCallback(bool sentSynchronously); 29 30 /// 31 /// <summary> 32 /// Called when an invocation raises an exception. 33 /// </summary> 34 /// ExceptionCallback(Ice.Exception ex)35 public delegate void ExceptionCallback(Ice.Exception ex); 36 37 /// 38 /// <summary> 39 /// <!-- TODO --> 40 /// </summary> 41 public interface AsyncResult : System.IAsyncResult 42 { cancel()43 void cancel(); 44 getCommunicator()45 Communicator getCommunicator(); 46 getConnection()47 Connection getConnection(); 48 getProxy()49 ObjectPrx getProxy(); 50 isCompleted_()51 bool isCompleted_(); 52 waitForCompleted()53 void waitForCompleted(); 54 isSent()55 bool isSent(); waitForSent()56 void waitForSent(); 57 throwLocalException()58 void throwLocalException(); 59 sentSynchronously()60 bool sentSynchronously(); 61 getOperation()62 string getOperation(); 63 whenSent(AsyncCallback cb)64 AsyncResult whenSent(AsyncCallback cb); whenSent(SentCallback cb)65 AsyncResult whenSent(SentCallback cb); whenCompleted(ExceptionCallback excb)66 AsyncResult whenCompleted(ExceptionCallback excb); 67 } 68 69 public interface AsyncResult<T> : AsyncResult 70 { whenCompleted(T cb, ExceptionCallback excb)71 AsyncResult<T> whenCompleted(T cb, ExceptionCallback excb); 72 whenCompleted(ExceptionCallback excb)73 new AsyncResult<T> whenCompleted(ExceptionCallback excb); whenSent(SentCallback cb)74 new AsyncResult<T> whenSent(SentCallback cb); 75 } 76 } 77 78 namespace IceInternal 79 { 80 using System.Diagnostics; 81 using System.Threading; 82 83 abstract public class AsyncResultI : Ice.AsyncResult 84 { cancel()85 public virtual void cancel() 86 { 87 Debug.Assert(outgoing_ != null); 88 outgoing_.cancel(); 89 } 90 getCommunicator()91 public Ice.Communicator getCommunicator() 92 { 93 return _communicator; 94 } 95 getConnection()96 public virtual Ice.Connection getConnection() 97 { 98 return null; 99 } 100 getProxy()101 public virtual Ice.ObjectPrx getProxy() 102 { 103 return null; 104 } 105 isCompleted_()106 public bool isCompleted_() 107 { 108 lock(this) 109 { 110 return (state_ & StateDone) != 0; 111 } 112 } 113 waitForCompleted()114 public void waitForCompleted() 115 { 116 lock(this) 117 { 118 while((state_ & StateDone) == 0) 119 { 120 Monitor.Wait(this); 121 } 122 } 123 } 124 isSent()125 public bool isSent() 126 { 127 lock(this) 128 { 129 return (state_ & StateSent) != 0; 130 } 131 } 132 waitForSent()133 public void waitForSent() 134 { 135 lock(this) 136 { 137 while((state_ & StateSent) == 0 && exception_ == null) 138 { 139 Monitor.Wait(this); 140 } 141 } 142 } 143 throwLocalException()144 public void throwLocalException() 145 { 146 lock(this) 147 { 148 if(exception_ != null) 149 { 150 throw exception_; 151 } 152 } 153 } 154 sentSynchronously()155 public bool sentSynchronously() 156 { 157 Debug.Assert(outgoing_ != null); 158 return outgoing_.sentSynchronously(); // No lock needed 159 } 160 161 // 162 // Implementation of System.IAsyncResult properties 163 // 164 public bool IsCompleted 165 { 166 get 167 { 168 return isCompleted_(); 169 } 170 } 171 172 public bool CompletedSynchronously 173 { 174 get 175 { 176 Debug.Assert(outgoing_ != null); 177 if(getProxy() != null && getProxy().ice_isTwoway()) 178 { 179 return false; 180 } 181 return outgoing_.sentSynchronously(); 182 } 183 } 184 185 public object AsyncState 186 { 187 get 188 { 189 return _cookie; // No lock needed, cookie is immutable. 190 } 191 } 192 193 public WaitHandle AsyncWaitHandle 194 { 195 get 196 { 197 lock(this) 198 { 199 if(waitHandle_ == null) 200 { 201 waitHandle_ = new EventWaitHandle(false, EventResetMode.ManualReset); 202 } 203 if((state_ & StateDone) != 0) 204 { 205 waitHandle_.Set(); 206 } 207 return waitHandle_; 208 } 209 } 210 } 211 212 public OutgoingAsyncBase OutgoingAsync 213 { 214 get 215 { 216 return outgoing_; 217 } 218 } 219 whenSent(Ice.AsyncCallback cb)220 public Ice.AsyncResult whenSent(Ice.AsyncCallback cb) 221 { 222 lock(this) 223 { 224 if(cb == null) 225 { 226 throw new System.ArgumentException("callback is null"); 227 } 228 if(sentCallback_ != null) 229 { 230 throw new System.ArgumentException("sent callback already set"); 231 } 232 sentCallback_ = cb; 233 if((state_ & StateSent) == 0) 234 { 235 return this; 236 } 237 } 238 239 if(outgoing_.sentSynchronously()) 240 { 241 try 242 { 243 sentCallback_(this); 244 } 245 catch(System.Exception ex) 246 { 247 warning(ex); 248 } 249 } 250 else 251 { 252 instance_.clientThreadPool().dispatch(() => 253 { 254 try 255 { 256 sentCallback_(this); 257 } 258 catch(System.Exception ex) 259 { 260 warning(ex); 261 } 262 }, cachedConnection_); 263 } 264 return this; 265 } 266 whenSent(Ice.SentCallback cb)267 public Ice.AsyncResult whenSent(Ice.SentCallback cb) 268 { 269 lock(this) 270 { 271 if(cb == null) 272 { 273 throw new System.ArgumentException("callback is null"); 274 } 275 if(sentCallback_ != null) 276 { 277 throw new System.ArgumentException("sent callback already set"); 278 } 279 sentCallback_ = (Ice.AsyncResult r) => 280 { 281 cb(r.sentSynchronously()); 282 }; 283 if((state_ & StateSent) == 0) 284 { 285 return this; 286 } 287 } 288 289 if(outgoing_.sentSynchronously()) 290 { 291 try 292 { 293 cb(true); 294 } 295 catch(System.Exception ex) 296 { 297 warning(ex); 298 } 299 } 300 else 301 { 302 instance_.clientThreadPool().dispatch(() => 303 { 304 try 305 { 306 cb(false); 307 } 308 catch(System.Exception ex) 309 { 310 warning(ex); 311 } 312 }, cachedConnection_); 313 } 314 return this; 315 } 316 whenCompleted(Ice.ExceptionCallback cb)317 public Ice.AsyncResult whenCompleted(Ice.ExceptionCallback cb) 318 { 319 if(cb == null) 320 { 321 throw new System.ArgumentException("callback is null"); 322 } 323 lock(this) 324 { 325 if(exceptionCallback_ != null) 326 { 327 throw new System.ArgumentException("callback already set"); 328 } 329 exceptionCallback_ = cb; 330 } 331 setCompletedCallback(getCompletedCallback()); 332 return this; 333 } 334 getOperation()335 public string getOperation() 336 { 337 return _operation; 338 } 339 wait()340 public bool wait() 341 { 342 lock(this) 343 { 344 if((state_ & StateEndCalled) != 0) 345 { 346 throw new System.ArgumentException("end_ method called more than once"); 347 } 348 state_ |= StateEndCalled; 349 while((state_ & StateDone) == 0) 350 { 351 Monitor.Wait(this); 352 } 353 if(exception_ != null) 354 { 355 throw exception_; 356 } 357 return (state_ & StateOK) != 0; 358 } 359 } 360 AsyncResultI(Ice.Communicator communicator, Instance instance, string op, object cookie, Ice.AsyncCallback cb)361 protected AsyncResultI(Ice.Communicator communicator, 362 Instance instance, 363 string op, 364 object cookie, 365 Ice.AsyncCallback cb) 366 { 367 instance_ = instance; 368 state_ = 0; 369 370 _communicator = communicator; 371 _operation = op; 372 exception_ = null; 373 _cookie = cookie; 374 completedCallback_ = cb; 375 } 376 setCompletedCallback(Ice.AsyncCallback cb)377 protected void setCompletedCallback(Ice.AsyncCallback cb) 378 { 379 lock(this) 380 { 381 if(cb == null) 382 { 383 throw new System.ArgumentException("callback is null"); 384 } 385 if(completedCallback_ != null) 386 { 387 throw new System.ArgumentException("callback already set"); 388 } 389 completedCallback_ = cb; 390 if((state_ & StateDone) == 0) 391 { 392 return; 393 } 394 else if((getProxy() == null || !getProxy().ice_isTwoway()) && exception_ == null) 395 { 396 return; 397 } 398 } 399 400 instance_.clientThreadPool().dispatch(() => 401 { 402 try 403 { 404 try 405 { 406 cb(this); 407 } 408 catch(System.AggregateException ex) 409 { 410 throw ex.InnerException; 411 } 412 } 413 catch(System.Exception ex) 414 { 415 warning(ex); 416 } 417 }, cachedConnection_); 418 } 419 getCompletedCallback()420 abstract protected Ice.AsyncCallback getCompletedCallback(); 421 check(Ice.AsyncResult r, Ice.ObjectPrx prx, string operation)422 public static AsyncResultI check(Ice.AsyncResult r, Ice.ObjectPrx prx, string operation) 423 { 424 if(r != null && r.getProxy() != prx) 425 { 426 throw new System.ArgumentException("Proxy for call to end_" + operation + 427 " does not match proxy that was used to call corresponding begin_" + 428 operation + " method"); 429 } 430 return check(r, operation); 431 } 432 check(Ice.AsyncResult r, string operation)433 public static AsyncResultI check(Ice.AsyncResult r, string operation) 434 { 435 if(r == null) 436 { 437 throw new System.ArgumentException("AsyncResult == null"); 438 } 439 if(r.getOperation() != operation) 440 { 441 throw new System.ArgumentException("Incorrect operation for end_" + operation + " method: " + 442 r.getOperation()); 443 } 444 if(!(r is AsyncResultI)) 445 { 446 throw new System.ArgumentException("Incorrect AsyncResult object for end_" + operation + " method"); 447 } 448 return (AsyncResultI)r; 449 } 450 warning(System.Exception ex)451 protected void warning(System.Exception ex) 452 { 453 if(instance_.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0) 454 { 455 instance_.initializationData().logger.warning("exception raised by AMI callback:\n" + ex); 456 } 457 } 458 459 protected Instance instance_; 460 protected Ice.Instrumentation.InvocationObserver observer_; 461 protected Ice.Connection cachedConnection_; 462 463 private readonly Ice.Communicator _communicator; 464 private readonly string _operation; 465 private readonly object _cookie; 466 protected Ice.Exception exception_; 467 protected EventWaitHandle waitHandle_; 468 469 protected Ice.AsyncCallback completedCallback_; 470 protected Ice.AsyncCallback sentCallback_; 471 protected Ice.ExceptionCallback exceptionCallback_; 472 473 protected const int StateOK = 0x1; 474 protected const int StateDone = 0x2; 475 protected const int StateSent = 0x4; 476 protected const int StateEndCalled = 0x8; 477 protected int state_; 478 protected OutgoingAsyncBase outgoing_; 479 } 480 } 481