fa022e96e5d8fc29a94d34b28c2212e6eadd28f1
[mono.git] / mcs / class / referencesource / mscorlib / system / io / stream.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7 **
8 ** Class:  Stream
9 ** 
10 ** <OWNER>gpaperin</OWNER>
11 **
12 **
13 ** Purpose: Abstract base class for all Streams.  Provides
14 ** default implementations of asynchronous reads & writes, in
15 ** terms of the synchronous reads & writes (and vice versa).
16 **
17 **
18 ===========================================================*/
19 using System;
20 using System.Threading;
21 #if FEATURE_ASYNC_IO
22 using System.Threading.Tasks;
23 #endif
24
25 using System.Runtime;
26 using System.Runtime.InteropServices;
27 #if NEW_EXPERIMENTAL_ASYNC_IO
28 using System.Runtime.CompilerServices;
29 #endif
30 using System.Runtime.ExceptionServices;
31 using System.Security;
32 using System.Security.Permissions;
33 using System.Diagnostics.Contracts;
34 using System.Reflection;
35
36 namespace System.IO {
37     [Serializable]
38     [ComVisible(true)]
39 #if CONTRACTS_FULL
40     [ContractClass(typeof(StreamContract))]
41 #endif
42 #if FEATURE_REMOTING || MONO
43     public abstract class Stream : MarshalByRefObject, IDisposable {
44 #else // FEATURE_REMOTING
45     public abstract class Stream : IDisposable {
46 #endif // FEATURE_REMOTING
47
48         public static readonly Stream Null = new NullStream();
49
50         //We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
51         // The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
52         // improvement in Copy performance.
53         private const int _DefaultCopyBufferSize = 81920;
54
55 #if NEW_EXPERIMENTAL_ASYNC_IO
56         // To implement Async IO operations on streams that don't support async IO
57
58         [NonSerialized]
59         private ReadWriteTask _activeReadWriteTask;
60         [NonSerialized]
61         private SemaphoreSlim _asyncActiveSemaphore;
62
63         internal SemaphoreSlim EnsureAsyncActiveSemaphoreInitialized()
64         {
65             // Lazily-initialize _asyncActiveSemaphore.  As we're never accessing the SemaphoreSlim's
66             // WaitHandle, we don't need to worry about Disposing it.
67             return LazyInitializer.EnsureInitialized(ref _asyncActiveSemaphore, () => new SemaphoreSlim(1, 1));
68         }
69 #endif
70
71         public abstract bool CanRead {
72             [Pure]
73             get;
74         }
75
76         // If CanSeek is false, Position, Seek, Length, and SetLength should throw.
77         public abstract bool CanSeek {
78             [Pure]
79             get;
80         }
81
82         [ComVisible(false)]
83         public virtual bool CanTimeout {
84             [Pure]
85             get {
86                 return false;
87             }
88         }
89         
90         public abstract bool CanWrite {
91             [Pure]
92             get;
93         }
94
95         public abstract long Length {
96             get;
97         }
98
99         public abstract long Position {
100             get;
101             set;
102         }
103
104         [ComVisible(false)]
105         public virtual int ReadTimeout {
106             get {
107                 Contract.Ensures(Contract.Result<int>() >= 0);
108                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TimeoutsNotSupported"));
109             }
110             set {
111                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TimeoutsNotSupported"));
112             }
113         }
114
115         [ComVisible(false)]
116         public virtual int WriteTimeout {
117             get {
118                 Contract.Ensures(Contract.Result<int>() >= 0);
119                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TimeoutsNotSupported"));
120             }
121             set {
122                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TimeoutsNotSupported"));
123             }
124         }
125
126 #if FEATURE_ASYNC_IO
127         [HostProtection(ExternalThreading = true)]
128         [ComVisible(false)]
129         public Task CopyToAsync(Stream destination)
130         {
131             return CopyToAsync(destination, _DefaultCopyBufferSize);
132         }
133
134         [HostProtection(ExternalThreading = true)]
135         [ComVisible(false)]
136         public Task CopyToAsync(Stream destination, Int32 bufferSize)
137         {
138             return CopyToAsync(destination, bufferSize, CancellationToken.None);
139         }
140
141         [HostProtection(ExternalThreading = true)]
142         [ComVisible(false)]
143         public virtual Task CopyToAsync(Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
144         {
145             if (destination == null)
146                 throw new ArgumentNullException("destination");
147             if (bufferSize <= 0)
148                 throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
149             if (!CanRead && !CanWrite)
150                 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
151             if (!destination.CanRead && !destination.CanWrite)
152                 throw new ObjectDisposedException("destination", Environment.GetResourceString("ObjectDisposed_StreamClosed"));
153             if (!CanRead)
154                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
155             if (!destination.CanWrite)
156                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
157             Contract.EndContractBlock();
158
159             return CopyToAsyncInternal(destination, bufferSize, cancellationToken);
160         }
161
162         private async Task CopyToAsyncInternal(Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
163         {
164             Contract.Requires(destination != null);
165             Contract.Requires(bufferSize > 0);
166             Contract.Requires(CanRead);
167             Contract.Requires(destination.CanWrite);
168
169             byte[] buffer = new byte[bufferSize];
170             int bytesRead;
171             while ((bytesRead = await ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
172             {
173                 await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
174             }
175         }
176 #endif // FEATURE_ASYNC_IO
177
178         // Reads the bytes from the current stream and writes the bytes to
179         // the destination stream until all bytes are read, starting at
180         // the current position.
181         public void CopyTo(Stream destination)
182         {
183             if (destination == null)
184                 throw new ArgumentNullException("destination");
185             if (!CanRead && !CanWrite)
186                 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
187             if (!destination.CanRead && !destination.CanWrite)
188                 throw new ObjectDisposedException("destination", Environment.GetResourceString("ObjectDisposed_StreamClosed"));
189             if (!CanRead)
190                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
191             if (!destination.CanWrite)
192                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
193             Contract.EndContractBlock();
194
195             InternalCopyTo(destination, _DefaultCopyBufferSize);
196         }
197
198         public void CopyTo(Stream destination, int bufferSize)
199         {
200             if (destination == null)
201                 throw new ArgumentNullException("destination");
202             if (bufferSize <= 0)
203                 throw new ArgumentOutOfRangeException("bufferSize",
204                         Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
205             if (!CanRead && !CanWrite)
206                 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
207             if (!destination.CanRead && !destination.CanWrite)
208                 throw new ObjectDisposedException("destination", Environment.GetResourceString("ObjectDisposed_StreamClosed"));
209             if (!CanRead)
210                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
211             if (!destination.CanWrite)
212                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
213             Contract.EndContractBlock();
214
215             InternalCopyTo(destination, bufferSize);
216         }
217
218         private void InternalCopyTo(Stream destination, int bufferSize)
219         {
220             Contract.Requires(destination != null);
221             Contract.Requires(CanRead);
222             Contract.Requires(destination.CanWrite);
223             Contract.Requires(bufferSize > 0);
224             
225             byte[] buffer = new byte[bufferSize];
226             int read;
227             while ((read = Read(buffer, 0, buffer.Length)) != 0)
228                 destination.Write(buffer, 0, read);
229         }
230
231
232         // Stream used to require that all cleanup logic went into Close(),
233         // which was thought up before we invented IDisposable.  However, we
234         // need to follow the IDisposable pattern so that users can write 
235         // sensible subclasses without needing to inspect all their base 
236         // classes, and without worrying about version brittleness, from a
237         // base class switching to the Dispose pattern.  We're moving
238         // Stream to the Dispose(bool) pattern - that's where all subclasses 
239         // should put their cleanup starting in V2.
240         public virtual void Close()
241         {
242             /* These are correct, but we'd have to fix PipeStream & NetworkStream very carefully.
243             Contract.Ensures(CanRead == false);
244             Contract.Ensures(CanWrite == false);
245             Contract.Ensures(CanSeek == false);
246             */
247
248             Dispose(true);
249             GC.SuppressFinalize(this);
250         }
251
252         public void Dispose()
253         {
254             /* These are correct, but we'd have to fix PipeStream & NetworkStream very carefully.
255             Contract.Ensures(CanRead == false);
256             Contract.Ensures(CanWrite == false);
257             Contract.Ensures(CanSeek == false);
258             */
259
260             Close();
261         }
262
263
264         protected virtual void Dispose(bool disposing)
265         {
266             // Note: Never change this to call other virtual methods on Stream
267             // like Write, since the state on subclasses has already been 
268             // torn down.  This is the last code to run on cleanup for a stream.
269         }
270
271         public abstract void Flush();
272
273 #if FEATURE_ASYNC_IO
274         [HostProtection(ExternalThreading=true)]
275         [ComVisible(false)]
276         public Task FlushAsync()
277         {
278             return FlushAsync(CancellationToken.None);
279         }
280
281         [HostProtection(ExternalThreading=true)]
282         [ComVisible(false)]
283         public virtual Task FlushAsync(CancellationToken cancellationToken)
284         {
285             return Task.Factory.StartNew(state => ((Stream)state).Flush(), this,
286                 cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
287         }
288 #endif // FEATURE_ASYNC_IO
289
290         [Obsolete("CreateWaitHandle will be removed eventually.  Please use \"new ManualResetEvent(false)\" instead.")]
291         protected virtual WaitHandle CreateWaitHandle()
292         {
293             Contract.Ensures(Contract.Result<WaitHandle>() != null);
294             return new ManualResetEvent(false);
295         }
296
297         [HostProtection(ExternalThreading=true)]
298         public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
299         {
300             Contract.Ensures(Contract.Result<IAsyncResult>() != null);
301             return BeginReadInternal(buffer, offset, count, callback, state, serializeAsynchronously: false);
302         }
303
304         [HostProtection(ExternalThreading = true)]
305         internal IAsyncResult BeginReadInternal(byte[] buffer, int offset, int count, AsyncCallback callback, Object state, bool serializeAsynchronously)
306         {
307             Contract.Ensures(Contract.Result<IAsyncResult>() != null);
308             if (!CanRead) __Error.ReadNotSupported();
309
310 #if !NEW_EXPERIMENTAL_ASYNC_IO
311             return BlockingBeginRead(buffer, offset, count, callback, state);
312 #else
313
314             // Mango did not do Async IO.
315             if(CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
316             {
317                 return BlockingBeginRead(buffer, offset, count, callback, state);
318             }
319
320             // To avoid a race with a stream's position pointer & generating ---- 
321             // conditions with internal buffer indexes in our own streams that 
322             // don't natively support async IO operations when there are multiple 
323             // async requests outstanding, we will block the application's main
324             // thread if it does a second IO request until the first one completes.
325             var semaphore = EnsureAsyncActiveSemaphoreInitialized();
326             Task semaphoreTask = null;
327             if (serializeAsynchronously)
328             {
329                 semaphoreTask = semaphore.WaitAsync();
330             }
331             else
332             {
333                 semaphore.Wait();
334             }
335
336             // Create the task to asynchronously do a Read.  This task serves both
337             // as the asynchronous work item and as the IAsyncResult returned to the user.
338             var asyncResult = new ReadWriteTask(true /*isRead*/, delegate
339             {
340                 // The ReadWriteTask stores all of the parameters to pass to Read.
341                 // As we're currently inside of it, we can get the current task
342                 // and grab the parameters from it.
343                 var thisTask = Task.InternalCurrent as ReadWriteTask;
344                 Contract.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask");
345
346                 // Do the Read and return the number of bytes read
347                 var bytesRead = thisTask._stream.Read(thisTask._buffer, thisTask._offset, thisTask._count);
348                 thisTask.ClearBeginState(); // just to help alleviate some memory pressure
349                 return bytesRead;
350             }, state, this, buffer, offset, count, callback);
351
352             // Schedule it
353             if (semaphoreTask != null)
354                 RunReadWriteTaskWhenReady(semaphoreTask, asyncResult);
355             else
356                 RunReadWriteTask(asyncResult);
357
358             
359             return asyncResult; // return it
360 #endif
361         }
362
363         public virtual int EndRead(IAsyncResult asyncResult)
364         {
365             if (asyncResult == null)
366                 throw new ArgumentNullException("asyncResult");
367             Contract.Ensures(Contract.Result<int>() >= 0);
368             Contract.EndContractBlock();
369
370 #if !NEW_EXPERIMENTAL_ASYNC_IO
371             return BlockingEndRead(asyncResult);
372 #else
373             // Mango did not do async IO.
374             if(CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
375             {
376                 return BlockingEndRead(asyncResult);
377             }
378
379             var readTask = _activeReadWriteTask;
380
381             if (readTask == null)
382             {
383                 throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple"));
384             }
385             else if (readTask != asyncResult)
386             {
387                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple"));
388             }
389             else if (!readTask._isRead)
390             {
391                 throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple"));
392             }
393             
394             try 
395             {
396                 return readTask.GetAwaiter().GetResult(); // block until completion, then get result / propagate any exception
397             }
398             finally
399             {
400                 _activeReadWriteTask = null;
401                 Contract.Assert(_asyncActiveSemaphore != null, "Must have been initialized in order to get here.");
402                 _asyncActiveSemaphore.Release();
403             }
404 #endif
405         }
406
407 #if FEATURE_ASYNC_IO
408         [HostProtection(ExternalThreading = true)]
409         [ComVisible(false)]
410         public Task<int> ReadAsync(Byte[] buffer, int offset, int count)
411         {
412             return ReadAsync(buffer, offset, count, CancellationToken.None);
413         }
414
415         [HostProtection(ExternalThreading = true)]
416         [ComVisible(false)]
417         public virtual Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
418         {
419             // If cancellation was requested, bail early with an already completed task.
420             // Otherwise, return a task that represents the Begin/End methods.
421             return cancellationToken.IsCancellationRequested
422                         ? Task.FromCancellation<int>(cancellationToken)
423                         : BeginEndReadAsync(buffer, offset, count);
424         }
425
426         private Task<Int32> BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
427         {            
428             return TaskFactory<Int32>.FromAsyncTrim(
429                         this, new ReadWriteParameters { Buffer = buffer, Offset = offset, Count = count },
430                         (stream, args, callback, state) => stream.BeginRead(args.Buffer, args.Offset, args.Count, callback, state), // cached by compiler
431                         (stream, asyncResult) => stream.EndRead(asyncResult)); // cached by compiler
432         }
433
434         private struct ReadWriteParameters // struct for arguments to Read and Write calls
435         {
436             internal byte[] Buffer;
437             internal int Offset;
438             internal int Count;
439         }
440 #endif //FEATURE_ASYNC_IO
441
442
443
444         [HostProtection(ExternalThreading=true)]
445         public virtual IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
446         {
447             Contract.Ensures(Contract.Result<IAsyncResult>() != null);
448             return BeginWriteInternal(buffer, offset, count, callback, state, serializeAsynchronously: false);
449         }
450
451         [HostProtection(ExternalThreading = true)]
452         internal IAsyncResult BeginWriteInternal(byte[] buffer, int offset, int count, AsyncCallback callback, Object state, bool serializeAsynchronously)
453         {
454             Contract.Ensures(Contract.Result<IAsyncResult>() != null);
455             if (!CanWrite) __Error.WriteNotSupported();
456 #if !NEW_EXPERIMENTAL_ASYNC_IO
457             return BlockingBeginWrite(buffer, offset, count, callback, state);
458 #else
459
460             // Mango did not do Async IO.
461             if(CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
462             {
463                 return BlockingBeginWrite(buffer, offset, count, callback, state);
464             }
465
466             // To avoid a race with a stream's position pointer & generating ---- 
467             // conditions with internal buffer indexes in our own streams that 
468             // don't natively support async IO operations when there are multiple 
469             // async requests outstanding, we will block the application's main
470             // thread if it does a second IO request until the first one completes.
471             var semaphore = EnsureAsyncActiveSemaphoreInitialized();
472             Task semaphoreTask = null;
473             if (serializeAsynchronously)
474             {
475                 semaphoreTask = semaphore.WaitAsync(); // kick off the asynchronous wait, but don't block
476             }
477             else
478             {
479                 semaphore.Wait(); // synchronously wait here
480             }
481
482             // Create the task to asynchronously do a Write.  This task serves both
483             // as the asynchronous work item and as the IAsyncResult returned to the user.
484             var asyncResult = new ReadWriteTask(false /*isRead*/, delegate
485             {
486                 // The ReadWriteTask stores all of the parameters to pass to Write.
487                 // As we're currently inside of it, we can get the current task
488                 // and grab the parameters from it.
489                 var thisTask = Task.InternalCurrent as ReadWriteTask;
490                 Contract.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask");
491
492                 // Do the Write
493                 thisTask._stream.Write(thisTask._buffer, thisTask._offset, thisTask._count);  
494                 thisTask.ClearBeginState(); // just to help alleviate some memory pressure
495                 return 0; // not used, but signature requires a value be returned
496             }, state, this, buffer, offset, count, callback);
497
498             // Schedule it
499             if (semaphoreTask != null)
500                 RunReadWriteTaskWhenReady(semaphoreTask, asyncResult);
501             else
502                 RunReadWriteTask(asyncResult);
503
504             return asyncResult; // return it
505 #endif
506         }
507
508 #if NEW_EXPERIMENTAL_ASYNC_IO
509         private void RunReadWriteTaskWhenReady(Task asyncWaiter, ReadWriteTask readWriteTask)
510         {
511             Contract.Assert(readWriteTask != null);  // Should be Contract.Requires, but CCRewrite is doing a poor job with
512                                                      // preconditions in async methods that await.  Mike & Manuel are aware. (10/6/2011, bug 290222)
513             Contract.Assert(asyncWaiter != null);    // Ditto
514
515             // If the wait has already complete, run the task.
516             if (asyncWaiter.IsCompleted)
517             {
518                 Contract.Assert(asyncWaiter.IsRanToCompletion, "The semaphore wait should always complete successfully.");
519                 RunReadWriteTask(readWriteTask);
520             }                
521             else  // Otherwise, wait for our turn, and then run the task.
522             {
523                 asyncWaiter.ContinueWith((t, state) =>
524                     {
525                         Contract.Assert(t.IsRanToCompletion, "The semaphore wait should always complete successfully.");
526                         var tuple = (Tuple<Stream,ReadWriteTask>)state;
527                         tuple.Item1.RunReadWriteTask(tuple.Item2); // RunReadWriteTask(readWriteTask);
528                     }, Tuple.Create<Stream,ReadWriteTask>(this, readWriteTask),
529                 default(CancellationToken),
530                 TaskContinuationOptions.ExecuteSynchronously, 
531                 TaskScheduler.Default);
532             }
533         }
534
535         private void RunReadWriteTask(ReadWriteTask readWriteTask)
536         {
537             Contract.Requires(readWriteTask != null);
538             Contract.Assert(_activeReadWriteTask == null, "Expected no other readers or writers");
539
540             // Schedule the task.  ScheduleAndStart must happen after the write to _activeReadWriteTask to avoid a race.
541             // Internally, we're able to directly call ScheduleAndStart rather than Start, avoiding
542             // two interlocked operations.  However, if ReadWriteTask is ever changed to use
543             // a cancellation token, this should be changed to use Start.
544             _activeReadWriteTask = readWriteTask; // store the task so that EndXx can validate it's given the right one
545             readWriteTask.m_taskScheduler = TaskScheduler.Default;
546             readWriteTask.ScheduleAndStart(needsProtection: false);
547         }
548 #endif
549
550         public virtual void EndWrite(IAsyncResult asyncResult)
551         {
552             if (asyncResult==null)
553                 throw new ArgumentNullException("asyncResult");
554             Contract.EndContractBlock();
555
556 #if !NEW_EXPERIMENTAL_ASYNC_IO
557             BlockingEndWrite(asyncResult);
558 #else            
559
560             // Mango did not do Async IO.
561             if(CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
562             {
563                 BlockingEndWrite(asyncResult);
564                 return;
565             }            
566
567             var writeTask = _activeReadWriteTask;
568             if (writeTask == null)
569             {
570                 throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple"));
571             }
572             else if (writeTask != asyncResult)
573             {
574                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple"));
575             }
576             else if (writeTask._isRead)
577             {
578                 throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple"));
579             }
580
581             try 
582             {
583                 writeTask.GetAwaiter().GetResult(); // block until completion, then propagate any exceptions
584                 Contract.Assert(writeTask.Status == TaskStatus.RanToCompletion);
585             }
586             finally
587             {
588                 _activeReadWriteTask = null;
589                 Contract.Assert(_asyncActiveSemaphore != null, "Must have been initialized in order to get here.");
590                 _asyncActiveSemaphore.Release();
591             }
592 #endif
593         }
594
595 #if NEW_EXPERIMENTAL_ASYNC_IO
596         // Task used by BeginRead / BeginWrite to do Read / Write asynchronously.
597         // A single instance of this task serves four purposes:
598         // 1. The work item scheduled to run the Read / Write operation
599         // 2. The state holding the arguments to be passed to Read / Write
600         // 3. The IAsyncResult returned from BeginRead / BeginWrite
601         // 4. The completion action that runs to invoke the user-provided callback.
602         // This last item is a bit tricky.  Before the AsyncCallback is invoked, the
603         // IAsyncResult must have completed, so we can't just invoke the handler
604         // from within the task, since it is the IAsyncResult, and thus it's not
605         // yet completed.  Instead, we use AddCompletionAction to install this
606         // task as its own completion handler.  That saves the need to allocate
607         // a separate completion handler, it guarantees that the task will
608         // have completed by the time the handler is invoked, and it allows
609         // the handler to be invoked synchronously upon the completion of the
610         // task.  This all enables BeginRead / BeginWrite to be implemented
611         // with a single allocation.
612         private sealed class ReadWriteTask : Task<int>, ITaskCompletionAction
613         {
614             internal readonly bool _isRead;
615             internal Stream _stream;
616             internal byte [] _buffer;
617             internal int _offset;
618             internal int _count;
619             private AsyncCallback _callback;
620             private ExecutionContext _context;
621
622             internal void ClearBeginState() // Used to allow the args to Read/Write to be made available for GC
623             {
624                 _stream = null;
625                 _buffer = null;
626             }
627
628             [SecuritySafeCritical] // necessary for EC.Capture
629             [MethodImpl(MethodImplOptions.NoInlining)]
630             public ReadWriteTask(
631                 bool isRead,
632                 Func<object,int> function, object state,
633                 Stream stream, byte[] buffer, int offset, int count, AsyncCallback callback) :
634                 base(function, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach)
635             {
636                 Contract.Requires(function != null);
637                 Contract.Requires(stream != null);
638                 Contract.Requires(buffer != null);
639                 Contract.EndContractBlock();
640
641                 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
642
643                 // Store the arguments
644                 _isRead = isRead;
645                 _stream = stream;
646                 _buffer = buffer;
647                 _offset = offset;
648                 _count = count;
649
650                 // If a callback was provided, we need to:
651                 // - Store the user-provided handler
652                 // - Capture an ExecutionContext under which to invoke the handler
653                 // - Add this task as its own completion handler so that the Invoke method
654                 //   will run the callback when this task completes.
655                 if (callback != null)
656                 {
657                     _callback = callback;
658                     _context = ExecutionContext.Capture(ref stackMark, 
659                         ExecutionContext.CaptureOptions.OptimizeDefaultCase | ExecutionContext.CaptureOptions.IgnoreSyncCtx);
660                     base.AddCompletionAction(this);
661                 }
662             }
663
664             [SecurityCritical] // necessary for CoreCLR
665             private static void InvokeAsyncCallback(object completedTask)
666             {
667                 var rwc = (ReadWriteTask)completedTask;
668                 var callback = rwc._callback;
669                 rwc._callback = null;
670                 callback(rwc);
671             }
672
673             [SecurityCritical] // necessary for CoreCLR
674             private static ContextCallback s_invokeAsyncCallback;
675             
676             [SecuritySafeCritical] // necessary for ExecutionContext.Run
677             void ITaskCompletionAction.Invoke(Task completingTask)
678             {
679                 // Get the ExecutionContext.  If there is none, just run the callback
680                 // directly, passing in the completed task as the IAsyncResult.
681                 // If there is one, process it with ExecutionContext.Run.
682                 var context = _context;
683                 if (context == null) 
684                 {
685                     var callback = _callback;
686                     _callback = null;
687                     callback(completingTask);
688                 }
689                 else 
690                 {
691                     _context = null;
692         
693                     var invokeAsyncCallback = s_invokeAsyncCallback;
694                     if (invokeAsyncCallback == null) s_invokeAsyncCallback = invokeAsyncCallback = InvokeAsyncCallback; // benign ----
695
696                     using(context) ExecutionContext.Run(context, invokeAsyncCallback, this, true);
697                 }
698             }
699         }
700 #endif
701
702 #if FEATURE_ASYNC_IO
703         [HostProtection(ExternalThreading = true)]
704         [ComVisible(false)]
705         public Task WriteAsync(Byte[] buffer, int offset, int count)
706         {
707             return WriteAsync(buffer, offset, count, CancellationToken.None);
708         }
709
710         [HostProtection(ExternalThreading = true)]
711         [ComVisible(false)]
712         public virtual Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
713         {
714             // If cancellation was requested, bail early with an already completed task.
715             // Otherwise, return a task that represents the Begin/End methods.
716             return cancellationToken.IsCancellationRequested
717                         ? Task.FromCancellation(cancellationToken)
718                         : BeginEndWriteAsync(buffer, offset, count);
719         }
720
721
722         private Task BeginEndWriteAsync(Byte[] buffer, Int32 offset, Int32 count)
723         {            
724             return TaskFactory<VoidTaskResult>.FromAsyncTrim(
725                         this, new ReadWriteParameters { Buffer=buffer, Offset=offset, Count=count },
726                         (stream, args, callback, state) => stream.BeginWrite(args.Buffer, args.Offset, args.Count, callback, state), // cached by compiler
727                         (stream, asyncResult) => // cached by compiler
728                         {
729                             stream.EndWrite(asyncResult);
730                             return default(VoidTaskResult);
731                         });
732         }        
733 #endif // FEATURE_ASYNC_IO
734
735         public abstract long Seek(long offset, SeekOrigin origin);
736
737         public abstract void SetLength(long value);
738
739         public abstract int Read([In, Out] byte[] buffer, int offset, int count);
740
741         // Reads one byte from the stream by calling Read(byte[], int, int). 
742         // Will return an unsigned byte cast to an int or -1 on end of stream.
743         // This implementation does not perform well because it allocates a new
744         // byte[] each time you call it, and should be overridden by any 
745         // subclass that maintains an internal buffer.  Then, it can help perf
746         // significantly for people who are reading one byte at a time.
747         public virtual int ReadByte()
748         {
749             Contract.Ensures(Contract.Result<int>() >= -1);
750             Contract.Ensures(Contract.Result<int>() < 256);
751
752             byte[] oneByteArray = new byte[1];
753             int r = Read(oneByteArray, 0, 1);
754             if (r==0)
755                 return -1;
756             return oneByteArray[0];
757         }
758
759         public abstract void Write(byte[] buffer, int offset, int count);
760
761         // Writes one byte from the stream by calling Write(byte[], int, int).
762         // This implementation does not perform well because it allocates a new
763         // byte[] each time you call it, and should be overridden by any 
764         // subclass that maintains an internal buffer.  Then, it can help perf
765         // significantly for people who are writing one byte at a time.
766         public virtual void WriteByte(byte value)
767         {
768             byte[] oneByteArray = new byte[1];
769             oneByteArray[0] = value;
770             Write(oneByteArray, 0, 1);
771         }
772
773         [HostProtection(Synchronization=true)]
774         public static Stream Synchronized(Stream stream) 
775         {
776             if (stream==null)
777                 throw new ArgumentNullException("stream");
778             Contract.Ensures(Contract.Result<Stream>() != null);
779             Contract.EndContractBlock();
780             if (stream is SyncStream)
781                 return stream;
782             
783             return new SyncStream(stream);
784         }
785
786 #if !FEATURE_PAL || MONO // This method shouldn't have been exposed in Dev10 (we revised object invariants after locking down).
787         [Obsolete("Do not call or override this method.")]
788         protected virtual void ObjectInvariant() 
789         {
790         }
791 #endif
792
793         internal IAsyncResult BlockingBeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
794         {
795             Contract.Ensures(Contract.Result<IAsyncResult>() != null);
796
797             // To avoid a race with a stream's position pointer & generating ---- 
798             // conditions with internal buffer indexes in our own streams that 
799             // don't natively support async IO operations when there are multiple 
800             // async requests outstanding, we will block the application's main
801             // thread and do the IO synchronously.  
802             // This can't perform well - use a different approach.
803             SynchronousAsyncResult asyncResult; 
804             try {
805                 int numRead = Read(buffer, offset, count);
806                 asyncResult = new SynchronousAsyncResult(numRead, state);
807             }
808             catch (IOException ex) {
809                 asyncResult = new SynchronousAsyncResult(ex, state, isWrite: false);
810             }
811             
812             if (callback != null) {
813                 callback(asyncResult);
814             }
815
816             return asyncResult;
817         }
818
819         internal static int BlockingEndRead(IAsyncResult asyncResult)
820         {
821             Contract.Ensures(Contract.Result<int>() >= 0);
822
823             return SynchronousAsyncResult.EndRead(asyncResult);
824         }
825
826         internal IAsyncResult BlockingBeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
827         {
828             Contract.Ensures(Contract.Result<IAsyncResult>() != null);
829
830             // To avoid a race with a stream's position pointer & generating ---- 
831             // conditions with internal buffer indexes in our own streams that 
832             // don't natively support async IO operations when there are multiple 
833             // async requests outstanding, we will block the application's main
834             // thread and do the IO synchronously.  
835             // This can't perform well - use a different approach.
836             SynchronousAsyncResult asyncResult;
837             try {
838                 Write(buffer, offset, count);
839                 asyncResult = new SynchronousAsyncResult(state);
840             }
841             catch (IOException ex) {
842                 asyncResult = new SynchronousAsyncResult(ex, state, isWrite: true);
843             }
844
845             if (callback != null) {
846                 callback(asyncResult);
847             }
848
849             return asyncResult;
850         }
851
852         internal static void BlockingEndWrite(IAsyncResult asyncResult)
853         {
854             SynchronousAsyncResult.EndWrite(asyncResult);
855         }
856
857         [Serializable]
858         private sealed class NullStream : Stream
859         {
860             internal NullStream() {}
861
862             public override bool CanRead {
863                 [Pure]
864                 get { return true; }
865             }
866
867             public override bool CanWrite {
868                 [Pure]
869                 get { return true; }
870             }
871
872             public override bool CanSeek {
873                 [Pure]
874                 get { return true; }
875             }
876
877             public override long Length {
878                 get { return 0; }
879             }
880
881             public override long Position {
882                 get { return 0; }
883                 set {}
884             }
885
886             protected override void Dispose(bool disposing)
887             {
888                 // Do nothing - we don't want NullStream singleton (static) to be closable
889             }
890
891             public override void Flush()
892             {
893             }
894
895 #if FEATURE_ASYNC_IO
896             [ComVisible(false)]
897             public override Task FlushAsync(CancellationToken cancellationToken)
898             {
899                 return cancellationToken.IsCancellationRequested ?
900                     Task.FromCancellation(cancellationToken) :
901                     Task.CompletedTask;
902             }
903 #endif // FEATURE_ASYNC_IO
904
905             [HostProtection(ExternalThreading = true)]
906             public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
907             {
908                 if (!CanRead) __Error.ReadNotSupported();
909
910                 return BlockingBeginRead(buffer, offset, count, callback, state);
911             }
912
913             public override int EndRead(IAsyncResult asyncResult)
914             {
915                 if (asyncResult == null)
916                     throw new ArgumentNullException("asyncResult");
917                 Contract.EndContractBlock();
918
919                 return BlockingEndRead(asyncResult);
920             }
921
922             [HostProtection(ExternalThreading = true)]
923             public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
924             {
925                 if (!CanWrite) __Error.WriteNotSupported();
926
927                 return BlockingBeginWrite(buffer, offset, count, callback, state);
928             }
929
930             public override void EndWrite(IAsyncResult asyncResult)
931             {
932                 if (asyncResult == null)
933                     throw new ArgumentNullException("asyncResult");
934                 Contract.EndContractBlock();
935
936                 BlockingEndWrite(asyncResult);
937             }
938
939             public override int Read([In, Out] byte[] buffer, int offset, int count)
940             {
941                 return 0;
942             }
943
944 #if FEATURE_ASYNC_IO
945             [ComVisible(false)]
946             public override Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
947             {
948                 var nullReadTask = s_nullReadTask;
949                 if (nullReadTask == null) 
950                     s_nullReadTask = nullReadTask = new Task<int>(false, 0, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, CancellationToken.None); // benign ----
951                 return nullReadTask;
952             }
953             private static Task<int> s_nullReadTask;
954 #endif //FEATURE_ASYNC_IO
955
956             public override int ReadByte()
957             {
958                 return -1;
959             }
960
961             public override void Write(byte[] buffer, int offset, int count)
962             {
963             }
964
965 #if FEATURE_ASYNC_IO
966             [ComVisible(false)]
967             public override Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
968             {
969                 return cancellationToken.IsCancellationRequested ?
970                     Task.FromCancellation(cancellationToken) :
971                     Task.CompletedTask;
972             }
973 #endif // FEATURE_ASYNC_IO
974
975             public override void WriteByte(byte value)
976             {
977             }
978
979             public override long Seek(long offset, SeekOrigin origin)
980             {
981                 return 0;
982             }
983
984             public override void SetLength(long length)
985             {
986             }
987         }
988
989         
990         /// <summary>Used as the IAsyncResult object when using asynchronous IO methods on the base Stream class.</summary>
991         internal sealed class SynchronousAsyncResult : IAsyncResult {
992             
993             private readonly Object _stateObject;            
994             private readonly bool _isWrite;
995             private ManualResetEvent _waitHandle;
996             private ExceptionDispatchInfo _exceptionInfo;
997
998             private bool _endXxxCalled;
999             private Int32 _bytesRead;
1000
1001             internal SynchronousAsyncResult(Int32 bytesRead, Object asyncStateObject) {
1002                 _bytesRead = bytesRead;
1003                 _stateObject = asyncStateObject;
1004                 //_isWrite = false;
1005             }
1006
1007             internal SynchronousAsyncResult(Object asyncStateObject) {
1008                 _stateObject = asyncStateObject;
1009                 _isWrite = true;
1010             }
1011
1012             internal SynchronousAsyncResult(Exception ex, Object asyncStateObject, bool isWrite) {
1013                 _exceptionInfo = ExceptionDispatchInfo.Capture(ex);
1014                 _stateObject = asyncStateObject;
1015                 _isWrite = isWrite;                
1016             }
1017
1018             public bool IsCompleted {
1019                 // We never hand out objects of this type to the user before the synchronous IO completed:
1020                 get { return true; }
1021             }
1022
1023             public WaitHandle AsyncWaitHandle {
1024                 get {
1025                     return LazyInitializer.EnsureInitialized(ref _waitHandle, () => new ManualResetEvent(true));                    
1026                 }
1027             }
1028
1029             public Object AsyncState {
1030                 get { return _stateObject; }
1031             }
1032
1033             public bool CompletedSynchronously {
1034                 get { return true; }
1035             }
1036
1037             internal void ThrowIfError() {
1038                 if (_exceptionInfo != null)
1039                     _exceptionInfo.Throw();
1040             }                        
1041
1042             internal static Int32 EndRead(IAsyncResult asyncResult) {
1043
1044                 SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult;
1045                 if (ar == null || ar._isWrite)
1046                     __Error.WrongAsyncResult();
1047
1048                 if (ar._endXxxCalled)
1049                     __Error.EndReadCalledTwice();
1050
1051                 ar._endXxxCalled = true;
1052
1053                 ar.ThrowIfError();
1054                 return ar._bytesRead;
1055             }
1056
1057             internal static void EndWrite(IAsyncResult asyncResult) {
1058
1059                 SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult;
1060                 if (ar == null || !ar._isWrite)
1061                     __Error.WrongAsyncResult();
1062
1063                 if (ar._endXxxCalled)
1064                     __Error.EndWriteCalledTwice();
1065
1066                 ar._endXxxCalled = true;
1067
1068                 ar.ThrowIfError();
1069             }
1070         }   // class SynchronousAsyncResult
1071
1072
1073         // SyncStream is a wrapper around a stream that takes 
1074         // a lock for every operation making it thread safe.
1075         [Serializable]
1076         internal sealed class SyncStream : Stream, IDisposable
1077         {
1078             private Stream _stream;
1079             [NonSerialized]
1080             private bool? _overridesBeginRead;
1081             [NonSerialized]
1082             private bool? _overridesBeginWrite;
1083
1084             internal SyncStream(Stream stream)
1085             {
1086                 if (stream == null)
1087                     throw new ArgumentNullException("stream");
1088                 Contract.EndContractBlock();
1089                 _stream = stream;
1090             }
1091         
1092             public override bool CanRead {
1093                 [Pure]
1094                 get { return _stream.CanRead; }
1095             }
1096         
1097             public override bool CanWrite {
1098                 [Pure]
1099                 get { return _stream.CanWrite; }
1100             }
1101         
1102             public override bool CanSeek {
1103                 [Pure]
1104                 get { return _stream.CanSeek; }
1105             }
1106         
1107             [ComVisible(false)]
1108             public override bool CanTimeout {
1109                 [Pure]
1110                 get {
1111                     return _stream.CanTimeout;
1112                 }
1113             }
1114
1115             public override long Length {
1116                 get {
1117                     lock(_stream) {
1118                         return _stream.Length;
1119                     }
1120                 }
1121             }
1122         
1123             public override long Position {
1124                 get {
1125                     lock(_stream) {
1126                         return _stream.Position;
1127                     }
1128                 }
1129                 set {
1130                     lock(_stream) {
1131                         _stream.Position = value;
1132                     }
1133                 }
1134             }
1135
1136             [ComVisible(false)]
1137             public override int ReadTimeout {
1138                 get {
1139                     return _stream.ReadTimeout;
1140                 }
1141                 set {
1142                     _stream.ReadTimeout = value;
1143                 }
1144             }
1145
1146             [ComVisible(false)]
1147             public override int WriteTimeout {
1148                 get {
1149                     return _stream.WriteTimeout;
1150                 }
1151                 set {
1152                     _stream.WriteTimeout = value;
1153                 }
1154             }
1155
1156             // In the off chance that some wrapped stream has different 
1157             // semantics for Close vs. Dispose, let's preserve that.
1158             public override void Close()
1159             {
1160                 lock(_stream) {
1161                     try {
1162                         _stream.Close();
1163                     }
1164                     finally {
1165                         base.Dispose(true);
1166                     }
1167                 }
1168             }
1169         
1170             protected override void Dispose(bool disposing)
1171             {
1172                 lock(_stream) {
1173                     try {
1174                         // Explicitly pick up a potentially methodimpl'ed Dispose
1175                         if (disposing)
1176                             ((IDisposable)_stream).Dispose();
1177                     }
1178                     finally {
1179                         base.Dispose(disposing);
1180                     }
1181                 }
1182             }
1183         
1184             public override void Flush()
1185             {
1186                 lock(_stream)
1187                     _stream.Flush();
1188             }
1189         
1190             public override int Read([In, Out]byte[] bytes, int offset, int count)
1191             {
1192                 lock(_stream)
1193                     return _stream.Read(bytes, offset, count);
1194             }
1195         
1196             public override int ReadByte()
1197             {
1198                 lock(_stream)
1199                     return _stream.ReadByte();
1200             }
1201
1202             private static bool OverridesBeginMethod(Stream stream, string methodName)
1203             {
1204                 Contract.Requires(stream != null, "Expected a non-null stream.");
1205                 Contract.Requires(methodName == "BeginRead" || methodName == "BeginWrite",
1206                     "Expected BeginRead or BeginWrite as the method name to check.");
1207
1208                 // Get all of the methods on the underlying stream
1209                 var methods = stream.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);
1210
1211                 // If any of the methods have the desired name and are defined on the base Stream
1212                 // Type, then the method was not overridden.  If none of them were defined on the
1213                 // base Stream, then it must have been overridden.
1214                 foreach (var method in methods)
1215                 {
1216                     if (method.DeclaringType == typeof(Stream) &&
1217                         method.Name == methodName)
1218                     {
1219                         return false;
1220                     }
1221                 }
1222                 return true;
1223             }
1224         
1225             [HostProtection(ExternalThreading=true)]
1226             public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
1227             {
1228                 // Lazily-initialize whether the wrapped stream overrides BeginRead
1229                 if (_overridesBeginRead == null)
1230                 {
1231                     _overridesBeginRead = OverridesBeginMethod(_stream, "BeginRead");
1232                 }
1233
1234                 lock (_stream)
1235                 {
1236                     // If the Stream does have its own BeginRead implementation, then we must use that override.
1237                     // If it doesn't, then we'll use the base implementation, but we'll make sure that the logic
1238                     // which ensures only one asynchronous operation does so with an asynchronous wait rather
1239                     // than a synchronous wait.  A synchronous wait will result in a deadlock condition, because
1240                     // the EndXx method for the outstanding async operation won't be able to acquire the lock on
1241                     // _stream due to this call blocked while holding the lock.
1242                     return _overridesBeginRead.Value ?
1243                         _stream.BeginRead(buffer, offset, count, callback, state) :
1244                         _stream.BeginReadInternal(buffer, offset, count, callback, state, serializeAsynchronously: true);
1245                 }
1246             }
1247         
1248             public override int EndRead(IAsyncResult asyncResult)
1249             {
1250                 if (asyncResult == null)
1251                     throw new ArgumentNullException("asyncResult");
1252                 Contract.Ensures(Contract.Result<int>() >= 0);
1253                 Contract.EndContractBlock();
1254
1255                 lock(_stream)
1256                     return _stream.EndRead(asyncResult);
1257             }
1258         
1259             public override long Seek(long offset, SeekOrigin origin)
1260             {
1261                 lock(_stream)
1262                     return _stream.Seek(offset, origin);
1263             }
1264         
1265             public override void SetLength(long length)
1266             {
1267                 lock(_stream)
1268                     _stream.SetLength(length);
1269             }
1270         
1271             public override void Write(byte[] bytes, int offset, int count)
1272             {
1273                 lock(_stream)
1274                     _stream.Write(bytes, offset, count);
1275             }
1276         
1277             public override void WriteByte(byte b)
1278             {
1279                 lock(_stream)
1280                     _stream.WriteByte(b);
1281             }
1282         
1283             [HostProtection(ExternalThreading=true)]
1284             public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
1285             {
1286                 // Lazily-initialize whether the wrapped stream overrides BeginWrite
1287                 if (_overridesBeginWrite == null)
1288                 {
1289                     _overridesBeginWrite = OverridesBeginMethod(_stream, "BeginWrite");
1290                 }
1291
1292                 lock (_stream)
1293                 {
1294                     // If the Stream does have its own BeginWrite implementation, then we must use that override.
1295                     // If it doesn't, then we'll use the base implementation, but we'll make sure that the logic
1296                     // which ensures only one asynchronous operation does so with an asynchronous wait rather
1297                     // than a synchronous wait.  A synchronous wait will result in a deadlock condition, because
1298                     // the EndXx method for the outstanding async operation won't be able to acquire the lock on
1299                     // _stream due to this call blocked while holding the lock.
1300                     return _overridesBeginWrite.Value ?
1301                         _stream.BeginWrite(buffer, offset, count, callback, state) :
1302                         _stream.BeginWriteInternal(buffer, offset, count, callback, state, serializeAsynchronously: true);
1303                 }
1304             }
1305             
1306             public override void EndWrite(IAsyncResult asyncResult)
1307             {
1308                 if (asyncResult == null)
1309                     throw new ArgumentNullException("asyncResult");
1310                 Contract.EndContractBlock();
1311
1312                 lock(_stream)
1313                     _stream.EndWrite(asyncResult);
1314             }
1315         }
1316     }
1317
1318 #if CONTRACTS_FULL
1319     [ContractClassFor(typeof(Stream))]
1320     internal abstract class StreamContract : Stream
1321     {
1322         public override long Seek(long offset, SeekOrigin origin)
1323         {
1324             Contract.Ensures(Contract.Result<long>() >= 0);
1325             throw new NotImplementedException();
1326         }
1327
1328         public override void SetLength(long value)
1329         {
1330             throw new NotImplementedException();
1331         }
1332
1333         public override int Read(byte[] buffer, int offset, int count)
1334         {
1335             Contract.Ensures(Contract.Result<int>() >= 0);
1336             Contract.Ensures(Contract.Result<int>() <= count);
1337             throw new NotImplementedException();
1338         }
1339
1340         public override void Write(byte[] buffer, int offset, int count)
1341         {
1342             throw new NotImplementedException();
1343         }
1344
1345         public override long Position {
1346             get {
1347                 Contract.Ensures(Contract.Result<long>() >= 0);
1348                 throw new NotImplementedException();
1349             }
1350             set {
1351                 throw new NotImplementedException();
1352             }
1353         }
1354
1355         public override void Flush()
1356         {
1357             throw new NotImplementedException();
1358         }
1359
1360         public override bool CanRead {
1361             get { throw new NotImplementedException(); }
1362         }
1363
1364         public override bool CanWrite {
1365             get { throw new NotImplementedException(); }
1366         }
1367
1368         public override bool CanSeek {
1369             get { throw new NotImplementedException(); }
1370         }
1371
1372         public override long Length
1373         {
1374             get {
1375                 Contract.Ensures(Contract.Result<long>() >= 0);
1376                 throw new NotImplementedException();
1377             }
1378         }
1379     }
1380 #endif  // CONTRACTS_FULL
1381 }