Author: Armin Rigo <[email protected]>
Branch: bag
Changeset: r1574:cfd89ce23688
Date: 2015-01-23 22:05 +0100
http://bitbucket.org/pypy/stmgc/changeset/cfd89ce23688/

Log:    getting started

diff --git a/c7/stm/bag.c b/c7/stm/bag.c
new file mode 100644
--- /dev/null
+++ b/c7/stm/bag.c
@@ -0,0 +1,85 @@
+/*
+Design of stmgc's "bag" objects
+===============================
+
+A "bag" is an unordered list of objects.  You can only add objects and
+pop a random object.
+
+Conflicts never occur, but popping may return "the bag looks empty",
+which can be wrong in the serialized order.  The caller should be
+ready to handle this case.  The guarantee is that if you get the
+result "the bag looks empty" in all threads that may add objects to
+it, and afterwards none of the threads adds any object, then at this
+point the bag is really empty.
+
+
+Implementation
+--------------
+
+In raw memory, for each segment, we have a list and a deque:
+
+     abort list             deque
+   +--------------+       +-----------------------+---------------+
+   | already      |       | next items            | added in this |
+   | popped items |       | to pop                | transaction   |
+   +--------------+       +-----------------------+---------------+
+
+Adding objects puts them at the right end of the deque.  Popping them
+takes them off the left end and stores a copy of the pointer into a
+separate list.  This list, the "abort list", is only used to re-add
+the objects in case the transaction aborts.
+
+If, when we try to pop, we find that the deque is completely empty,
+then we try to "steal" some items from another segment's deque.  This
+movement is done completely outside the normal STM rules: the objects
+remain moved even after an abort.  More precisely, we take some
+objects from the left end of the other segment's deque (but not from
+the "added in this transaction" part) and add them to our own deque.
+Our own "added in this transaction" part remains empty, and the
+objects are not copied in the other transaction's abort list.  This
+is done with careful compare-and-swaps.
+*/
+
+
+struct stm_bag_seg_s {
+    struct deque_block_s *deque_left, *deque_middle, *deque_right;
+    deque_idx_t deque_left_pos, deque_middle_pos, deque_right_pos;
+    struct list_s *abort_list;
+};
+
+struct stm_bag_s {
+    struct stm_bag_seg_s by_segment[STM_NB_SEGMENTS];
+};
+
+stm_bag_t *stm_bag_create(void)
+{
+    int i;
+    stm_bag_t *bag = malloc(sizeof(stm_bag_t));
+    assert(bag);
+    for (i = 0; i < STM_NB_SEGMENTS; i++) {
+        struct stm_bag_seg_s *bs = &bag->by_segment[i];
+        struct deque_block_s *block = deque_new_block();
+        bs->deque_left = block;
+        bs->deque_middle = block;
+        bs->deque_right = block;
+        bs->deque_left_pos = 0;
+        bs->deque_middle_pos = 0;
+        bs->deque_right_pos = 0;
+        LIST_CREATE(bs->abort_list);
+    }
+    return bag;
+}
+
+void stm_bag_free(stm_bag_t *bag)
+{
+    int i;
+    for (i = 0; i < STM_NB_SEGMENTS; i++) {
+        struct stm_bag_seg_s *bs = &bag->by_segment[i];
+        while (bs->deque_left) {
+            struct deque_block_s *block = bs->deque_left;
+            bs->deque_left = block->next;
+            deque_free_block(block);
+        }
+        LIST_FREE(bs->abort_list);
+    }
+}
diff --git a/c7/stm/list.h b/c7/stm/list.h
--- a/c7/stm/list.h
+++ b/c7/stm/list.h
@@ -218,3 +218,27 @@
     TREE_FIND(*tree, addr, result, return false);
     return true;
 }
+
+/************************************************************/
+
+#define DEQUE_BLOCK_SIZE  31
+typedef unsigned char deque_idx_t;
+
+struct deque_block_s {
+    struct deque_block_s *next;
+    uintptr_t items[DEQUE_BLOCK_SIZE];
+};
+
+static inline struct deque_block_s *deque_new_block(void)
+{
+    struct deque_block_s *db = malloc(sizeof(struct deque_block_s));
+    if (db == NULL)
+        stm_fatalerror("out of memory in deque_new_block");   /* XXX */
+    db->next = NULL;
+    return db;
+}
+
+static inline void deque_free_block(struct deque_block_s *db)
+{
+    free(db);
+}
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -553,6 +553,13 @@
     object_t *object;
 };
 
+/* Bags, i.e. unordered lists. */
+typedef struct stm_bag_s stm_bag_t;
+stm_bag_t *stm_bag_create(void);
+void stm_bag_free(stm_bag_t *);
+void stm_bag_add(stm_bag_t *, object_t *);
+object_t *stm_bag_try_pop(stm_bag_t *);
+
 /* ==================== END ==================== */
 
 #endif
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to