1 module test3; 2 3 import std.algorithm : map; 4 import std.stdio; 5 import core.thread.fiber; 6 import std.container.rbtree; 7 8 struct Item 9 { 10 uint id; 11 string description; 12 } 13 14 struct ItemPtr 15 { 16 uint id; 17 Item* payload; 18 19 this(uint i) 20 { 21 id = i; 22 payload = null; 23 } 24 25 this(ref Item i) 26 { 27 id = i.id; 28 payload = &i; 29 } 30 31 this(uint i, Item* p) 32 { 33 id = i; 34 payload = p; 35 } 36 } 37 38 struct ItemIndex 39 { 40 alias Impl = RedBlackTree!(ItemPtr, "a.id < b.id"); 41 Impl _impl; 42 alias _impl this; 43 44 auto keys() 45 { 46 import std.array : array; 47 return _impl[].map!"a.id".array; 48 } 49 50 struct Range 51 { 52 import std.array : back, empty, front, popBack, popFront; 53 54 alias Type = ItemPtr; 55 alias Keys = typeof(ItemIndex.init.keys()); 56 private ItemIndex* _idx; 57 private Keys _keys; 58 59 this(ref ItemIndex si) 60 { 61 _idx = &si; 62 _keys = si.keys; 63 } 64 65 this(ItemIndex* i, Keys k) 66 { 67 _idx = i; 68 _keys = k; 69 } 70 71 @disable this(); 72 73 bool empty() 74 { 75 return _keys.empty; 76 } 77 78 Type front() 79 { 80 auto e = ItemPtr(_keys.front); 81 return _idx.equalRange(e).front; 82 } 83 84 void popFront() 85 { 86 _keys.popFront; 87 } 88 89 Type back() 90 { 91 auto e = ItemPtr(_keys.front); 92 return _idx.equalRange(e).front; 93 } 94 95 void popBack() 96 { 97 _keys.popBack; 98 } 99 100 typeof(this) save() 101 { 102 auto instance = this; 103 instance._keys = _keys.dup; 104 return instance; 105 } 106 107 Type opIndex(size_t idx) 108 { 109 auto e = ItemPtr(_keys.front); 110 return _idx.equalRange(e).front; 111 } 112 113 size_t length() 114 { 115 return _keys.length; 116 } 117 } 118 119 auto opIndex(uint i) 120 { 121 return _impl.equalRange(ItemPtr(i, null)).front; 122 } 123 124 auto opSlice() 125 { 126 return Range(this); 127 } 128 } 129 130 void testItemIndex() 131 { 132 Item[] data = [ 133 Item(100, "item100"), 134 Item(200, "item200"), 135 Item(50, "item50"), 136 ]; 137 138 auto index = ItemIndex(); 139 index._impl = new ItemIndex.Impl(data.map!((ref a)=>ItemPtr(a.id, &a))); 140 141 writeln(index[].map!"*a.payload"); 142 writeln; 143 144 auto idx = index[]; 145 146 scope Fiber composed = new Fiber(() 147 { 148 while(!idx.empty) 149 { 150 writeln(*idx.front.payload); 151 idx.popFront; 152 Fiber.yield(); 153 } 154 }); 155 156 composed.call(); 157 composed.call(); 158 composed.call(); 159 composed.call(); 160 161 // since each fiber has run to completion, each should have state TERM 162 assert( composed.state == Fiber.State.TERM ); 163 }