1 
2 
3 module rwslist;
4 
5 import llist.slist;
6 
7 import core.sync.rwmutex;
8 
9 
10 ///A bundle of values for the SList payload.
11 private struct Bundle(T) {
12 	T payload;
13 	ReadWriteMutex mutex;
14 }
15 private Bundle!T newBundle(T)() {
16 	auto b = Bundle!T();
17 	b.initialize;
18 	return b;
19 }
20 private Bundle!T newBundle(T)(T payload) {
21 	Bundle!T b = Bundle!T(payload);
22 	b.initialize;
23 	return b;
24 }
25 private void initialize(T)(ref Bundle!T bundle) {
26 	bundle.mutex = new ReadWriteMutex;
27 }
28 
29 class RwSList(T) {
30 	private alias NodeT = Node!(Bundle!T)*;
31 	NodeT slist;
32 	NodeT last;
33 	this() {
34 		slist = new Node!(Bundle!T);
35 		slist.payload = newBundle!T();
36 		last = slist;
37 	}
38 	void iterate(bool delegate(const(T)) callback) {
39 		NodeT node=slist;
40 		while (true) {
41 			//---lock
42 			node.payload.mutex.reader.lock;
43 			NodeT lockedNode = node;
44 			scope(exit) lockedNode.payload.mutex.reader.unlock;
45 			//---empty
46 			if (node.empty) break;
47 			//---callback
48 			if (!callback(node.payload.payload)) break;
49 			//---move to next
50 			node = node.next;
51 			//---unlock
52 			// Done in `scope(exit)`
53 		}
54 	}
55 	void writeIterate(bool delegate(T, void delegate() remove) callback) {
56 		NodeT lastNode=null;
57 		NodeT node=slist;
58 		while (true) {
59 			//---lock
60 			node.payload.mutex.writer.lock;
61 			//---empty
62 			if (node.empty) {
63 				lastNode.payload.mutex.writer.unlock;
64 				node.payload.mutex.writer.unlock;
65 				break;
66 			}
67 			//---callback
68 			if (!callback(node.payload.payload, (){lastNode.removeNext;})) break;
69 			//---unlock old node (does not need to happen after "move to next" because `last` does not get used)
70 			if (lastNode!=null) {
71 				lastNode.payload.mutex.writer.unlock;
72 			}
73 			//---move to next
74 			lastNode = node;
75 			node = node.next;
76 		}
77 	}
78 	void put(T value) {
79 		last.payload.mutex.writer.lock;
80 		NodeT lockedNode = last;
81 		scope(exit) lockedNode.payload.mutex.writer.unlock;
82 		
83 		last.append(newBundle(value));
84 		last = last.next;
85 		last.payload = newBundle!T();
86 	}
87 }
88 
89 
90 
91 unittest {
92 	import std.stdio;
93 	
94 	class A {
95 		int a = 0;
96 		uint[5] b = [5652,144,1,684,888];
97 		this(int a) {
98 			this.a = a;
99 		}
100 	}
101 	
102 	RwSList!A list = new RwSList!A;
103 	
104 	list.put(new A(1));
105 	list.put(new A(2));
106 	list.put(new A(3));
107 	list.put(new A(4));
108 	list.put(new A(5));
109 	list.put(new A(6));
110 	list.put(new A(7));
111 	
112 	list.iterate((const A a){a.a.writeln; a.b.writeln; return true;});
113 	list.writeIterate((A a, void delegate() remove){a.a++; a.b.writeln; return true;});
114 	list.iterate((const A a){a.a.writeln; a.b.writeln; return true;});
115 }
116 
117 
118 
119