diff --git a/headers/os/media/BufferGroup.h b/headers/os/media/BufferGroup.h index a45a794924..674b2767b5 100644 --- a/headers/os/media/BufferGroup.h +++ b/headers/os/media/BufferGroup.h @@ -1,82 +1,68 @@ -/******************************************************************************* -/ -/ File: BufferGroup.h -/ -/ Description: A BBufferGroup organizes sets of BBuffers so that you can request -/ and reclaim them. -/ -/ Copyright 1997-98, Be Incorporated, All Rights Reserved -/ -*******************************************************************************/ - -#if !defined(_BUFFER_GROUP_H) +/* + * Copyright 2009, Haiku Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _BUFFER_GROUP_H #define _BUFFER_GROUP_H + #include + class BBuffer; struct _shared_buffer_list; -class BBufferGroup -{ + +class BBufferGroup { public: + BBufferGroup(size_t size, int32 count = 3, + uint32 placement = B_ANY_ADDRESS, + uint32 lock = B_FULL_LOCK); + explicit BBufferGroup(); + BBufferGroup(int32 count, + const media_buffer_id* buffers); + ~BBufferGroup(); - BBufferGroup( - size_t size, - int32 count = 3, - uint32 placement = B_ANY_ADDRESS, - uint32 lock = B_FULL_LOCK); -explicit BBufferGroup(); - BBufferGroup( - int32 count, - const media_buffer_id * buffers); - ~BBufferGroup(); /* BBufferGroup is NOT a virtual class!!! */ + status_t InitCheck(); - status_t InitCheck(); + status_t AddBuffer(const buffer_clone_info& info, + BBuffer** _buffer = NULL); - /* use this function to add buffers you created on your own */ - status_t AddBuffer( - const buffer_clone_info & info, - BBuffer ** out_buffer = NULL); + BBuffer* RequestBuffer(size_t size, + bigtime_t timeout = B_INFINITE_TIMEOUT); + status_t RequestBuffer(BBuffer* buffer, + bigtime_t timeout = B_INFINITE_TIMEOUT); - BBuffer * RequestBuffer( - size_t size, - bigtime_t timeout = B_INFINITE_TIMEOUT); - status_t RequestBuffer( - BBuffer * buffer, - bigtime_t timeout = B_INFINITE_TIMEOUT); - status_t RequestError(); /* return last RequestBuffer error, useful if NULL is returned */ + status_t RequestError(); - status_t CountBuffers( - int32 * out_count); - status_t GetBufferList( - int32 buf_count, - BBuffer ** out_buffers); + status_t CountBuffers(int32* _count); + status_t GetBufferList(int32 bufferCount, + BBuffer** _buffers); - status_t WaitForBuffers(); - status_t ReclaimAllBuffers(); + status_t WaitForBuffers(); + status_t ReclaimAllBuffers(); private: - /* in BeOS R5 this is a deprecated api, from BeOS R4 times */ - status_t AddBuffersTo(BMessage * message, const char * name, bool needLock=true); - - status_t InitBufferGroup(); /* used internally */ - BBufferGroup(const BBufferGroup &); /* not implemented */ - BBufferGroup& operator=(const BBufferGroup&); /* not implemented */ + // deprecated BeOS R4 API + status_t AddBuffersTo(BMessage* message, const char* name, + bool needLock); - friend struct _shared_buffer_list; + BBufferGroup(const BBufferGroup& other); + BBufferGroup& operator=(const BBufferGroup& other); - status_t fInitError; - status_t fRequestError; - int32 fBufferCount; - _shared_buffer_list * fBufferList; - - // this is a BBufferGroup specific semaphore used for reclaiming BBuffers of this group - // is also is a system wide unique identifier of this group - sem_id fReclaimSem; + status_t _Init(); - uint32 _reserved_buffer_group_[9]; +private: + friend struct _shared_buffer_list; + + status_t fInitError; + status_t fRequestError; + int32 fBufferCount; + _shared_buffer_list* fBufferList; + sem_id fReclaimSem; + + uint32 _reserved[9]; }; -#endif /* _BUFFER_GROUP_H */ +#endif // _BUFFER_GROUP_H diff --git a/src/kits/media/BufferGroup.cpp b/src/kits/media/BufferGroup.cpp index 6ccd8721b3..cc2618e7e1 100644 --- a/src/kits/media/BufferGroup.cpp +++ b/src/kits/media/BufferGroup.cpp @@ -27,69 +27,21 @@ * */ + #include + #include + #include "debug.h" -#include "SharedBufferList.h" #include "DataExchange.h" +#include "SharedBufferList.h" -/************************************************************* - * private BBufferGroup - *************************************************************/ -status_t -BBufferGroup::InitBufferGroup() +BBufferGroup::BBufferGroup(size_t size, int32 count, uint32 placement, + uint32 lock) { CALLED(); - - // some defaults - fBufferList = 0; - fReclaimSem = B_ERROR; - fInitError = B_ERROR; - fRequestError = B_ERROR; - fBufferCount = 0; - - // create the reclaim semaphore - fReclaimSem = create_sem(0,"buffer reclaim sem"); - if (fReclaimSem < B_OK) { - ERROR("BBufferGroup::InitBufferGroup: couldn't create fReclaimSem\n"); - fInitError = (status_t)fReclaimSem; - return fInitError; - } - - // ask media_server to get the area_id of the shared buffer list - server_get_shared_buffer_area_request area_request; - server_get_shared_buffer_area_reply area_reply; - if (QueryServer(SERVER_GET_SHARED_BUFFER_AREA, &area_request, sizeof(area_request), &area_reply, sizeof(area_reply)) != B_OK) { - ERROR("BBufferGroup::InitBufferGroup: SERVER_GET_SHARED_BUFFER_AREA failed\n"); - fInitError = B_ERROR; - return fInitError; - } - ASSERT(area_reply.area > 0); - - fBufferList = _shared_buffer_list::Clone(area_reply.area); - if (fBufferList == NULL) { - ERROR("BBufferGroup::InitBufferGroup: _shared_buffer_list::Clone failed\n"); - fInitError = B_ERROR; - return fInitError; - } - - fInitError = B_OK; - return fInitError; -} - - -/************************************************************* - * public BBufferGroup - *************************************************************/ - -BBufferGroup::BBufferGroup(size_t size, - int32 count, - uint32 placement, - uint32 lock) -{ - CALLED(); - if (InitBufferGroup() != B_OK) + if (_Init() != B_OK) return; // This one is easy. We need to create "count" BBuffers, @@ -99,99 +51,75 @@ BBufferGroup::BBufferGroup(size_t size, // then we delete our area. This way BBuffers are // independent from the BBufferGroup - void *start_addr; - area_id buffer_area; - size_t area_size; - buffer_clone_info bci; - BBuffer *buffer; - // don't allow all placement parameter values if (placement != B_ANY_ADDRESS && placement != B_ANY_KERNEL_ADDRESS) { - ERROR("BBufferGroup: placement != B_ANY_ADDRESS && placement != B_ANY_KERNEL_ADDRESS (0x%08lx)\n",placement); + ERROR("BBufferGroup: placement != B_ANY_ADDRESS " + "&& placement != B_ANY_KERNEL_ADDRESS (0x%08lx)\n", placement); placement = B_ANY_ADDRESS; } // first we roundup for a better placement in memory - int allocsize = (size + 63) & ~63; + size_t allocSize = (size + 63) & ~63; // now we create the area - area_size = ((allocsize * count) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1); + size_t areaSize + = ((allocSize * count) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); - buffer_area = create_area("some buffers area", &start_addr,placement,area_size,lock,B_READ_AREA | B_WRITE_AREA); - if (buffer_area < B_OK) { - ERROR("BBufferGroup: failed to allocate %ld bytes area\n",area_size); - fInitError = (status_t)buffer_area; + void* startAddress; + area_id bufferArea = create_area("some buffers area", &startAddress, + placement, areaSize, lock, B_READ_AREA | B_WRITE_AREA); + if (bufferArea < 0) { + ERROR("BBufferGroup: failed to allocate %ld bytes area\n", areaSize); + fInitError = (status_t)bufferArea; return; } - - fBufferCount = count; + + buffer_clone_info info; for (int32 i = 0; i < count; i++) { - bci.area = buffer_area; - bci.offset = i * allocsize; - bci.size = size; - buffer = new BBuffer(bci); - if (0 == buffer->Data()) { - // BBuffer::Data() will return 0 if an error occured - ERROR("BBufferGroup: error while creating buffer\n"); - delete buffer; - fInitError = B_ERROR; + info.area = bufferArea; + info.offset = i * allocSize; + info.size = size; + + fInitError = AddBuffer(info); + if (fInitError != B_OK) break; - } - if (B_OK != fBufferList->AddBuffer(fReclaimSem,buffer)) { - ERROR("BBufferGroup: error when adding buffer\n"); - delete buffer; - fInitError = B_ERROR; - break; - } } - delete_area(buffer_area); + delete_area(bufferArea); } -/* explicit */ + BBufferGroup::BBufferGroup() { CALLED(); - if (InitBufferGroup() != B_OK) + if (_Init() != B_OK) return; // this one simply creates an empty BBufferGroup } -BBufferGroup::BBufferGroup(int32 count, - const media_buffer_id *buffers) +BBufferGroup::BBufferGroup(int32 count, const media_buffer_id* buffers) { CALLED(); - if (InitBufferGroup() != B_OK) + if (_Init() != B_OK) return; - // XXX we need to make sure that a media_buffer_id is only added once to each group + // TODO: we need to make sure that a media_buffer_id is only added + // once to each group // this one creates "BBuffer"s from "media_buffer_id"s passed // by the application. - fBufferCount = count; + buffer_clone_info info; - buffer_clone_info bci; - BBuffer *buffer; for (int32 i = 0; i < count; i++) { - bci.buffer = buffers[i]; - buffer = new BBuffer(bci); - if (0 == buffer->Data()) { - // BBuffer::Data() will return 0 if an error occured - ERROR("BBufferGroup(2): error while creating buffer\n"); - delete buffer; - fInitError = B_ERROR; + info.buffer = buffers[i]; + + fInitError = AddBuffer(info); + if (fInitError != B_OK) break; - } - if (B_OK != fBufferList->AddBuffer(fReclaimSem,buffer)) { - ERROR("BBufferGroup(2): error when adding buffer\n"); - delete buffer; - fInitError = B_ERROR; - break; - } } } @@ -201,8 +129,8 @@ BBufferGroup::~BBufferGroup() CALLED(); if (fBufferList) fBufferList->Terminate(fReclaimSem); - if (fReclaimSem >= B_OK) - delete_sem(fReclaimSem); + + delete_sem(fReclaimSem); } @@ -215,41 +143,44 @@ BBufferGroup::InitCheck() status_t -BBufferGroup::AddBuffer(const buffer_clone_info &info, - BBuffer **out_buffer) +BBufferGroup::AddBuffer(const buffer_clone_info& info, BBuffer** _buffer) { CALLED(); if (fInitError != B_OK) return B_NO_INIT; - // XXX we need to make sure that a media_buffer_id is only added once to each group + // TODO: we need to make sure that a media_buffer_id is only added + // once to each group - BBuffer *buffer; - buffer = new BBuffer(info); - if (0 == buffer->Data()) { - // BBuffer::Data() will return 0 if an error occured - ERROR("BBufferGroup::AddBuffer: error while creating buffer\n"); + BBuffer* buffer = new(std::nothrow) BBuffer(info); + if (buffer == NULL) + return B_NO_MEMORY; + + if (buffer->Data() == NULL) { + // BBuffer::Data() will return NULL if an error occured + ERROR("BBufferGroup: error while creating buffer\n"); delete buffer; return B_ERROR; } - if (B_OK != fBufferList->AddBuffer(fReclaimSem,buffer)) { - ERROR("BBufferGroup::AddBuffer: error when adding buffer\n"); + + status_t status = fBufferList->AddBuffer(fReclaimSem, buffer); + if (status != B_OK) { + ERROR("BBufferGroup: error when adding buffer\n"); delete buffer; - fInitError = B_ERROR; - return B_ERROR; + return status; } - atomic_add(&fBufferCount,1); - - if (out_buffer != 0) - *out_buffer = buffer; + + atomic_add(&fBufferCount, 1); + + if (_buffer != NULL) + *_buffer = buffer; return B_OK; } -BBuffer * -BBufferGroup::RequestBuffer(size_t size, - bigtime_t timeout) +BBuffer* +BBufferGroup::RequestBuffer(size_t size, bigtime_t timeout) { CALLED(); if (fInitError != B_OK) @@ -262,16 +193,16 @@ BBufferGroup::RequestBuffer(size_t size, status_t status; buffer = NULL; - status = fBufferList->RequestBuffer(fReclaimSem, fBufferCount, size, 0, &buffer, timeout); + status = fBufferList->RequestBuffer(fReclaimSem, fBufferCount, size, 0, + &buffer, timeout); fRequestError = status; - - return (status == B_OK) ? buffer : NULL; + + return status == B_OK ? buffer : NULL; } status_t -BBufferGroup::RequestBuffer(BBuffer *buffer, - bigtime_t timeout) +BBufferGroup::RequestBuffer(BBuffer* buffer, bigtime_t timeout) { CALLED(); if (fInitError != B_OK) @@ -281,7 +212,8 @@ BBufferGroup::RequestBuffer(BBuffer *buffer, return B_BAD_VALUE; status_t status; - status = fBufferList->RequestBuffer(fReclaimSem, fBufferCount, 0, 0, &buffer, timeout); + status = fBufferList->RequestBuffer(fReclaimSem, fBufferCount, 0, 0, + &buffer, timeout); fRequestError = status; return status; @@ -300,29 +232,28 @@ BBufferGroup::RequestError() status_t -BBufferGroup::CountBuffers(int32 *out_count) +BBufferGroup::CountBuffers(int32* _count) { CALLED(); if (fInitError != B_OK) return B_NO_INIT; - *out_count = fBufferCount; + *_count = fBufferCount; return B_OK; } status_t -BBufferGroup::GetBufferList(int32 buf_count, - BBuffer **out_buffers) +BBufferGroup::GetBufferList(int32 bufferCount, BBuffer** _buffers) { CALLED(); if (fInitError != B_OK) return B_NO_INIT; - if (buf_count <= 0 || buf_count > fBufferCount) + if (bufferCount <= 0 || bufferCount > fBufferCount) return B_BAD_VALUE; - return fBufferList->GetBufferList(fReclaimSem,buf_count,out_buffers); + return fBufferList->GetBufferList(fReclaimSem, bufferCount, _buffers); } @@ -333,25 +264,26 @@ BBufferGroup::WaitForBuffers() if (fInitError != B_OK) return B_NO_INIT; - // XXX this function is not really useful anyway, and will - // XXX not work exactly as documented, but it is close enough + // TODO: this function is not really useful anyway, and will + // not work exactly as documented, but it is close enough if (fBufferCount < 0) return B_BAD_VALUE; if (fBufferCount == 0) return B_OK; - // we need to wait until at least one buffer belonging to this group is reclaimed. - // this has happened when can aquire "fReclaimSem" + // We need to wait until at least one buffer belonging to this group is + // reclaimed. + // This has happened when can aquire "fReclaimSem" status_t status; - while (B_INTERRUPTED == (status = acquire_sem(fReclaimSem))) + while ((status = acquire_sem(fReclaimSem)) == B_INTERRUPTED) ; - - if (status != B_OK) // some error happened + if (status != B_OK) return status; - // we need to release the "fReclaimSem" now, else we would block requesting of new buffers + // we need to release the "fReclaimSem" now, else we would block + // requesting of new buffers return release_sem(fReclaimSem); } @@ -364,7 +296,8 @@ BBufferGroup::ReclaimAllBuffers() if (fInitError != B_OK) return B_NO_INIT; - // because additional BBuffers might get added to this group betweeen acquire and release + // because additional BBuffers might get added to this group betweeen + // acquire and release int32 count = fBufferCount; if (count < 0) @@ -373,32 +306,29 @@ BBufferGroup::ReclaimAllBuffers() return B_OK; // we need to wait until all BBuffers belonging to this group are reclaimed. - // this has happened when the "fReclaimSem" can be aquired "fBufferCount" times + // this has happened when the "fReclaimSem" can be aquired "fBufferCount" + // times status_t status; - while (B_INTERRUPTED == (status = acquire_sem_etc(fReclaimSem, count, 0, 0))) - ; + do { + status = acquire_sem_etc(fReclaimSem, count, 0, 0); + } while (status == B_INTERRUPTED); - if (status != B_OK) // some error happened + if (status != B_OK) return status; - // we need to release the "fReclaimSem" now, else we would block requesting of new buffers + // we need to release the "fReclaimSem" now, else we would block + // requesting of new buffers return release_sem_etc(fReclaimSem, count, 0); } -/************************************************************* - * private BBufferGroup - *************************************************************/ -/* not implemented */ -/* -BBufferGroup::BBufferGroup(const BBufferGroup &) -BBufferGroup & BBufferGroup::operator=(const BBufferGroup &) -*/ +// #pragma mark - deprecated BeOS R4 API + status_t -BBufferGroup::AddBuffersTo(BMessage * message, const char * name, bool needLock) +BBufferGroup::AddBuffersTo(BMessage* message, const char* name, bool needLock) { CALLED(); if (fInitError != B_OK) @@ -413,22 +343,76 @@ BBufferGroup::AddBuffersTo(BMessage * message, const char * name, bool needLock) if (name == NULL || strlen(name) == 0) return B_BAD_VALUE; - BBuffer ** buffers; - status_t status; + BBuffer** buffers; int32 count; count = fBufferCount; buffers = new BBuffer * [count]; - - if (B_OK != (status = GetBufferList(count,buffers))) + + status_t status = GetBufferList(count, buffers); + if (status != B_OK) goto end; - for (int32 i = 0; i < count; i++) - if (B_OK != (status = message->AddInt32(name,int32(buffers[i]->ID())))) + for (int32 i = 0; i < count; i++) { + status = message->AddInt32(name, int32(buffers[i]->ID())); + if (status != B_OK) goto end; - + } + end: delete [] buffers; return status; } + +// #pragma mark - private methods + + +/* not implemented */ +//BBufferGroup::BBufferGroup(const BBufferGroup &) +//BBufferGroup & BBufferGroup::operator=(const BBufferGroup &) + + +status_t +BBufferGroup::_Init() +{ + CALLED(); + + // some defaults in case we drop out early + fBufferList = 0; + fInitError = B_ERROR; + fRequestError = B_ERROR; + fBufferCount = 0; + + // Create the reclaim semaphore + // This is also used as a system wide unique identifier for this group + fReclaimSem = create_sem(0, "buffer reclaim sem"); + if (fReclaimSem < B_OK) { + ERROR("BBufferGroup::InitBufferGroup: couldn't create fReclaimSem\n"); + fInitError = (status_t)fReclaimSem; + return fInitError; + } + + // ask media_server to get the area_id of the shared buffer list + server_get_shared_buffer_area_request areaRequest; + server_get_shared_buffer_area_reply areaReply; + if (QueryServer(SERVER_GET_SHARED_BUFFER_AREA, &areaRequest, + sizeof(areaRequest), &areaReply, sizeof(areaReply)) != B_OK) { + ERROR("BBufferGroup::InitBufferGroup: SERVER_GET_SHARED_BUFFER_AREA " + "failed\n"); + fInitError = B_ERROR; + return fInitError; + } + + fBufferList = _shared_buffer_list::Clone(areaReply.area); + if (fBufferList == NULL) { + ERROR("BBufferGroup::InitBufferGroup: _shared_buffer_list::Clone " + "failed\n"); + fInitError = B_ERROR; + return fInitError; + } + + fInitError = B_OK; + return fInitError; +} +