diff --git a/src/vault/mem/local-buffer-store.hpp b/src/vault/mem/local-buffer-store.hpp
index df842973f..9c351ebea 100644
--- a/src/vault/mem/local-buffer-store.hpp
+++ b/src/vault/mem/local-buffer-store.hpp
@@ -42,6 +42,31 @@ namespace mem {
class LocalBufferStore
: public BufferProviderSetup::Store
{
+ struct SetupPool;
+ using LocalPool = lib::LocalSlice;
+ using GlobalPool = lib::Depend;
+
+ struct SetupPool
+ {
+ using Service = LocalMemPool;
+
+ static LocalMemPool
+ init()
+ {
+ return LocalMemPool{[](LocalMemPool& pool2close)
+ {
+ pool2close.purge([](Buff* mem, size_t siz)
+ {
+ Alloc alloc{mem,siz};
+ GlobalPool globalPool;
+ globalPool().supply(alloc);
+ });
+ }};
+ }
+ };
+
+ LocalPool localReg_;
+ GlobalPool globalReg_;
public:
LocalBufferStore()
diff --git a/src/vault/mem/local-mem-pool.hpp b/src/vault/mem/local-mem-pool.hpp
index a147f0b91..36dde72f8 100644
--- a/src/vault/mem/local-mem-pool.hpp
+++ b/src/vault/mem/local-mem-pool.hpp
@@ -77,6 +77,7 @@
#include "vault/mem/engine-buffer-manager.hpp"
#include "lib/util.hpp"
+#include
#include
#include
#include
@@ -98,6 +99,7 @@ namespace mem {
using std::move;
using std::forward;
+ using std::invocable;
using util::unConst;
using util::isLimited;
@@ -123,7 +125,8 @@ namespace mem {
*/
class LocalMemPool
: public AllocReceiver
- {
+ { // NonCopyable
+
struct Block
{
Alloc alloc{nullptr,0};
@@ -143,11 +146,29 @@ namespace mem {
int32_t maxScore_{1};
+ std::function shutdownHook_{};
+
public:
LocalMemPool()
: AllocReceiver{}
, blocks_{}
{ }
+ // NonCopyable
+
+ template FUN>
+ explicit
+ LocalMemPool (FUN&& onShutdown)
+ : AllocReceiver{}
+ , blocks_{}
+ , shutdownHook_{forward (onShutdown)}
+ { }
+
+ ~LocalMemPool()
+ {
+ if (shutdownHook_)
+ shutdownHook_(*this);
+ }
+
/* ===== Pool Access API ===== */
@@ -283,7 +304,7 @@ namespace mem {
* @param siz precise size of the memory block(s) to yield
* @return actual number of allocations removed from the pool.
*/
- template ////////TODO requires std::invocable
+ template FUN>
uint
yield (uint cnt, size_t siz, FUN&& consumer)
{
@@ -317,7 +338,7 @@ namespace mem {
* \a degree ≡ 0.5 retains all matches that were frequently successful.
* @return actual number of allocations removed from the pool.
*/
- template ////////TODO requires std::invocable
+ template FUN>
uint
cleanup (double degree, FUN&& consumer)
{
@@ -345,6 +366,23 @@ namespace mem {
return removed;
}
+ /** unconditionally dispose of the pool's entire contents.
+ * @warning there must not be any allocations in use when invoking this function
+ */
+ template FUN>
+ uint
+ purge (FUN&& consumer)
+ {
+ ingest();
+ ///////////////////////////////////////OOO need a way to »lock down« the inqueue at that point
+ for (Block& block : blocks_)
+ {
+ REQUIRE (not block.used);
+ consumer (block.alloc.mem, block.alloc.siz);
+ blocks_.clear();
+ }
+ ENSURE (this->empty());
+ }
private:
void
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 6dff95641..3936a6399 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -144403,7 +144403,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
-
+
@@ -144413,6 +144413,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
+
+
+
@@ -144995,6 +144998,72 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
+
+
+
+
+
+
+
+
+ ...weil es ja durch das Ende eines Thread verursacht wird, wodurch ein thread-local Subobjekt out of scope geht.
+
+
+
+
+
+
+
+
+
+
+
+
+ ...ich hatte bereits über die Konfiguration nachgedacht, und dann für LocalSlice ein policy-based-design verwendet, allerdings in einer Form so daß es weiterhin default-constructible bleibt. Leider kann ich hier den Shutdown / clean-Up nicht einfach anbauen, da LocalSlice davon garnichts merkt.
+
+
+
+
+
+
+
+
+
+
+
+ eine Verdrahtung auf das managing Object ist nur indirekt (trickreich) möglich
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ...denn ich muß irgendwie einen clean-up-Hook in jede Instanz installieren, sofern ich LocalMemPool weiterhin von der sonstigen Implementierung entkoppelt haben möchte. Das bedingt dann entweder, einen Template-Parameter einzuführen, oder std::function mit einer Konstruktor-Variante. Letzteres erscheint attraktiv, da es diesen Sachverhalt etwas »unter den Teppich kehrt« und eigentlich erst auffällt, wenn man das PROD-Setup für die Engine sieht...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -145026,8 +145095,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
Es müßt nach jeder de-Allokation die ganze Blockliste gescannt werden, wobei erwartungsgemäß nach den meisten Scans nichts zur Freigabe gefunden wird
-
-
+
@@ -145769,8 +145837,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
-
-
+
+
@@ -146843,8 +146911,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
-
-
+
+
@@ -146902,7 +146970,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)