Skip to content

Commit fc7286c

Browse files
authored
Stream subclasses now have Close call base.Close to ensure disposal. (#369)
* Subclasses of `Stream` now have `Close` call `base.Close` to ensure disposal. * Add DeleteOnClose to File opening. * Remove explicit delete of file. * Remove explicit close of substream. * Since no longer deleting explicitly, no longer need `_overflowPath` member.
1 parent 84cb59e commit fc7286c

File tree

2 files changed

+23
-41
lines changed

2 files changed

+23
-41
lines changed

src/Microsoft.ML.Core/Utilities/HybridMemoryStream.cs

+16-21
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,24 @@ public sealed class HybridMemoryStream : Stream
1919
{
2020
private MemoryStream _memStream;
2121
private Stream _overflowStream;
22-
private string _overflowPath;
2322
private readonly int _overflowBoundary;
2423
private const int _defaultMaxLen = 1 << 30;
2524

2625
private bool _disposed;
2726

28-
private Stream MyStream { get { return _memStream ?? _overflowStream; } }
27+
private Stream MyStream => _memStream ?? _overflowStream;
2928

30-
private bool IsMemory { get { return _memStream != null; } }
29+
private bool IsMemory => _memStream != null;
3130

32-
public override long Position
33-
{
34-
get { return MyStream.Position; }
35-
set { Seek(value, SeekOrigin.Begin); }
31+
public override long Position {
32+
get => MyStream.Position;
33+
set => Seek(value, SeekOrigin.Begin);
3634
}
3735

38-
public override long Length { get { return MyStream.Length; } }
39-
public override bool CanWrite { get { return MyStream.CanWrite; } }
40-
public override bool CanSeek { get { return MyStream.CanSeek; } }
41-
public override bool CanRead { get { return MyStream.CanRead; } }
36+
public override long Length => MyStream.Length;
37+
public override bool CanWrite => MyStream.CanWrite;
38+
public override bool CanSeek => MyStream.CanSeek;
39+
public override bool CanRead => MyStream.CanRead;
4240

4341
/// <summary>
4442
/// Constructs an initially empty read-write stream. Once the number of
@@ -123,27 +121,24 @@ protected override void Dispose(bool disposing)
123121
var overflow = _overflowStream;
124122
_overflowStream = null;
125123
overflow.Dispose();
126-
Contracts.AssertValue(_overflowPath);
127-
File.Delete(_overflowPath);
128-
_overflowPath = null;
129124
}
130125
_disposed = true;
131126
AssertInvariants();
127+
base.Dispose(disposing);
132128
}
133129
}
134130

135131
public override void Close()
136132
{
137133
AssertInvariants();
138-
if (MyStream != null)
139-
MyStream.Close();
134+
// The base Stream class Close will call Dispose(bool).
135+
base.Close();
140136
}
141137

142138
public override void Flush()
143139
{
144140
AssertInvariants();
145-
if (MyStream != null)
146-
MyStream.Flush();
141+
MyStream?.Flush();
147142
AssertInvariants();
148143
}
149144

@@ -164,9 +159,9 @@ private void EnsureOverflow()
164159
// been closed.
165160
Contracts.Check(_memStream.CanRead, "attempt to perform operation on closed stream");
166161

167-
Contracts.Assert(_overflowPath == null);
168-
_overflowPath = Path.GetTempFileName();
169-
_overflowStream = new FileStream(_overflowPath, FileMode.Open, FileAccess.ReadWrite);
162+
string overflowPath = Path.GetTempFileName();
163+
_overflowStream = new FileStream(overflowPath, FileMode.Open, FileAccess.ReadWrite,
164+
FileShare.None, bufferSize: 4096, FileOptions.DeleteOnClose);
170165

171166
// The documentation is not clear on this point, but the source code for
172167
// memory stream makes clear that this buffer is exposable for a memory

src/Microsoft.ML.Core/Utilities/TextReaderStream.cs

+7-20
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace Microsoft.ML.Runtime.Internal.Utilities
1414
/// compensates by inserting <c>\n</c> line feed characters at the end of every
1515
/// input line, including the last one.
1616
/// </summary>
17-
public class TextReaderStream : Stream
17+
public sealed class TextReaderStream : Stream
1818
{
1919
private readonly TextReader _baseReader;
2020
private readonly Encoding _encoding;
@@ -38,19 +38,11 @@ public class TextReaderStream : Stream
3838
public override bool CanWrite => false;
3939

4040
public override long Length
41-
{
42-
get
43-
{
44-
throw Contracts.ExceptNotSupp("Stream cannot determine length.");
45-
}
46-
}
41+
=> throw Contracts.ExceptNotSupp("Stream cannot determine length.");
4742

4843
public override long Position
4944
{
50-
get
51-
{
52-
return _position;
53-
}
45+
get => _position;
5446
set
5547
{
5648
if (value != Position)
@@ -96,6 +88,7 @@ public override void Close()
9688
protected override void Dispose(bool disposing)
9789
{
9890
_baseReader.Dispose();
91+
base.Dispose(disposing);
9992
}
10093

10194
public override void Flush()
@@ -182,18 +175,12 @@ public override int ReadByte()
182175
}
183176

184177
public override long Seek(long offset, SeekOrigin origin)
185-
{
186-
throw Contracts.ExceptNotSupp("Stream cannot seek.");
187-
}
178+
=> throw Contracts.ExceptNotSupp("Stream cannot seek.");
188179

189180
public override void Write(byte[] buffer, int offset, int count)
190-
{
191-
throw Contracts.ExceptNotSupp("Stream is not writable.");
192-
}
181+
=> throw Contracts.ExceptNotSupp("Stream is not writable.");
193182

194183
public override void SetLength(long value)
195-
{
196-
throw Contracts.ExceptNotSupp("Stream is not writable.");
197-
}
184+
=> throw Contracts.ExceptNotSupp("Stream is not writable.");
198185
}
199186
}

0 commit comments

Comments
 (0)