-
-
Notifications
You must be signed in to change notification settings - Fork 216
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gh-610 Added MemoryLimiter and other classes etc
- Loading branch information
1 parent
4015b01
commit 68a5da3
Showing
22 changed files
with
658 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* Copyright (c) 2023 Roc Streaming authors | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
|
||
#include "roc_core/limited_arena.h" | ||
|
||
namespace roc { | ||
namespace core { | ||
|
||
LimitedArena::LimitedArena(IArena& arena, MemoryLimiter& memory_limiter) | ||
: arena_(arena) | ||
, memory_limiter_(memory_limiter) { | ||
} | ||
|
||
void* LimitedArena::allocate(size_t size) { | ||
size_t allocated_size = arena_.compute_allocated_size(size); | ||
if (memory_limiter_.acquire(allocated_size)) { | ||
void* ptr = arena_.allocate(size); | ||
if (!ptr) | ||
memory_limiter_.release(allocated_size); | ||
return ptr; | ||
} | ||
return NULL; | ||
} | ||
|
||
void LimitedArena::deallocate(void* ptr) { | ||
size_t allocated_size = arena_.allocated_size(ptr); | ||
arena_.deallocate(ptr); | ||
memory_limiter_.release(allocated_size); | ||
} | ||
|
||
size_t LimitedArena::compute_allocated_size(size_t size) const { | ||
return arena_.compute_allocated_size(size); | ||
} | ||
|
||
size_t LimitedArena::allocated_size(void* ptr) const { | ||
return arena_.allocated_size(ptr); | ||
} | ||
|
||
} // namespace core | ||
} // namespace roc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright (c) 2023 Roc Streaming authors | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
|
||
//! @file roc_core/limited_arena.h | ||
//! @brief Limited Arena. | ||
|
||
#ifndef ROC_CORE_LIMITED_ARENA_H_ | ||
#define ROC_CORE_LIMITED_ARENA_H_ | ||
|
||
#include "roc_core/iarena.h" | ||
#include "roc_core/memory_limiter.h" | ||
#include "roc_core/noncopyable.h" | ||
|
||
namespace roc { | ||
namespace core { | ||
|
||
//! Decorator around IArena to make it memory limited. | ||
class LimitedArena : public NonCopyable<>, public IArena { | ||
public: | ||
//! Initialize. | ||
LimitedArena(IArena& arena, MemoryLimiter& memory_limiter); | ||
|
||
//! Allocate memory after checking with the memory limiter. | ||
//! @returns | ||
//! pointer to a maximum aligned uninitialized memory at least of @p size | ||
//! bytes or NULL if memory can't be allocated. | ||
virtual void* allocate(size_t size); | ||
|
||
//! Deallocate previously allocated memory. | ||
virtual void deallocate(void* ptr); | ||
|
||
//! Computes how many bytes will be actually allocated if allocate() is called with | ||
//! given size. Covers all internal overhead, if any. | ||
virtual size_t compute_allocated_size(size_t size) const; | ||
|
||
//! Returns how many bytes was allocated for given pointer returned by allocate(). | ||
//! Covers all internal overhead, if any. | ||
//! Returns same value as computed by compute_allocated_size(size). | ||
virtual size_t allocated_size(void* ptr) const; | ||
|
||
private: | ||
IArena& arena_; | ||
MemoryLimiter& memory_limiter_; | ||
}; | ||
|
||
} // namespace core | ||
} // namespace roc | ||
|
||
#endif // ROC_CORE_LIMITED_ARENA_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* Copyright (c) 2023 Roc Streaming authors | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
|
||
#include "roc_core/limited_pool.h" | ||
|
||
namespace roc { | ||
namespace core { | ||
|
||
LimitedPool::LimitedPool(IPool& pool, MemoryLimiter& memory_limiter) | ||
: pool_(pool) | ||
, memory_limiter_(memory_limiter) { | ||
} | ||
|
||
size_t LimitedPool::allocation_size() const { | ||
return pool_.allocation_size(); | ||
} | ||
|
||
ROC_ATTR_NODISCARD bool LimitedPool::reserve(size_t n_objects) { | ||
return pool_.reserve(n_objects); | ||
} | ||
|
||
void* LimitedPool::allocate() { | ||
size_t allocation_size = pool_.allocation_size(); | ||
if (memory_limiter_.acquire(allocation_size)) { | ||
void* ptr = pool_.allocate(); | ||
if (!ptr) | ||
memory_limiter_.release(allocation_size); | ||
return ptr; | ||
} | ||
return NULL; | ||
} | ||
|
||
void LimitedPool::deallocate(void* memory) { | ||
pool_.deallocate(memory); | ||
memory_limiter_.release(pool_.allocation_size()); | ||
} | ||
|
||
} // namespace core | ||
} // namespace roc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* Copyright (c) 2023 Roc Streaming authors | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
|
||
//! @file roc_core/limited_pool.h | ||
//! @brief Limited Pool. | ||
|
||
#ifndef ROC_CORE_LIMITED_POOL_H_ | ||
#define ROC_CORE_LIMITED_POOL_H_ | ||
|
||
#include "roc_core/ipool.h" | ||
#include "roc_core/memory_limiter.h" | ||
#include "roc_core/noncopyable.h" | ||
|
||
namespace roc { | ||
namespace core { | ||
|
||
//! Decorator around IPool to make it memory limited. | ||
class LimitedPool : public NonCopyable<LimitedPool>, public IPool { | ||
public: | ||
//! Initialize. | ||
LimitedPool(IPool& pool, MemoryLimiter& memory_limiter); | ||
|
||
//! Get size of the allocation per object. | ||
size_t allocation_size() const; | ||
|
||
//! Reserve memory for given number of objects. | ||
//! @returns | ||
//! false if allocation failed. | ||
ROC_ATTR_NODISCARD bool reserve(size_t n_objects); | ||
|
||
//! Allocate memory for an object, after checking with the memory limiter. | ||
//! @returns | ||
//! pointer to a maximum aligned uninitialized memory for a new object | ||
//! or NULL if memory can't be allocated. | ||
void* allocate(); | ||
|
||
//! Return memory to pool, then update the memory limiter. | ||
void deallocate(void* memory); | ||
|
||
private: | ||
IPool& pool_; | ||
MemoryLimiter& memory_limiter_; | ||
}; | ||
|
||
} // namespace core | ||
} // namespace roc | ||
|
||
#endif // ROC_CORE_LIMITED_POOL_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
* Copyright (c) 2023 Roc Streaming authors | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
|
||
#include "roc_core/memory_limiter.h" | ||
|
||
#include "roc_core/cpu_instructions.h" | ||
#include "roc_core/log.h" | ||
|
||
namespace roc { | ||
namespace core { | ||
|
||
MemoryLimiter::MemoryLimiter(const char* name, size_t max_bytes) | ||
: name_(name) | ||
, max_bytes_(max_bytes) | ||
, bytes_acquired_(0) { | ||
} | ||
|
||
MemoryLimiter::~MemoryLimiter() { | ||
if (bytes_acquired_ > 0) { | ||
roc_panic("memory limiter (%s): detected that memory has not been released: " | ||
"acquired=%lu", | ||
name_, (unsigned long)bytes_acquired_); | ||
} | ||
} | ||
|
||
bool MemoryLimiter::acquire(size_t num_bytes) { | ||
if (num_bytes == 0) { | ||
roc_panic("memory limiter (%s): tried to acquire zero bytes", name_); | ||
} | ||
size_t current; | ||
do { | ||
current = bytes_acquired_; | ||
size_t next = current + num_bytes; | ||
if (max_bytes_ > 0 && next > max_bytes_) { | ||
break; | ||
} | ||
if (bytes_acquired_.compare_exchange(current, next)) { | ||
return true; | ||
} | ||
cpu_relax(); | ||
} while (true); | ||
roc_log(LogError, | ||
"memory limiter (%s): could not acquire bytes due to limit: requested=%lu " | ||
"acquired=%lu limit=%lu", | ||
name_, (unsigned long)num_bytes, (unsigned long)current, | ||
(unsigned long)max_bytes_); | ||
return false; | ||
} | ||
|
||
void MemoryLimiter::release(size_t num_bytes) { | ||
if (num_bytes == 0) { | ||
roc_panic("memory limiter (%s): tried to release zero bytes", name_); | ||
} | ||
size_t next = bytes_acquired_ -= num_bytes; | ||
size_t prev = next + num_bytes; | ||
if (next > prev) { | ||
roc_panic("memory limiter (%s): tried to release too many bytes: requested=%lu, " | ||
"acquired=%lu", | ||
name_, (unsigned long)num_bytes, (unsigned long)prev); | ||
} | ||
} | ||
|
||
size_t MemoryLimiter::num_acquired() { | ||
return bytes_acquired_; | ||
} | ||
|
||
} // namespace core | ||
} // namespace roc |
Oops, something went wrong.