summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2023-02-14 17:13:31 +1100
committerMaxime Coste <mawww@kakoune.org>2023-02-14 17:13:31 +1100
commit85ceef29bdc3e9fe8cd42770f9191ad48726bda5 (patch)
tree992cf24c17da974da72d8fb5a6acb7f3abadc92f /src
parentd708b77186c1685dcbd2298246ada7d204acec2f (diff)
Fix broken corner cases in DualThreadStack::grow_ifn
We only grow when the ring buffer is full, which allows for a nice simplification of the code. Tell grow_ifn if we pushed in current or next so that we can distinguish between filled by next or filled by current when m_current == m_next_begin
Diffstat (limited to 'src')
-rw-r--r--src/regex_impl.cc5
-rw-r--r--src/regex_impl.hh48
2 files changed, 33 insertions, 20 deletions
diff --git a/src/regex_impl.cc b/src/regex_impl.cc
index 09efdb75..23321af8 100644
--- a/src/regex_impl.cc
+++ b/src/regex_impl.cc
@@ -1579,6 +1579,11 @@ auto test_regex = UnitTest{[]{
}
{
+ TestVM<RegexMode::Forward | RegexMode::Search> vm{".{40}"};
+ kak_assert(vm.exec("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", RegexExecFlags::None));
+ }
+
+ {
auto eq = [](const CompiledRegex::NamedCapture& lhs,
const CompiledRegex::NamedCapture& rhs) {
return lhs.name == rhs.name and
diff --git a/src/regex_impl.hh b/src/regex_impl.hh
index cb5acd05..fd99ea1e 100644
--- a/src/regex_impl.hh
+++ b/src/regex_impl.hh
@@ -492,6 +492,7 @@ private:
if (start_desc and m_threads.next_is_empty())
to_next_start(pos, config, *start_desc);
m_threads.push_next({first_inst, -1});
+ m_threads.grow_ifn(false);
}
m_threads.swap_next();
}
@@ -609,10 +610,10 @@ private:
bool current_is_empty() const { return m_current == m_next_begin; }
bool next_is_empty() const { return m_next_end == m_next_begin; }
- void push_current(Thread thread) { m_data[decrement(m_current)] = thread; grow_ifn(); }
- Thread pop_current() { auto res = m_data[m_current]; increment(m_current); return res; }
+ void push_current(Thread thread) { m_data[decrement(m_current)] = thread; grow_ifn(true); }
+ Thread pop_current() { return m_data[post_increment(m_current)]; }
- void push_next(Thread thread) { m_data[m_next_end] = thread; increment(m_next_end); }
+ void push_next(Thread thread) { m_data[post_increment(m_next_end)] = thread; }
Thread pop_next() { return m_data[decrement(m_next_end)]; }
void swap_next()
@@ -621,27 +622,31 @@ private:
m_next_begin = m_next_end;
}
- void ensure_initial_capacity() {
- if (m_capacity == 0)
- grow_ifn();
- }
-
- void grow_ifn()
+ void ensure_initial_capacity()
{
- if (m_current != m_next_end)
+ if (m_capacity != 0)
return;
constexpr int32_t initial_capacity = 64 / sizeof(Thread);
static_assert(initial_capacity >= 4);
+ m_data.reset(new Thread[initial_capacity]);
+ m_capacity = initial_capacity;
- const auto new_capacity = m_capacity ? m_capacity * 2 : initial_capacity;
- Thread* new_data = new Thread[new_capacity];
- if (m_current < m_next_end)
- m_next_end = std::copy(m_data.get() + m_current, m_data.get() + m_next_end, new_data) - new_data;
- else
- m_next_end = std::copy(m_data.get(), m_data.get() + m_next_end, std::copy(m_data.get() + m_current, m_data.get() + m_capacity, new_data)) - new_data;
+ }
+
+ void grow_ifn(bool pushed_current)
+ {
+ if (m_current != m_next_end)
+ return;
- m_next_begin = m_next_begin >= m_current ? m_next_begin - m_current : m_capacity - (m_current - m_next_begin);
+ const auto new_capacity = m_capacity * 2;
+ Thread* new_data = new Thread[new_capacity];
+ Thread* old_data = m_data.get();
+ std::rotate_copy(old_data, old_data + m_current, old_data + m_capacity, new_data);
+ m_next_begin -= m_current;
+ if ((pushed_current and m_next_begin == 0) or m_next_begin < 0)
+ m_next_begin += m_capacity;
+ m_next_end = m_capacity;
m_current = 0;
m_data.reset(new_data);
@@ -649,16 +654,19 @@ private:
}
private:
- int32_t decrement(int32_t& index) {
+ int32_t decrement(int32_t& index)
+ {
if (index == 0)
index = m_capacity;
return --index;
}
- int32_t increment(int32_t& index) {
+ int32_t post_increment(int32_t& index)
+ {
+ auto res = index;
if (++index == m_capacity)
index = 0;
- return index;
+ return res;
}
std::unique_ptr<Thread[]> m_data;