tgstation-server
6.12.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
src
Tgstation.Server.Host
IO
BufferedFileStreamProvider.cs
Go to the documentation of this file.
1
using
System;
2
using
System.IO;
3
using
System.Threading;
4
using
System.Threading.Tasks;
5
6
using
Tgstation.Server.Host.Utils
;
7
8
namespace
Tgstation.Server.Host.IO
9
{
13
public
sealed
class
BufferedFileStreamProvider
:
ISeekableFileStreamProvider
14
{
16
public
bool
Disposed
=>
buffer
==
null
;
17
21
readonly
Stream
input
;
22
26
readonly SemaphoreSlim
semaphore
;
27
31
volatile
MemoryStream?
buffer
;
32
36
volatile
bool
buffered
;
37
42
public
BufferedFileStreamProvider
(
Stream
input
)
43
{
44
this.input =
input
??
throw
new
ArgumentNullException(nameof(
input
));
45
46
semaphore
=
new
SemaphoreSlim(1);
47
try
48
{
49
buffer
=
new
MemoryStream();
50
}
51
catch
52
{
53
semaphore
.Dispose();
54
throw
;
55
}
56
}
57
59
public
async ValueTask
DisposeAsync
()
60
{
61
MemoryStream? localBuffer;
62
lock (
semaphore
)
63
{
64
localBuffer =
buffer
;
65
if
(localBuffer ==
null
)
66
return
;
67
68
// important to drop the reference so it can properly GC
69
// The implementation of MemoryStream doesn't fucking do this for some reason
70
buffer
=
null
;
71
buffered
=
true
;
72
}
73
74
var bufferDispose = localBuffer.DisposeAsync();
75
semaphore
.Dispose();
76
await bufferDispose;
77
}
78
80
public
async ValueTask<Stream>
GetResult
(CancellationToken cancellationToken)
81
{
82
var (sharedStream, _) = await
GetResultInternal
(cancellationToken);
83
return
sharedStream;
84
}
85
87
public
async ValueTask<MemoryStream>
GetOwnedResult
(CancellationToken cancellationToken)
88
{
89
var (sharedStream, length) = await
GetResultInternal
(cancellationToken);
90
return
new
MemoryStream(sharedStream.GetBuffer(), 0, (
int
)length,
false
,
true
);
91
}
92
98
public
Task
EnsureBuffered
(CancellationToken cancellationToken) =>
GetResultInternal
(cancellationToken).AsTask();
99
105
async ValueTask<(MemoryStream
Stream
,
long
StreamLength)>
GetResultInternal
(CancellationToken cancellationToken)
106
{
107
if
(!
buffered
)
108
using
(await
SemaphoreSlimContext
.
Lock
(
semaphore
, cancellationToken))
109
if
(!
buffered
)
110
{
111
MemoryStream localBuffer;
112
lock (
semaphore
)
113
localBuffer =
buffer
??
throw
new
ObjectDisposedException(nameof(
BufferedFileStreamProvider
));
114
115
await
input
.CopyToAsync(localBuffer, cancellationToken);
116
localBuffer.Seek(0, SeekOrigin.Begin);
117
buffered
=
true
;
118
return
(
Stream
: localBuffer, StreamLength: localBuffer.Length);
119
}
120
121
lock (
semaphore
)
122
{
123
var localBuffer =
buffer
??
throw
new
ObjectDisposedException(nameof(
BufferedFileStreamProvider
));
124
return
(
125
Stream
: localBuffer,
126
StreamLength: localBuffer.Length);
127
}
128
}
129
}
130
}
Stream
Tgstation.Server.Host.IO.BufferedFileStreamProvider
IFileStreamProvider that provides a ISeekableFileStreamProvider from an input Stream.
Definition
BufferedFileStreamProvider.cs:14
Tgstation.Server.Host.IO.BufferedFileStreamProvider.buffer
volatile? MemoryStream buffer
The backing Stream.
Definition
BufferedFileStreamProvider.cs:31
Tgstation.Server.Host.IO.BufferedFileStreamProvider.buffered
volatile bool buffered
If buffer has been populated.
Definition
BufferedFileStreamProvider.cs:36
Tgstation.Server.Host.IO.BufferedFileStreamProvider.GetOwnedResult
async ValueTask< MemoryStream > GetOwnedResult(CancellationToken cancellationToken)
Gets the provided MemoryStream. May be called multiple times, though cancelling any may cause all cal...
Definition
BufferedFileStreamProvider.cs:87
Tgstation.Server.Host.IO.BufferedFileStreamProvider.GetResultInternal
async ValueTask<(MemoryStream Stream, long StreamLength)> GetResultInternal(CancellationToken cancellationToken)
Gets the shared MemoryStream and its Stream.Length.
Definition
BufferedFileStreamProvider.cs:105
Tgstation.Server.Host.IO.BufferedFileStreamProvider.Disposed
bool Disposed
If the ISeekableFileStreamProvider has had global::System.IAsyncDisposable.DisposeAsync called on it.
Definition
BufferedFileStreamProvider.cs:16
Tgstation.Server.Host.IO.BufferedFileStreamProvider.GetResult
async ValueTask< Stream > GetResult(CancellationToken cancellationToken)
Gets the provided Stream. May be called multiple times, though cancelling any may cause all calls to ...
Definition
BufferedFileStreamProvider.cs:80
Tgstation.Server.Host.IO.BufferedFileStreamProvider.semaphore
readonly SemaphoreSlim semaphore
The SemaphoreSlim used to synchronize writes to buffer.
Definition
BufferedFileStreamProvider.cs:26
Tgstation.Server.Host.IO.BufferedFileStreamProvider.input
readonly Stream input
The original input Stream must remain valid for the lifetime of the BufferedFileStreamProvider or unt...
Definition
BufferedFileStreamProvider.cs:21
Tgstation.Server.Host.IO.BufferedFileStreamProvider.BufferedFileStreamProvider
BufferedFileStreamProvider(Stream input)
Initializes a new instance of the BufferedFileStreamProvider class.
Definition
BufferedFileStreamProvider.cs:42
Tgstation.Server.Host.IO.BufferedFileStreamProvider.EnsureBuffered
Task EnsureBuffered(CancellationToken cancellationToken)
Ensures the input Stream has been copied to the buffer.
Tgstation.Server.Host.IO.BufferedFileStreamProvider.DisposeAsync
async ValueTask DisposeAsync()
Definition
BufferedFileStreamProvider.cs:59
Tgstation.Server.Host.Utils.SemaphoreSlimContext
Async lock context helper.
Definition
SemaphoreSlimContext.cs:13
Tgstation.Server.Host.Utils.SemaphoreSlimContext.Lock
static async ValueTask< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken, ILogger? logger=null)
Asyncronously locks a semaphore .
Definition
SemaphoreSlimContext.cs:21
Tgstation.Server.Host.IO.ISeekableFileStreamProvider
IFileStreamProvider that provides MemoryStreams.
Definition
ISeekableFileStreamProvider.cs:11
Tgstation.Server.Host.IO
Definition
BufferedFileStreamProvider.cs:9
Tgstation.Server.Host.Utils
Definition
AbstractHttpClientFactory.cs:10
Generated by
1.9.8