scylla-gdb.py: fix disagreement between std_deque len() and iter()

std_deque implementation was broken, with __len__() and __iter__()
disagreeing about the size of the container. Turns out both are wrong in
certain situations. Fix the iteration logic and re-base both __len__()
and __iter__() on the same node iteration code to prevent future
disagreements.
This commit is contained in:
Botond Dénes
2022-07-11 15:16:12 +03:00
parent 7e2d2cf1c1
commit 966373fcfb

View File

@@ -562,39 +562,6 @@ class std_deque:
# should reflect the value of _GLIBCXX_DEQUE_BUF_SIZE
DEQUE_BUF_SIZE = 512
class iterator:
def __init__(self, ref, buf_size):
self.cur = ref['_M_cur']
self.first = ref['_M_first']
self.last = ref['_M_last']
self.node = ref['_M_node']
self.buf_size = buf_size
def _set_node(self, node):
self.first = node.dereference()
self.last = self.first + self.buf_size
self.node = node
def __eq__(self, other):
return self.node == other.node and self.cur == other.cur
def __str__(self):
return "{{node=0x{:x}, first=0x{:x}, last=0x{:x}, cur=0x{:x}}}".format(
int(self.node),
int(self.first),
int(self.last),
int(self.cur))
def next(self):
self.cur += 1
if self.cur == self.last:
self._set_node(self.node + 1)
self.cur = self.first
def get(self):
return self.cur.dereference()
def __init__(self, ref):
self.ref = ref
self.value_type = self.ref.type.strip_typedefs().template_argument(0)
@@ -603,12 +570,29 @@ class std_deque:
else:
self.buf_size = 1
def _foreach_node(self):
node_it = self.ref['_M_impl']['_M_start']
node_end = self.ref['_M_impl']['_M_finish']
node = node_it['_M_node']
it = node_it['_M_first']
end = node_it['_M_last']
if not bool(node):
return
while node != node_end['_M_node']:
yield it, end
node = node + 1
it = node.dereference()
end = it + self.buf_size
yield node_end['_M_first'], node_end['_M_cur']
def __len__(self):
start = self.ref['_M_impl']['_M_start']
finish = self.ref['_M_impl']['_M_finish']
return (self.buf_size * (max(1, finish['_M_node'] - start['_M_node']) - 1) +
start['_M_last'] - start['_M_cur'] +
finish['_M_cur'] - finish['_M_first'])
l = 0
for start, end in self._foreach_node():
l += (end - start)
return l
def __nonzero__(self):
return self.__len__() > 0
@@ -617,12 +601,10 @@ class std_deque:
return self.__len__() > 0
def __iter__(self):
it = std_deque.iterator(self.ref['_M_impl']['_M_start'], self.buf_size)
finish = std_deque.iterator(self.ref['_M_impl']['_M_finish'], self.buf_size)
while it != finish:
yield it.get()
it.next()
for it, end in self._foreach_node():
while it != end:
yield it.dereference()
it += 1
def __str__(self):
items = [str(item) for item in self]