OSDN Git Service

リセット
[momiji/momiji_main.git] / Core / Momiji.Core.Buffer.cpp
1 /*
2 [momiji music component library]
3 ---------------------------------------------------------------------
4 Momiji.Core.Winmm.cpp
5         
6 ---------------------------------------------------------------------
7 Copyright (C) 2011 tyiki badwell {miria@users.sourceforge.jp}.
8
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program.  If not, see <http://www.gnu.org/licenses/gpl-3.0.html>.
21 ---------------------------------------------------------------------
22 */
23 #include "StdAfx.h"
24
25 #include "Momiji.Core.Buffer.h"
26
27 namespace Momiji {
28 namespace Core {
29 namespace Buffer {
30
31         generic<typename DATA_TYPE> 
32         BufferPool<DATA_TYPE>::Buffer::Buffer(Allocator^ allocator)
33                 :_allocator(allocator)
34         {
35                 #ifdef _DEBUG
36                         System::Console::WriteLine("[{0}]",__FUNCTION__);
37                 #endif
38
39                 this->Alloc();
40         }
41
42         generic<typename DATA_TYPE> 
43         BufferPool<DATA_TYPE>::Buffer::~Buffer()
44         {
45                 #ifdef _DEBUG
46                         System::Console::WriteLine("[{0}]",__FUNCTION__);
47                 #endif
48                 this->!Buffer();
49         }
50
51         generic<typename DATA_TYPE> 
52         BufferPool<DATA_TYPE>::Buffer::!Buffer()
53         {
54                 #ifdef _DEBUG
55                         System::Console::WriteLine("[{0}]",__FUNCTION__);
56                 #endif
57                 this->Free();
58         }
59
60         generic<typename DATA_TYPE>
61         void BufferPool<DATA_TYPE>::Buffer::Alloc()
62         {
63                 #ifdef _DEBUG
64                         System::Console::WriteLine("[{0}]",__FUNCTION__);
65                 #endif
66
67                 this->_buffer = this->_allocator(); 
68                 this->_bufferHandle = InteropServices::GCHandle::Alloc(this->_buffer, InteropServices::GCHandleType::Pinned);
69         }
70
71         generic<typename DATA_TYPE>
72         void BufferPool<DATA_TYPE>::Buffer::Free()
73         {
74                 #ifdef _DEBUG
75                         System::Console::WriteLine("[{0}]",__FUNCTION__);
76                 #endif
77                 if (this->_bufferHandle.IsAllocated)
78                 {
79                         this->_bufferHandle.Free();
80                         delete this->_buffer;
81                 }
82         }
83
84         generic<typename DATA_TYPE>
85         System::IntPtr BufferPool<DATA_TYPE>::Buffer::GetBufferIntPtr()
86         {
87                 return this->_bufferHandle.AddrOfPinnedObject();
88         }
89
90         generic<typename DATA_TYPE>
91         DATA_TYPE% BufferPool<DATA_TYPE>::Buffer::GetBuffer()
92         {
93                 #ifdef _DEBUG
94                         System::Console::WriteLine("[{0}]",__FUNCTION__);
95                 #endif
96                 
97                 return this->_buffer;
98         }
99
100
101
102
103
104
105         generic<typename DATA_TYPE>
106         BufferPool<DATA_TYPE>::BufferPool(
107                 System::UInt32 defaultPoolSize,
108                 Allocator^ allocator
109         ):      _allocator(allocator),
110                 _buffers(gcnew System::Collections::Generic::List<Buffer^>()),
111                 _idleBuffers(gcnew System::Collections::Generic::Dictionary<System::IntPtr, Buffer^>()),
112                 _busyBuffers(gcnew System::Collections::Generic::Dictionary<System::IntPtr, Buffer^>()),
113                 _defaultPoolSize(defaultPoolSize)
114         {
115                 #ifdef _DEBUG
116                         System::Console::WriteLine("[{0}]",__FUNCTION__);
117                 #endif
118
119                 for (System::UInt32 i = 0; i < this->_defaultPoolSize; i++)
120                 {
121                         this->MakeBuffer();
122                 }
123         }
124
125         generic<typename DATA_TYPE> 
126         BufferPool<DATA_TYPE>::~BufferPool()
127         {
128                 #ifdef _DEBUG
129                         System::Console::WriteLine("[{0}]",__FUNCTION__);
130                 #endif
131                 this->!BufferPool();
132         }
133
134         generic<typename DATA_TYPE> 
135         BufferPool<DATA_TYPE>::!BufferPool()
136         {
137                 #ifdef _DEBUG
138                         System::Console::WriteLine("[{0}]",__FUNCTION__);
139                 #endif
140                 
141                 for each (Buffer^ buffer in this->_buffers)
142                 {
143                         delete buffer;
144                 }
145                 this->_buffers->Clear();
146                 this->_idleBuffers->Clear();
147                 this->_busyBuffers->Clear();
148         }
149
150         generic<typename DATA_TYPE> 
151         BufferPool<DATA_TYPE>::Buffer^ BufferPool<DATA_TYPE>::Get()
152         {
153                 #ifdef _DEBUG
154                         System::Console::WriteLine("[{0}]",__FUNCTION__);
155                 #endif
156
157                 System::Threading::Monitor::Enter(this);
158                 try
159                 {
160                         if (this->_idleBuffers->Count == 0)
161                         {
162                                 //暇なバッファが無ければ、1回分のバッファを新規作成
163                                 this->MakeBuffer();
164                         }
165
166                         System::Collections::Generic::KeyValuePair<System::IntPtr, Buffer^> pair = 
167                                 System::Linq::Enumerable::First(this->_idleBuffers);
168                         #ifdef _DEBUG
169                                 System::Console::WriteLine("[{0}] buffer ptr[{1}]", __FUNCTION__, pair.Key);
170                         #endif
171
172                         Buffer^ buffer = pair.Value;
173                         auto intPtr = buffer->GetBufferIntPtr();
174                         if (!this->_idleBuffers->Remove(intPtr))
175                         {
176                                 throw gcnew System::Exception("バッファの確保に失敗しました。");
177                         }
178                         this->_busyBuffers->Add(intPtr, buffer);
179
180                         //#ifdef _DEBUG
181                                 System::Console::WriteLine("[{0}] alloc[{1}] idle[{2}] busy[{3}]", __FUNCTION__, this->_buffers->Count, this->_idleBuffers->Count, this->_busyBuffers->Count);
182                         //#endif
183
184                         return buffer;
185                 }
186                 finally
187                 {
188                         System::Threading::Monitor::Exit(this);
189                 }
190         }
191
192         generic<typename DATA_TYPE> 
193         BufferPool<DATA_TYPE>::Buffer^ BufferPool<DATA_TYPE>::GetBusy(System::IntPtr bufferPtr)
194         {
195                 #ifdef _DEBUG
196                         System::Console::WriteLine("[{0}][{1}]",__FUNCTION__, bufferPtr);
197                 #endif
198
199                 BufferPool<DATA_TYPE>::Buffer^ buffer = nullptr;
200                 if (!this->_busyBuffers->TryGetValue(bufferPtr, buffer))
201                 {
202                         throw gcnew System::Exception("使用済みバッファの取得に失敗しました。");
203                 }
204
205                 return buffer;
206         }
207
208         generic<typename DATA_TYPE> 
209         void BufferPool<DATA_TYPE>::Release(Buffer^ buffer)
210         {
211                 #ifdef _DEBUG
212                         System::Console::WriteLine("[{0}]",__FUNCTION__);
213                 #endif
214
215                 System::Threading::Monitor::Enter(this);
216                 try
217                 {
218                         auto intPtr = buffer->GetBufferIntPtr();
219                         if (!this->_busyBuffers->Remove(intPtr))
220                         {
221                                 throw gcnew System::Exception("使用済みバッファの開放に失敗しました。");
222                         }
223                         #ifdef _DEBUG
224                                 System::Console::WriteLine("[{0}] buffer ptr[{1}]", __FUNCTION__, intPtr);
225                         #endif
226                         this->_idleBuffers->Add(intPtr, buffer);
227
228                         //#ifdef _DEBUG
229                                 System::Console::WriteLine("[{0}] alloc[{1}] idle[{2}] busy[{3}]", __FUNCTION__, this->_buffers->Count, this->_idleBuffers->Count, this->_busyBuffers->Count);
230                         //#endif
231                 }
232                 finally
233                 {
234                         System::Threading::Monitor::Exit(this);
235                 }
236         }
237
238         generic<typename DATA_TYPE> 
239         BufferPool<DATA_TYPE>::Buffer^ BufferPool<DATA_TYPE>::MakeBuffer()
240         {
241                 #ifdef _DEBUG
242                         System::Console::WriteLine("[{0}]",__FUNCTION__);
243                 #endif
244
245                 BufferPool<DATA_TYPE>::Buffer^ buffer = gcnew BufferPool<DATA_TYPE>::Buffer(this->_allocator);
246                 this->_buffers->Add(buffer);
247                 this->_idleBuffers->Add(buffer->GetBufferIntPtr(), buffer);
248
249                 //#ifdef _DEBUG
250                         System::Console::WriteLine("[{0}] alloc[{1}] idle[{2}] busy[{3}]", __FUNCTION__, this->_buffers->Count, this->_idleBuffers->Count, this->_busyBuffers->Count);
251                 //#endif
252
253                 return buffer;
254         }
255
256         generic<typename DATA_TYPE>
257         System::Boolean BufferPool<DATA_TYPE>::IsBusy()
258         {
259                 return (this->_busyBuffers->Count > 0);
260         }
261
262 }
263 }
264 }