OSDN Git Service

#38036 どこでCTextureの解放漏れが発生しているかを容易に識別できるようにするために、CTextureの生成時にラベルを付与できるようにした。(引数最後にラベ...
[dtxmania/dtxmania.git] / NVorbis / BufferedReadStream.cs
1 /****************************************************************************
2  * NVorbis                                                                  *
3  * Copyright (C) 2014, Andrew Ward <afward@gmail.com>                       *
4  *                                                                          *
5  * See COPYING for license terms (Ms-PL).                                   *
6  *                                                                          *
7  ***************************************************************************/
8 using System;
9 using System.Collections.Generic;
10 using System.IO;
11
12 namespace NVorbis
13 {
14     /// <summary>
15     /// A thread-safe, read-only, buffering stream wrapper.
16     /// </summary>
17     partial class BufferedReadStream : Stream
18     {
19         const int DEFAULT_INITIAL_SIZE = 32768; // 32KB  (1/2 full page)
20         const int DEFAULT_MAX_SIZE = 262144;    // 256KB (4 full pages)
21
22         Stream _baseStream;
23         StreamReadBuffer _buffer;
24         long _readPosition;
25         object _localLock = new object();
26         System.Threading.Thread _owningThread;
27         int _lockCount;
28
29         public BufferedReadStream(Stream baseStream)
30             : this(baseStream, DEFAULT_INITIAL_SIZE, DEFAULT_MAX_SIZE, false)
31         {
32         }
33
34         public BufferedReadStream(Stream baseStream, bool minimalRead)
35             : this(baseStream, DEFAULT_INITIAL_SIZE, DEFAULT_MAX_SIZE, minimalRead)
36         {
37         }
38
39         public BufferedReadStream(Stream baseStream, int initialSize, int maxSize)
40             : this(baseStream, initialSize, maxSize, false)
41         {
42         }
43
44         public BufferedReadStream(Stream baseStream, int initialSize, int maxBufferSize, bool minimalRead)
45         {
46             if (baseStream == null) throw new ArgumentNullException("baseStream");
47             if (!baseStream.CanRead) throw new ArgumentException("baseStream");
48
49             if (maxBufferSize < 1) maxBufferSize = 1;
50             if (initialSize < 1) initialSize = 1;
51             if (initialSize > maxBufferSize) initialSize = maxBufferSize;
52
53             _baseStream = baseStream;
54             _buffer = new StreamReadBuffer(baseStream, initialSize, maxBufferSize, minimalRead);
55             _buffer.MaxSize = maxBufferSize;
56             _buffer.MinimalRead = minimalRead;
57         }
58
59         protected override void Dispose(bool disposing)
60         {
61             base.Dispose(disposing);
62             if (disposing)
63             {
64                 if (_buffer != null)
65                 {
66                     _buffer.Dispose();
67                     _buffer = null;
68                 }
69
70                 if (CloseBaseStream)
71                 {
72                     _baseStream.Close();
73                 }
74             }
75         }
76
77         // route all the container locking through here so we can track whether the caller actually took the lock...
78         public void TakeLock()
79         {
80             System.Threading.Monitor.Enter(_localLock);
81             if (++_lockCount == 1)
82             {
83                 _owningThread = System.Threading.Thread.CurrentThread;
84             }
85         }
86
87         void CheckLock()
88         {
89             if (_owningThread != System.Threading.Thread.CurrentThread)
90             {
91                 throw new System.Threading.SynchronizationLockException();
92             }
93         }
94
95         public void ReleaseLock()
96         {
97             CheckLock();
98             if (--_lockCount == 0)
99             {
100                 _owningThread = null;
101             }
102             System.Threading.Monitor.Exit(_localLock);
103         }
104
105         public bool CloseBaseStream
106         {
107             get;
108             set;
109         }
110
111         public bool MinimalRead
112         {
113             get { return _buffer.MinimalRead; }
114             set { _buffer.MinimalRead = value; }
115         }
116
117         public int MaxBufferSize
118         {
119             get { return _buffer.MaxSize; }
120             set
121             {
122                 CheckLock();
123                 _buffer.MaxSize = value;
124             }
125         }
126
127         public long BufferBaseOffset
128         {
129             get { return _buffer.BaseOffset; }
130         }
131
132         public int BufferBytesFilled
133         {
134             get { return _buffer.BytesFilled; }
135         }
136
137         public void Discard(int bytes)
138         {
139             CheckLock();
140             _buffer.DiscardThrough(_buffer.BaseOffset + bytes);
141         }
142
143         public void DiscardThrough(long offset)
144         {
145             CheckLock();
146             _buffer.DiscardThrough(offset);
147         }
148
149         public override bool CanRead
150         {
151             get { return true; }
152         }
153
154         public override bool CanSeek
155         {
156             get { return true; }
157         }
158
159         public override bool CanWrite
160         {
161             get { return false; }
162         }
163
164         public override void Flush()
165         {
166             // no-op
167         }
168
169         public override long Length
170         {
171             get { return _baseStream.Length; }
172         }
173
174         public override long Position
175         {
176             get { return _readPosition; }
177             set { Seek(value, SeekOrigin.Begin); }
178         }
179
180         public override int ReadByte()
181         {
182             CheckLock();
183             var val = _buffer.ReadByte(Position);
184             if (val > -1)
185             {
186                 Seek(1, SeekOrigin.Current);
187             }
188             return val;
189         }
190
191         public override int Read(byte[] buffer, int offset, int count)
192         {
193             CheckLock();
194             var cnt = _buffer.Read(Position, buffer, offset, count);
195             Seek(cnt, SeekOrigin.Current);
196             return cnt;
197         }
198
199         public override long Seek(long offset, SeekOrigin origin)
200         {
201             CheckLock();
202             switch (origin)
203             {
204                 case SeekOrigin.Begin:
205                     // no-op
206                     break;
207                 case SeekOrigin.Current:
208                     offset += Position;
209                     break;
210                 case SeekOrigin.End:
211                     offset += _baseStream.Length;
212                     break;
213             }
214
215             if (!_baseStream.CanSeek)
216             {
217                 if (offset < _buffer.BaseOffset) throw new InvalidOperationException("Cannot seek to before the start of the buffer!");
218                 if (offset >= _buffer.BufferEndOffset) throw new InvalidOperationException("Cannot seek to beyond the end of the buffer!  Discard some bytes.");
219             }
220
221             return (_readPosition = offset);
222         }
223
224         public override void SetLength(long value)
225         {
226             throw new NotSupportedException();
227         }
228
229         public override void Write(byte[] buffer, int offset, int count)
230         {
231             throw new NotSupportedException();
232         }
233     }
234 }