* When a buffer_info is removed, its area is now actually deleted as well. This

already fixes bug #4189, although there is another bug that could cause a
  similar effect (working on that next).
* Switched from media_server local TMap to HashMap, although this is probably
  equally archaic.
* Also replaced TList with std::set for the team list.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32155 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-08-06 09:45:04 +00:00
parent 5174cb1f74
commit 8399a7c04d
2 changed files with 114 additions and 53 deletions
+50 -43
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2002, Marcus Overhagen. All rights reserved.
* Copyright 2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
@@ -34,6 +35,7 @@ BufferManager::SharedBufferListID()
return fSharedBufferListID;
}
status_t
BufferManager::RegisterBuffer(team_id team, media_buffer_id bufferID,
size_t* _size, int32* _flags, size_t* _offset, area_id* _area)
@@ -43,13 +45,13 @@ BufferManager::RegisterBuffer(team_id team, media_buffer_id bufferID,
TRACE("RegisterBuffer team = %ld, bufferid = %ld\n", team, bufferID);
buffer_info* info;
if (!fBufferInfoMap.Get(bufferID, &info)) {
if (!fBufferInfoMap.Get(bufferID, info)) {
ERROR("failed to register buffer! team = %ld, bufferid = %ld\n", team,
bufferID);
return B_ERROR;
}
info->teams.Insert(team);
info->teams.insert(team);
*_area = info->area;
*_offset = info->offset;
@@ -68,14 +70,12 @@ BufferManager::RegisterBuffer(team_id team, size_t size, int32 flags,
TRACE("RegisterBuffer team = %ld, area = %ld, offset = %ld, size = %ld\n",
team, area, offset, size);
void* address;
area_id clonedArea = clone_area("media_server cloned buffer", &address,
B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area);
area_id clonedArea = _CloneArea(area);
if (clonedArea < 0) {
ERROR("RegisterBuffer: failed to clone buffer! error = %#lx, team = "
"%ld, areaid = %ld, offset = %ld, size = %ld\n", clonedArea, team,
"%ld, area = %ld, offset = %ld, size = %ld\n", clonedArea, team,
area, offset, size);
return B_ERROR;
return clonedArea;
}
buffer_info info;
@@ -84,11 +84,11 @@ BufferManager::RegisterBuffer(team_id team, size_t size, int32 flags,
info.offset = offset;
info.size = size;
info.flags = flags;
info.teams.Insert(team);
info.teams.insert(team);
*_bufferID = info.id;
fBufferInfoMap.Insert(info.id, info);
fBufferInfoMap.Put(info.id, info);
TRACE("RegisterBuffer: done, bufferID = %ld\n", info.id);
@@ -103,34 +103,26 @@ BufferManager::UnregisterBuffer(team_id team, media_buffer_id bufferID)
TRACE("UnregisterBuffer: team = %ld, bufferid = %ld\n", team, bufferID);
buffer_info* info;
if (!fBufferInfoMap.Get(bufferID, &info)) {
if (!fBufferInfoMap.Get(bufferID, info)) {
ERROR("UnregisterBuffer: failed to unregister buffer! team = %ld, "
"bufferid = %ld\n", team, bufferID);
return B_ERROR;
}
int index = info->teams.Find(team);
if (index < 0) {
if (info->teams.find(team) == info->teams.end()) {
ERROR("UnregisterBuffer: failed to find team = %ld belonging to "
"bufferID = %ld\n", team, bufferID);
return B_ERROR;
}
if (!info->teams.Remove(index)) {
ERROR("UnregisterBuffer: failed to remove team = %ld from bufferID "
"= %ld\n", team, bufferID);
return B_ERROR;
}
info->teams.erase(team);
TRACE("UnregisterBuffer: team = %ld removed from bufferID = %ld\n", team,
bufferID);
if (info->teams.IsEmpty()) {
if (!fBufferInfoMap.Remove(bufferID)) {
ERROR("UnregisterBuffer: failed to remove bufferID = %ld\n",
bufferID);
return B_ERROR;
}
if (info->teams.empty()) {
_ReleaseClonedArea(info->area);
fBufferInfoMap.Remove(bufferID);
TRACE("UnregisterBuffer: bufferID = %ld removed\n", bufferID);
}
@@ -146,20 +138,17 @@ BufferManager::CleanupTeam(team_id team)
TRACE("BufferManager::CleanupTeam: team %ld\n", team);
buffer_info* info;
for (fBufferInfoMap.Rewind(); fBufferInfoMap.GetNext(&info); ) {
team_id* currentTeam;
for (info->teams.Rewind(); info->teams.GetNext(&currentTeam); ) {
if (team == *currentTeam) {
PRINT(1, "BufferManager::CleanupTeam: removing team %ld from "
"buffer id %ld\n", team, info->id);
info->teams.RemoveCurrent();
}
}
if (info->teams.IsEmpty()) {
BufferInfoMap::Iterator iterator = fBufferInfoMap.GetIterator();
while (iterator.HasNext()) {
BufferInfoMap::Entry entry = iterator.Next();
entry.value.teams.erase(team);
if (entry.value.teams.empty()) {
PRINT(1, "BufferManager::CleanupTeam: removing buffer id %ld that "
"has no teams\n", info->id);
fBufferInfoMap.RemoveCurrent();
"has no teams\n", entry.key);
_ReleaseClonedArea(entry.value.area);
iterator.Remove();
}
}
}
@@ -173,18 +162,36 @@ BufferManager::Dump()
printf("\n");
printf("BufferManager: list of buffers follows:\n");
buffer_info *info;
for (fBufferInfoMap.Rewind(); fBufferInfoMap.GetNext(&info); ) {
BufferInfoMap::Iterator iterator = fBufferInfoMap.GetIterator();
while (iterator.HasNext()) {
buffer_info& info = *iterator.NextValue();
printf(" buffer-id %ld, area-id %ld, offset %ld, size %ld, flags "
"%#08lx\n", info->id, info->area, info->offset, info->size,
info->flags);
"%#08lx\n", info.id, info.area, info.offset, info.size, info.flags);
printf(" assigned teams: ");
team_id* team;
for (info->teams.Rewind(); info->teams.GetNext(&team); ) {
printf("%ld, ", *team);
std::set<team_id>::iterator teamIterator = info.teams.begin();
for (; teamIterator != info.teams.end(); teamIterator++) {
printf("%ld, ", *teamIterator);
}
printf("\n");
}
printf("BufferManager: list end\n");
}
area_id
BufferManager::_CloneArea(area_id area)
{
void* address;
area_id clonedArea = clone_area("media_server cloned buffer", &address,
B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area);
return clonedArea;
}
void
BufferManager::_ReleaseClonedArea(area_id clone)
{
delete_area(clone);
}
+64 -10
View File
@@ -1,14 +1,16 @@
/*
* Copyright 2002, Marcus Overhagen. All rights reserved.
* Copyright 2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <set>
#include <Locker.h>
#include <MediaDefs.h>
#include <TMap.h>
#include <TList.h>
#include <HashMap.h>
struct _shared_buffer_list;
@@ -37,19 +39,71 @@ public:
void Dump();
private:
struct buffer_info {
media_buffer_id id;
area_id area;
size_t offset;
size_t size;
int32 flags;
List<team_id> teams;
area_id _CloneArea(area_id area);
void _ReleaseClonedArea(area_id clone);
private:
struct clone_info {
area_id source;
area_id clone;
vint32 ref_count;
};
struct buffer_info {
media_buffer_id id;
area_id area;
size_t offset;
size_t size;
int32 flags;
std::set<team_id> teams;
};
template<typename Type> struct id_hash {
id_hash()
:
fID(0)
{
}
id_hash(Type id)
:
fID(id)
{
}
id_hash(const id_hash& other)
{
fID = other.fID;
}
uint32 GetHashCode() const
{
return fID;
}
operator Type() const
{
return fID;
}
id_hash& operator=(const id_hash& other)
{
fID = other.fID;
return *this;
}
private:
Type fID;
};
typedef HashMap<id_hash<media_buffer_id>, buffer_info> BufferInfoMap;
typedef HashMap<id_hash<area_id>, clone_info> CloneInfoMap;
_shared_buffer_list* fSharedBufferList;
area_id fSharedBufferListID;
media_buffer_id fNextBufferID;
BLocker fLocker;
Map<media_buffer_id, buffer_info> fBufferInfoMap;
BufferInfoMap fBufferInfoMap;
CloneInfoMap fCloneInfoMap;
};