Author: Armin Rigo <ar...@tunes.org> Branch: stm Changeset: r51633:5ab80750fca1 Date: 2012-01-22 11:17 +0100 http://bitbucket.org/pypy/pypy/changeset/5ab80750fca1/
Log: Add an explicit fifo queue implementation, instead of using list.pop(0). diff --git a/pypy/module/transaction/fifo.py b/pypy/module/transaction/fifo.py new file mode 100644 --- /dev/null +++ b/pypy/module/transaction/fifo.py @@ -0,0 +1,34 @@ + +class Fifo(object): + def __init__(self): + self.first = None + self.last = None + + def append(self, newitem): + newitem.next = None + if self.last is None: + self.first = newitem + else: + self.last.next = newitem + self.last = newitem + + def is_empty(self): + assert (self.first is None) == (self.last is None) + return self.first is None + + def popleft(self): + item = self.first + self.first = item.next + if self.first is None: + self.last = None + return item + + def steal(self, otherfifo): + if otherfifo.last is not None: + if self.last is None: + self.first = otherfifo.first + else: + self.last.next = otherfifo.first + self.last = otherfifo.last + otherfifo.first = None + otherfifo.last = None diff --git a/pypy/module/transaction/interp_transaction.py b/pypy/module/transaction/interp_transaction.py --- a/pypy/module/transaction/interp_transaction.py +++ b/pypy/module/transaction/interp_transaction.py @@ -1,6 +1,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import unwrap_spec from pypy.module.transaction import threadintf +from pypy.module.transaction.fifo import Fifo from pypy.rlib import rstm @@ -13,7 +14,7 @@ self.__dict__.clear() self.running = False self.num_threads = NUM_THREADS_DEFAULT - self.pending = [] + self.pending = Fifo() self.pending_lists = {0: self.pending} self.ll_lock = threadintf.null_ll_lock self.ll_no_tasks_pending_lock = threadintf.null_ll_lock @@ -110,24 +111,23 @@ def add_list(new_pending_list): - if len(new_pending_list) == 0: + if new_pending_list.is_empty(): return - was_empty = len(state.pending) == 0 - state.pending += new_pending_list - del new_pending_list[:] + was_empty = state.pending.is_empty() + state.pending.steal(new_pending_list) if was_empty: state.unlock_no_tasks_pending() def _run_thread(): state.lock() - my_pending_list = [] + my_pending_list = Fifo() my_thread_id = threadintf.thread_id() state.pending_lists[my_thread_id] = my_pending_list rstm.descriptor_init() # while True: - if len(state.pending) == 0: + if state.pending.is_empty(): assert state.is_locked_no_tasks_pending() state.num_waiting_threads += 1 if state.num_waiting_threads == state.num_threads: @@ -143,8 +143,8 @@ if state.finished: break else: - pending = state.pending.pop(0) - if len(state.pending) == 0: + pending = state.pending.popleft() + if state.pending.is_empty(): state.lock_no_tasks_pending() state.unlock() pending.run() @@ -164,7 +164,7 @@ state.w_error, space.wrap("recursive invocation of transaction.run()")) assert not state.is_locked_no_tasks_pending() - if len(state.pending) == 0: + if state.pending.is_empty(): return state.num_waiting_threads = 0 state.finished = False @@ -177,7 +177,7 @@ state.lock_unfinished() # wait for all threads to finish # assert state.num_waiting_threads == 0 - assert len(state.pending) == 0 + assert state.pending.is_empty() assert state.pending_lists.keys() == [state.main_thread_id] assert not state.is_locked_no_tasks_pending() state.running = False diff --git a/pypy/module/transaction/test/test_fifo.py b/pypy/module/transaction/test/test_fifo.py new file mode 100644 --- /dev/null +++ b/pypy/module/transaction/test/test_fifo.py @@ -0,0 +1,40 @@ +from pypy.module.transaction.fifo import Fifo + +class Item: + def __init__(self, value): + self.value = value + +def test_one_item(): + f = Fifo() + assert f.is_empty() + f.append(Item(123)) + assert not f.is_empty() + item = f.popleft() + assert f.is_empty() + assert item.value == 123 + +def test_three_items(): + f = Fifo() + for i in [10, 20, 30]: + f.append(Item(i)) + assert not f.is_empty() + for i in [10, 20, 30]: + assert not f.is_empty() + item = f.popleft() + assert item.value == i + assert f.is_empty() + +def test_steal(): + for n1 in range(3): + for n2 in range(3): + f1 = Fifo() + f2 = Fifo() + for i in range(n1): f1.append(Item(10 + i)) + for i in range(n2): f2.append(Item(20 + i)) + f1.steal(f2) + assert f2.is_empty() + for x in range(10, 10+n1) + range(20, 20+n2): + assert not f1.is_empty() + item = f1.popleft() + assert item.value == x + assert f1.is_empty() _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit