Пример #1
0
        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);
                }
            }
        }