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
This commit is contained in:
parent
d708b77186
commit
85ceef29bd
|
@ -1578,6 +1578,11 @@ auto test_regex = UnitTest{[]{
|
||||||
kak_assert(vm.exec({str, str + sizeof(str)-1}));
|
kak_assert(vm.exec({str, str + sizeof(str)-1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TestVM<RegexMode::Forward | RegexMode::Search> vm{".{40}"};
|
||||||
|
kak_assert(vm.exec("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", RegexExecFlags::None));
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto eq = [](const CompiledRegex::NamedCapture& lhs,
|
auto eq = [](const CompiledRegex::NamedCapture& lhs,
|
||||||
const CompiledRegex::NamedCapture& rhs) {
|
const CompiledRegex::NamedCapture& rhs) {
|
||||||
|
|
|
@ -492,6 +492,7 @@ private:
|
||||||
if (start_desc and m_threads.next_is_empty())
|
if (start_desc and m_threads.next_is_empty())
|
||||||
to_next_start(pos, config, *start_desc);
|
to_next_start(pos, config, *start_desc);
|
||||||
m_threads.push_next({first_inst, -1});
|
m_threads.push_next({first_inst, -1});
|
||||||
|
m_threads.grow_ifn(false);
|
||||||
}
|
}
|
||||||
m_threads.swap_next();
|
m_threads.swap_next();
|
||||||
}
|
}
|
||||||
|
@ -609,10 +610,10 @@ private:
|
||||||
bool current_is_empty() const { return m_current == m_next_begin; }
|
bool current_is_empty() const { return m_current == m_next_begin; }
|
||||||
bool next_is_empty() const { return m_next_end == 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(); }
|
void push_current(Thread thread) { m_data[decrement(m_current)] = thread; grow_ifn(true); }
|
||||||
Thread pop_current() { auto res = m_data[m_current]; increment(m_current); return res; }
|
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)]; }
|
Thread pop_next() { return m_data[decrement(m_next_end)]; }
|
||||||
|
|
||||||
void swap_next()
|
void swap_next()
|
||||||
|
@ -621,27 +622,31 @@ private:
|
||||||
m_next_begin = m_next_end;
|
m_next_begin = m_next_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensure_initial_capacity() {
|
void ensure_initial_capacity()
|
||||||
if (m_capacity == 0)
|
|
||||||
grow_ifn();
|
|
||||||
}
|
|
||||||
|
|
||||||
void grow_ifn()
|
|
||||||
{
|
{
|
||||||
if (m_current != m_next_end)
|
if (m_capacity != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
constexpr int32_t initial_capacity = 64 / sizeof(Thread);
|
constexpr int32_t initial_capacity = 64 / sizeof(Thread);
|
||||||
static_assert(initial_capacity >= 4);
|
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;
|
}
|
||||||
|
|
||||||
|
void grow_ifn(bool pushed_current)
|
||||||
|
{
|
||||||
|
if (m_current != m_next_end)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto new_capacity = m_capacity * 2;
|
||||||
Thread* new_data = new Thread[new_capacity];
|
Thread* new_data = new Thread[new_capacity];
|
||||||
if (m_current < m_next_end)
|
Thread* old_data = m_data.get();
|
||||||
m_next_end = std::copy(m_data.get() + m_current, m_data.get() + m_next_end, new_data) - new_data;
|
std::rotate_copy(old_data, old_data + m_current, old_data + m_capacity, new_data);
|
||||||
else
|
m_next_begin -= m_current;
|
||||||
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;
|
if ((pushed_current and m_next_begin == 0) or m_next_begin < 0)
|
||||||
|
m_next_begin += m_capacity;
|
||||||
m_next_begin = m_next_begin >= m_current ? m_next_begin - m_current : m_capacity - (m_current - m_next_begin);
|
m_next_end = m_capacity;
|
||||||
m_current = 0;
|
m_current = 0;
|
||||||
|
|
||||||
m_data.reset(new_data);
|
m_data.reset(new_data);
|
||||||
|
@ -649,16 +654,19 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32_t decrement(int32_t& index) {
|
int32_t decrement(int32_t& index)
|
||||||
|
{
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
index = m_capacity;
|
index = m_capacity;
|
||||||
return --index;
|
return --index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t increment(int32_t& index) {
|
int32_t post_increment(int32_t& index)
|
||||||
|
{
|
||||||
|
auto res = index;
|
||||||
if (++index == m_capacity)
|
if (++index == m_capacity)
|
||||||
index = 0;
|
index = 0;
|
||||||
return index;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Thread[]> m_data;
|
std::unique_ptr<Thread[]> m_data;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user