Author: Armin Rigo <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit