mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-07 03:13:49 +00:00
Throw an exception if a buffer greater than the ring buffer pool max size is allocated instead of dead locking forever.
This commit is contained in:
parent
f918a909c7
commit
9c4653a148
|
@ -1,6 +1,8 @@
|
||||||
#include "RingBufferPool.h"
|
#include "RingBufferPool.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
#include <Log.h>
|
||||||
|
|
||||||
namespace opengl {
|
namespace opengl {
|
||||||
|
|
||||||
|
@ -50,10 +52,11 @@ size_t PoolBufferPointer::getSize() const
|
||||||
}
|
}
|
||||||
|
|
||||||
RingBufferPool::RingBufferPool(size_t _poolSize) :
|
RingBufferPool::RingBufferPool(size_t _poolSize) :
|
||||||
m_poolBuffer(_poolSize, 0),
|
m_poolBuffer(m_startBufferPoolSize, 0),
|
||||||
m_inUseStartOffset(0),
|
m_inUseStartOffset(0),
|
||||||
m_inUseEndOffset(0),
|
m_inUseEndOffset(0),
|
||||||
m_full(false)
|
m_full(false),
|
||||||
|
m_maxBufferPoolSize(_poolSize)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,14 +64,14 @@ RingBufferPool::RingBufferPool(size_t _poolSize) :
|
||||||
PoolBufferPointer RingBufferPool::createPoolBuffer(const char* _buffer, size_t _bufferSize)
|
PoolBufferPointer RingBufferPool::createPoolBuffer(const char* _buffer, size_t _bufferSize)
|
||||||
{
|
{
|
||||||
size_t realBufferSize = _bufferSize;
|
size_t realBufferSize = _bufferSize;
|
||||||
size_t remainder = _bufferSize % 4;
|
const size_t remainder = _bufferSize % 4;
|
||||||
|
|
||||||
if (remainder != 0)
|
if (remainder != 0)
|
||||||
realBufferSize = _bufferSize + 4 - remainder;
|
realBufferSize = _bufferSize + 4 - remainder;
|
||||||
|
|
||||||
size_t tempInUseStart = m_inUseStartOffset;
|
const size_t tempInUseStart = m_inUseStartOffset;
|
||||||
|
|
||||||
size_t remaining = tempInUseStart > m_inUseEndOffset || m_full ?
|
const size_t remaining = tempInUseStart > m_inUseEndOffset || m_full ?
|
||||||
static_cast<size_t>(tempInUseStart - m_inUseEndOffset) :
|
static_cast<size_t>(tempInUseStart - m_inUseEndOffset) :
|
||||||
m_poolBuffer.size() - m_inUseEndOffset + tempInUseStart;
|
m_poolBuffer.size() - m_inUseEndOffset + tempInUseStart;
|
||||||
|
|
||||||
|
@ -91,7 +94,7 @@ PoolBufferPointer RingBufferPool::createPoolBuffer(const char* _buffer, size_t _
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
m_condition.wait(lock, [this, realBufferSize] {
|
m_condition.wait(lock, [this, realBufferSize] {
|
||||||
size_t tempInUseStartLocal = m_inUseStartOffset;
|
const size_t tempInUseStartLocal = m_inUseStartOffset;
|
||||||
return realBufferSize < tempInUseStartLocal ||
|
return realBufferSize < tempInUseStartLocal ||
|
||||||
tempInUseStartLocal == m_inUseEndOffset;
|
tempInUseStartLocal == m_inUseEndOffset;
|
||||||
});
|
});
|
||||||
|
@ -105,14 +108,28 @@ PoolBufferPointer RingBufferPool::createPoolBuffer(const char* _buffer, size_t _
|
||||||
} else {
|
} else {
|
||||||
// Wait until enough space is avalable
|
// Wait until enough space is avalable
|
||||||
{
|
{
|
||||||
|
if (realBufferSize > m_maxBufferPoolSize) {
|
||||||
|
std::stringstream errorString;
|
||||||
|
errorString << " Attempted to create buffer of invalid size, size=" << realBufferSize << ", max_size=" << m_maxBufferPoolSize;
|
||||||
|
LOG(LOG_ERROR, errorString.str().c_str());
|
||||||
|
throw std::runtime_error(errorString.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
if (m_poolBuffer.size() < realBufferSize) {
|
||||||
|
std::stringstream errorString;
|
||||||
|
errorString << " Increasing buffer size from " << m_poolBuffer.size() << " to " << realBufferSize;
|
||||||
|
LOG(LOG_VERBOSE, errorString.str().c_str());
|
||||||
|
|
||||||
|
m_poolBuffer.resize(realBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
m_condition.wait(lock, [this, realBufferSize] {
|
m_condition.wait(lock, [this, realBufferSize] {
|
||||||
size_t tempInUseStartLocal = m_inUseStartOffset;
|
const size_t tempInUseStartLocal = m_inUseStartOffset;
|
||||||
size_t remainingLocal =
|
const size_t remainingLocal =
|
||||||
tempInUseStartLocal > m_inUseEndOffset || m_full ? static_cast<size_t>(
|
tempInUseStartLocal > m_inUseEndOffset || m_full ? static_cast<size_t>(
|
||||||
tempInUseStartLocal - m_inUseEndOffset) :
|
tempInUseStartLocal - m_inUseEndOffset) :
|
||||||
m_poolBuffer.size() - m_inUseEndOffset + tempInUseStartLocal;
|
m_poolBuffer.size() - m_inUseEndOffset + tempInUseStartLocal;
|
||||||
|
|
||||||
return remainingLocal >= realBufferSize;
|
return remainingLocal >= realBufferSize;
|
||||||
});
|
});
|
||||||
|
@ -133,6 +150,7 @@ const char* RingBufferPool::getBufferFromPool(PoolBufferPointer _poolBufferPoint
|
||||||
if (!_poolBufferPointer.isValid()) {
|
if (!_poolBufferPointer.isValid()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
return m_poolBuffer.data() + _poolBufferPointer.m_offset;
|
return m_poolBuffer.data() + _poolBufferPointer.m_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,17 @@ public:
|
||||||
|
|
||||||
explicit RingBufferPool(size_t _poolSize);
|
explicit RingBufferPool(size_t _poolSize);
|
||||||
|
|
||||||
|
// Create a buffer pool. This method will block if there is not enough space until
|
||||||
|
// enough space has been freed from a seperate thread. If a buffer bigger than the
|
||||||
|
// maximum is allocated, then a run time exception will be thrown
|
||||||
PoolBufferPointer createPoolBuffer(const char* _buffer, size_t _bufferSize);
|
PoolBufferPointer createPoolBuffer(const char* _buffer, size_t _bufferSize);
|
||||||
|
|
||||||
|
// Retrieves a buffer from the buffer pool, will return a nullptr if an invalid
|
||||||
|
// buffer is provided
|
||||||
const char* getBufferFromPool(PoolBufferPointer _poolBufferPointer);
|
const char* getBufferFromPool(PoolBufferPointer _poolBufferPointer);
|
||||||
|
|
||||||
|
// Removes the give buffer from the pool, no action will be taken if the provided
|
||||||
|
// buffer is not valid
|
||||||
void removeBufferFromPool(PoolBufferPointer _poolBufferPointer);
|
void removeBufferFromPool(PoolBufferPointer _poolBufferPointer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -47,6 +54,8 @@ private:
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
std::atomic<bool> m_full;
|
std::atomic<bool> m_full;
|
||||||
std::condition_variable_any m_condition;
|
std::condition_variable_any m_condition;
|
||||||
|
size_t m_maxBufferPoolSize;
|
||||||
|
static const size_t m_startBufferPoolSize = 1024 * 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
namespace opengl {
|
namespace opengl {
|
||||||
|
|
||||||
// 15MB memory pool
|
// Max memory pool size
|
||||||
RingBufferPool OpenGlCommand::m_ringBufferPool(1024 * 1024 * 15 );
|
RingBufferPool OpenGlCommand::m_ringBufferPool(1024 * 1024 * 200 );
|
||||||
|
|
||||||
void OpenGlCommand::performCommandSingleThreaded()
|
void OpenGlCommand::performCommandSingleThreaded()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user