2 * Copyright 2002, Marcus Overhagen. All rights reserved.
3 * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
8 #include "BufferManager.h"
13 #include "SharedBufferList.h"
16 BufferManager::BufferManager()
18 fSharedBufferList(NULL
),
19 fSharedBufferListArea(-1),
21 fLocker("buffer manager locker")
24 = BPrivate::SharedBufferList::Create(&fSharedBufferList
);
28 BufferManager::~BufferManager()
30 fSharedBufferList
->Put();
35 BufferManager::SharedBufferListArea()
37 return fSharedBufferListArea
;
42 BufferManager::RegisterBuffer(team_id team
, media_buffer_id bufferID
,
43 size_t* _size
, int32
* _flags
, size_t* _offset
, area_id
* _area
)
45 BAutolock
lock(fLocker
);
47 TRACE("RegisterBuffer team = %" B_PRId32
", bufferid = %" B_PRId32
"\n",
51 if (!fBufferInfoMap
.Get(bufferID
, info
)) {
52 ERROR("failed to register buffer! team = %" B_PRId32
", bufferid = %"
53 B_PRId32
"\n", team
, bufferID
);
57 info
->teams
.insert(team
);
60 *_offset
= info
->offset
;
62 *_flags
= info
->flags
;
69 BufferManager::RegisterBuffer(team_id team
, size_t size
, int32 flags
,
70 size_t offset
, area_id area
, media_buffer_id
* _bufferID
)
72 BAutolock
lock(fLocker
);
73 TRACE("RegisterBuffer team = %ld, area = %ld, offset = %ld, size = %ld\n",
74 team
, area
, offset
, size
);
76 area_id clonedArea
= _CloneArea(area
);
78 ERROR("RegisterBuffer: failed to clone buffer! error = %#" B_PRIx32
79 ", team = %" B_PRId32
", area = %" B_PRId32
", offset = %"
80 B_PRIuSIZE
", size = %" B_PRIuSIZE
"\n", clonedArea
, team
,
86 info
.id
= fNextBufferID
++;
87 info
.area
= clonedArea
;
93 info
.teams
.insert(team
);
94 if (fBufferInfoMap
.Put(info
.id
, info
) != B_OK
)
95 throw std::bad_alloc();
96 } catch (std::bad_alloc
& exception
) {
97 _ReleaseClonedArea(clonedArea
);
101 TRACE("RegisterBuffer: done, bufferID = %ld\n", info
.id
);
103 *_bufferID
= info
.id
;
109 BufferManager::UnregisterBuffer(team_id team
, media_buffer_id bufferID
)
111 BAutolock
lock(fLocker
);
112 TRACE("UnregisterBuffer: team = %" B_PRId32
", bufferID = %" B_PRId32
"\n",
116 if (!fBufferInfoMap
.Get(bufferID
, info
)) {
117 ERROR("UnregisterBuffer: failed to unregister buffer! team = %"
118 B_PRId32
", bufferID = %" B_PRId32
"\n", team
, bufferID
);
122 if (info
->teams
.find(team
) == info
->teams
.end()) {
123 ERROR("UnregisterBuffer: failed to find team = %" B_PRId32
" belonging"
124 " to bufferID = %" B_PRId32
"\n", team
, bufferID
);
128 info
->teams
.erase(team
);
130 TRACE("UnregisterBuffer: team = %" B_PRId32
" removed from bufferID = %"
131 B_PRId32
"\n", team
, bufferID
);
133 if (info
->teams
.empty()) {
134 _ReleaseClonedArea(info
->area
);
135 fBufferInfoMap
.Remove(bufferID
);
137 TRACE("UnregisterBuffer: bufferID = %" B_PRId32
" removed\n", bufferID
);
145 BufferManager::CleanupTeam(team_id team
)
147 BAutolock
lock(fLocker
);
149 TRACE("BufferManager::CleanupTeam: team %" B_PRId32
"\n", team
);
151 BufferInfoMap::Iterator iterator
= fBufferInfoMap
.GetIterator();
152 while (iterator
.HasNext()) {
153 BufferInfoMap::Entry entry
= iterator
.Next();
155 entry
.value
.teams
.erase(team
);
157 if (entry
.value
.teams
.empty()) {
158 PRINT(1, "BufferManager::CleanupTeam: removing buffer id %"
159 B_PRId32
" that has no teams\n", entry
.key
.GetHashCode());
160 _ReleaseClonedArea(entry
.value
.area
);
168 BufferManager::Dump()
170 BAutolock
lock(fLocker
);
173 printf("BufferManager: list of buffers follows:\n");
175 BufferInfoMap::Iterator iterator
= fBufferInfoMap
.GetIterator();
176 while (iterator
.HasNext()) {
177 buffer_info
& info
= *iterator
.NextValue();
178 printf(" buffer-id %" B_PRId32
", area-id %" B_PRId32
", offset %ld, "
179 "size %ld, flags %#08" B_PRIx32
"\n", info
.id
, info
.area
,
180 info
.offset
, info
.size
, info
.flags
);
181 printf(" assigned teams: ");
183 std::set
<team_id
>::iterator teamIterator
= info
.teams
.begin();
184 for (; teamIterator
!= info
.teams
.end(); teamIterator
++) {
185 printf("%" B_PRId32
", ", *teamIterator
);
189 printf("BufferManager: list end\n");
194 BufferManager::_CloneArea(area_id area
)
198 if (fCloneInfoMap
.Get(area
, info
)) {
199 // we have already cloned this particular area
200 TRACE("BufferManager::_CloneArea() area %" B_PRId32
" has already"
201 " been cloned (id %" B_PRId32
")\n", area
, info
->clone
);
209 area_id clonedArea
= clone_area("media_server cloned buffer", &address
,
210 B_ANY_ADDRESS
, B_READ_AREA
| B_WRITE_AREA
, area
);
212 TRACE("BufferManager::_CloneArea() cloned area %" B_PRId32
", clone id %"
213 B_PRId32
"\n", area
, clonedArea
);
219 info
.clone
= clonedArea
;
222 if (fCloneInfoMap
.Put(area
, info
) == B_OK
) {
223 if (fSourceInfoMap
.Put(clonedArea
, area
) == B_OK
)
226 fCloneInfoMap
.Remove(area
);
229 delete_area(clonedArea
);
235 BufferManager::_ReleaseClonedArea(area_id clone
)
237 area_id source
= fSourceInfoMap
.Get(clone
);
240 if (!fCloneInfoMap
.Get(source
, info
)) {
241 ERROR("BufferManager::_ReleaseClonedArea(): could not find clone info "
242 "for id %" B_PRId32
" (clone %" B_PRId32
")\n", source
, clone
);
246 if (--info
->ref_count
== 0) {
247 TRACE("BufferManager::_ReleaseClonedArea(): delete cloned area %"
248 B_PRId32
" (source %" B_PRId32
")\n", clone
, source
);
250 fSourceInfoMap
.Remove(clone
);
251 fCloneInfoMap
.Remove(source
);
254 TRACE("BufferManager::_ReleaseClonedArea(): released cloned area %"
255 B_PRId32
" (source %" B_PRId32
")\n", clone
, source
);