From 5092279ce951f1f55bcb296e330f81b438fc5d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Wed, 14 Feb 2024 14:10:33 +0100 Subject: [PATCH] Deprecate vibe.internal.array.FixedRingBuffer. --- dub.sdl | 2 +- source/vibe/core/channel.d | 72 +++++++++++++++++++++++++++++++++++- source/vibe/core/core.d | 6 +-- source/vibe/core/taskpool.d | 8 ++-- source/vibe/internal/array.d | 5 ++- 5 files changed, 81 insertions(+), 12 deletions(-) diff --git a/dub.sdl b/dub.sdl index e8c1cfd9..96c81972 100644 --- a/dub.sdl +++ b/dub.sdl @@ -5,7 +5,7 @@ copyright "Copyright © 2016-2020, Sönke Ludwig" license "MIT" dependency "eventcore" version="~>0.9.27" -dependency "vibe-container" version=">=1.0.2 <2.0.0-0" +dependency "vibe-container" version=">=1.1.0 <2.0.0-0" targetName "vibe_core" diff --git a/source/vibe/core/channel.d b/source/vibe/core/channel.d index 0ee29e49..c3551368 100644 --- a/source/vibe/core/channel.d +++ b/source/vibe/core/channel.d @@ -6,6 +6,7 @@ */ module vibe.core.channel; +import vibe.container.ringbuffer : RingBuffer; import vibe.core.sync : TaskCondition; import vibe.internal.array : FixedRingBuffer; @@ -135,10 +136,20 @@ struct Channel(T, size_t buffer_size = 100) { If the `empty` property is or becomes `true` before data becomes avaiable, `dst` will be left untouched and `false` is returned. */ + bool consumeAll(ref RingBuffer!(T, buffer_size) dst) + in { assert(dst.empty); } + do { return m_impl.consumeAll(dst); } + /// ditto + bool consumeAll(ref RingBuffer!(T, buffer_size) dst) shared + in { assert(dst.empty); } + do { return m_impl.consumeAll(dst); } + /// ditto + deprecated("Pass a reference to `vibe.container.ringbuffer.RingBuffer` instead.") bool consumeAll(ref FixedRingBuffer!(T, buffer_size) dst) in { assert(dst.empty); } do { return m_impl.consumeAll(dst); } /// ditto + deprecated("Pass a reference to `vibe.container.ringbuffer.RingBuffer` instead.") bool consumeAll(ref FixedRingBuffer!(T, buffer_size) dst) shared in { assert(dst.empty); } do { return m_impl.consumeAll(dst); } @@ -161,7 +172,7 @@ private final class ChannelImpl(T, size_t buffer_size) { private { Mutex m_mutex; TaskCondition m_condition; - FixedRingBuffer!(T, buffer_size) m_items; + RingBuffer!(T, buffer_size) m_items; bool m_closed = false; ChannelConfig m_config; int m_refCount = 1; @@ -260,7 +271,7 @@ private final class ChannelImpl(T, size_t buffer_size) { need_notify = thisus.m_items.full; move(thisus.m_items.front, dst); - thisus.m_items.popFront(); + thisus.m_items.removeFront(); if (m_config.priority == ChannelPriority.overhead) need_notify = thisus.m_items.empty; @@ -284,7 +295,19 @@ private final class ChannelImpl(T, size_t buffer_size) { return ret; } + deprecated bool consumeAll(ref FixedRingBuffer!(T, buffer_size) dst) + shared nothrow { + RingBuffer!(T, buffer_size) tmp; + if (!consumeAll(tmp)) + return false; + dst.clear(); + foreach (ref el; tmp[]) + dst.put(el.move); + return true; + } + + bool consumeAll(ref RingBuffer!(T, buffer_size) dst) shared nothrow { auto thisus = () @trusted { return cast(ChannelImpl)this; } (); bool need_notify = false; @@ -371,6 +394,31 @@ deprecated @safe unittest { // test basic operation and non-copyable struct comp @disable this(this); } + auto ch = createChannel!S; + S v; + ch.put(S(1)); + assert(ch.tryConsumeOne(v) && v == S(1)); + ch.put(S(4)); + ch.put(S(5)); + { + RingBuffer!(S, 100) buf; + ch.consumeAll(buf); + assert(buf.length == 2); + assert(buf[0].i == 4); + assert(buf[1].i == 5); + } + ch.put(S(2)); + ch.close(); + assert(ch.tryConsumeOne(v) && v.i == 2); + assert(!ch.tryConsumeOne(v)); +} + +deprecated @safe unittest { // test basic operation and non-copyable struct compatiblity + static struct S { + int i; + @disable this(this); + } + auto ch = createChannel!S; S v; ch.put(S(1)); @@ -416,6 +464,26 @@ deprecated @safe unittest { // make sure shared(Channel!T) can also be used ch.put(S.init); ch.put(S.init); + S s; + RingBuffer!(S, 100, true) sb; + + () nothrow { + assert(ch.tryConsumeOne(s)); + assert(ch.consumeAll(sb)); + assert(sb.length == 1); + ch.close(); + assert(!ch.tryConsumeOne(s)); + } (); +} + +deprecated @safe unittest { // ensure nothrow'ness for throwing struct + static struct S { + this(this) { throw new Exception("meh!"); } + } + auto ch = createChannel!S; + ch.put(S.init); + ch.put(S.init); + S s; FixedRingBuffer!(S, 100, true) sb; diff --git a/source/vibe/core/core.d b/source/vibe/core/core.d index 0f3de704..4ee3c23c 100644 --- a/source/vibe/core/core.d +++ b/source/vibe/core/core.d @@ -10,6 +10,7 @@ module vibe.core.core; public import vibe.core.task; import eventcore.core; +import vibe.container.ringbuffer : RingBuffer; import vibe.core.args; import vibe.core.concurrency; import vibe.core.internal.release; @@ -17,7 +18,6 @@ import vibe.core.log; import vibe.core.sync : ManualEvent, createSharedManualEvent; import vibe.core.taskpool : TaskPool; import vibe.internal.async; -import vibe.internal.array : FixedRingBuffer; //import vibe.utils.array; import std.algorithm; import std.conv; @@ -407,7 +407,7 @@ package Task runTask_internal(alias TFI_SETUP)() TaskFiber f; while (!f && !s_availableFibers.empty) { f = s_availableFibers.back; - s_availableFibers.popBack(); + s_availableFibers.removeBack(); if (() @trusted nothrow { return f.state; } () != Fiber.State.HOLD) f = null; } @@ -1765,7 +1765,7 @@ private { bool delegate() @safe nothrow s_idleHandler; TaskScheduler s_scheduler; - FixedRingBuffer!TaskFiber s_availableFibers; + RingBuffer!TaskFiber s_availableFibers; size_t s_maxRecycledFibers = 100; string s_privilegeLoweringUserName; diff --git a/source/vibe/core/taskpool.d b/source/vibe/core/taskpool.d index 42dd887d..8d50d171 100644 --- a/source/vibe/core/taskpool.d +++ b/source/vibe/core/taskpool.d @@ -437,12 +437,12 @@ private struct TaskQueue { nothrow @safe: // TODO: avoid use of GC - import vibe.internal.array : FixedRingBuffer; - FixedRingBuffer!TaskFuncInfo* m_queue; + import vibe.container.ringbuffer : RingBuffer; + RingBuffer!TaskFuncInfo* m_queue; void setup() { - m_queue = new FixedRingBuffer!TaskFuncInfo; + m_queue = new RingBuffer!TaskFuncInfo; } @property bool empty() const { return m_queue.empty; } @@ -466,7 +466,7 @@ nothrow @safe: if (m_queue.empty) return false; swap(tfi, m_queue.front); - m_queue.popFront(); + m_queue.removeFront(); return true; } } diff --git a/source/vibe/internal/array.d b/source/vibe/internal/array.d index 075602d6..7df310a0 100644 --- a/source/vibe/internal/array.d +++ b/source/vibe/internal/array.d @@ -291,6 +291,7 @@ struct FixedAppender(ArrayType : E[], size_t NELEM, E) { /** TODO: clear ring buffer fields upon removal (to run struct destructors, if T is a struct) */ +deprecated("Use `vibe.container.ringbuffer.RingBuffer` instead.") struct FixedRingBuffer(T, size_t N = 0, bool INITIALIZE = true) { private { static if( N > 0 ) { @@ -559,7 +560,7 @@ struct FixedRingBuffer(T, size_t N = 0, bool INITIALIZE = true) { } } -unittest { +deprecated unittest { static assert(isInputRange!(FixedRingBuffer!int) && isOutputRange!(FixedRingBuffer!int, int)); FixedRingBuffer!(int, 5) buf; @@ -595,7 +596,7 @@ unittest { } } -unittest { +deprecated unittest { int* pcnt = new int; static struct S {