internal object GetResult(ISession session, FutureList futures, bool remove) { Debug.WriteLineIf(CLI.FnTrace.Enabled, "Future.GetResult ()"); bool locked = false; bool check_timeout = false; try { for (;;) { if (!locked) { Monitor.Enter(this); locked = true; } if (results != null && results.Count > 0) { object result = results[0]; if (remove) { results.RemoveAt(0); } return(result); } if (error != null) { if (error is bool && (bool)error) { throw new SystemException("Timeout expired."); } throw new SystemException(error.ToString()); } if (isComplete) { return(null); } if (endOfTime != 0) { if (check_timeout) { long now = DateTime.Now.Ticks; if (endOfTime > now) { timeout = (int)((endOfTime - now) / Values.TicksPerSec); } else { Debug.WriteLineIf(Switch.Enabled, "future timed out: " + requestNo); error = true; Future cancel = new Future(Service.Cancel); cancel.SendRequest(session); throw new SystemException("Timeout expired."); } } else { check_timeout = true; } } if (futures.ReadLock()) { try { bool read = session.PollRead(timeout); if (read) { object[] answer = ReadAnswer(session, false); if (answer != null) { int id = (int)answer[RpcMessageLayout.RRC_COND_NUMBER]; Debug.WriteLineIf(Switch.Enabled, "RRC_COND_NUMBER: " + id); Future future = (Future)futures[id]; if (future != null) { future.HandleAnswer(answer); } } } } finally { futures.ReadUnlock(); } } else { // Unlock so that HandleAnswer for this future // can be called from another thread. Monitor.Exit(this); locked = false; futures.ReadWait(timeout); } } } finally { if (locked) { Monitor.Exit(this); } } }