Commit 22510e2df16 by Armin Rigo

in-progress

--HG--
branch : bag
parent 93786da1292
......@@ -104,16 +104,34 @@ object_t *stm_bag_try_pop(stm_bag_t *bag)
return NULL;
}
struct deque_block_s *block = deque_block(bs->deque_left);
bool any_old_item_to_pop = (bs->deque_left != bs->deque_middle);
uintptr_t result = *bs->deque_left++;
if (bs->deque_left == &block->items[DEQUE_BLOCK_SIZE]) {
bs->deque_left = &block->next->items[0];
deque_free_block(block);
}
if (!any_old_item_to_pop) {
bs->deque_middle = bs->deque_left;
}
return (object_t *)result;
}
void stm_bag_tracefn(stm_bag_t *bag, void visit(object_t **))
void stm_bag_tracefn(stm_bag_t *bag, void trace(object_t **))
{
abort();
if (trace == TRACE_FOR_MINOR_COLLECTION) {
/* only trace the items added in the current transaction;
the rest is already old and cannot point into the nursery. */
int i = STM_SEGMENT->segment_num - 1;
struct stm_bag_seg_s *bs = &bag->by_segment[i];
deque_trace(bs->deque_middle, bs->deque_right, trace);
}
else {
int i;
for (i = 0; i < NB_SEGMENTS; i++) {
struct stm_bag_seg_s *bs = &bag->by_segment[i];
deque_trace(bs->deque_left, bs->deque_right, trace);
}
}
}
......@@ -212,3 +212,29 @@ static struct deque_block_s *deque_new_block(void)
db->next = NULL;
return db;
}
static void deque_trace(uintptr_t *start, uintptr_t *stop,
void trace(object_t **))
{
struct deque_block_s *block = deque_block(start);
struct deque_block_s *last_block = deque_block(stop);
uintptr_t *end;
while (1) {
if (block == last_block)
end = stop;
else
end = &block->items[DEQUE_BLOCK_SIZE];
while (start != end) {
trace((object_t **)start);
start++;
}
if (block == last_block)
break;
block = block->next;
start = &block->items[0];
}
}
......@@ -246,3 +246,5 @@ static inline bool deque_index_equal(uintptr_t *inner_ptr, uintptr_t index)
struct deque_block_s *block = deque_block(inner_ptr);
return (inner_ptr == &block->items[index]);
}
static void deque_trace(uintptr_t *start, uintptr_t *stop, void (object_t **));
......@@ -79,3 +79,55 @@ class TestBag(BaseTestBag):
assert got == lp
py.test.raises(BagLooksEmpty, b_pop, q)
py.test.raises(BagLooksEmpty, b_pop, q)
def test_keepalive_minor(self):
self.start_transaction()
b = self.allocate_bag()
self.push_root(b)
lp1 = stm_allocate(16)
stm_set_char(lp1, 'N')
b_add(b, lp1)
stm_minor_collect()
b = self.pop_root()
lp1b = b_pop(b)
assert lp1b != ffi.NULL
assert stm_get_char(lp1b) == 'N'
assert lp1b != lp1
def test_keepalive_major(self):
self.start_transaction()
b = self.allocate_bag()
self.push_root(b)
lp1 = stm_allocate(16)
stm_set_char(lp1, 'N')
b_add(b, lp1)
stm_major_collect()
b = self.pop_root()
lp1b = b_pop(b)
assert lp1b != ffi.NULL
assert stm_get_char(lp1b) == 'N'
assert lp1b != lp1
def test_transaction_local(self):
self.start_transaction()
q = self.allocate_bag()
self.push_root(q)
self.commit_transaction()
q = self.pop_root()
#
self.start_transaction()
lp1 = stm_allocate(16)
b_add(q, lp1)
#
self.switch(1)
self.start_transaction()
lp2 = stm_allocate(16)
b_add(q, lp2)
got = b_pop(q)
assert got == lp2
#
self.switch(0)
got = b_pop(q)
assert got == lp1
#
stm_major_collect() # to get rid of the bag object
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment