Example #1
0
        public static IObservable<Tuple<IDisposable<byte[]>, int>> ReadAsync(this Stream stream, int bufferSize, bool waitForObserver, bool refCount, IProducerConsumerCollection<IDisposable<byte[]>> cache)
        {
            var read = Observable.FromAsyncPattern<byte[], int, int, int> (stream.BeginRead, stream.EndRead);

            return Observable.Create<Tuple<IDisposable<byte[]>, int>> (observer => {
                var subscription = new BooleanDisposable ();
                Action<Exception> onError = error => {
                    observer.OnError (error);
                    subscription.Dispose ();
                };

                Action loop = null;
                Action<IDisposable<byte[]>, int> engine;
                if (waitForObserver)
                    engine = (buffer, bytesRead) => {
                        // OnNext is called first
                        observer.OnNext (new Tuple<IDisposable<byte[]>, int> (buffer, bytesRead));
                        // then we begin async read
                        if (!subscription.IsDisposed)
                            loop ();
                    };
                else
                    engine = (buffer, bytesRead) => {
                        // begin async read first
                        if (!subscription.IsDisposed)
                            loop ();
                        //then call OnNext
                        observer.OnNext (new Tuple<IDisposable<byte[]>, int> (buffer, bytesRead));
                    };

                loop = () => {
                    var buffer = cache.TakeOrCreate (refCount, () =>
                        new byte[bufferSize]);
                    read (buffer.Value, 0, bufferSize).Subscribe (bytesRead => {
                        if (0 == bytesRead)
                            observer.OnCompleted ();
                        else
                            engine (buffer, bytesRead);
                    }, onError);
                };

                loop ();

                return subscription;
            });
        }