|
@@ -0,0 +1,79 @@
|
|
|
|
+namespace Invercargill {
|
|
|
|
+
|
|
|
|
+ private class ParallelQuery<Tin, Tout> : BaseQuery<Tin, Tout> {
|
|
|
|
+ private TransformDelegate<Tin, Tout> transform_func;
|
|
|
|
+ private int workers;
|
|
|
|
+
|
|
|
|
+ public ParallelQuery(Enumerable<Tin> input, owned TransformDelegate<Tin, Tout> transform, int workers) {
|
|
|
|
+ this.input = input;
|
|
|
|
+ this.workers = workers;
|
|
|
|
+ transform_func = (owned)transform;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override Tracker<Tout> get_tracker() {
|
|
|
|
+ return new ParallelTracker<Tin, Tout>(i => transform_func(i), workers, input.get_tracker());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private class ParallelTracker<Tin, Tout> : Tracker<Tout> {
|
|
|
|
+
|
|
|
|
+ private Fifo<Tout> queue;
|
|
|
|
+ private Tracker<Tout> queue_tracker;
|
|
|
|
+ private TransformDelegate<Tin, Tout> transform_func;
|
|
|
|
+ private Tracker<Tin> input_tracker;
|
|
|
|
+
|
|
|
|
+ public ParallelTracker(owned TransformDelegate<Tin, Tout> transform, int workers, Tracker<Tin> input) {
|
|
|
|
+ input_tracker = input;
|
|
|
|
+ queue = new Fifo<Tout>();
|
|
|
|
+ queue_tracker = queue.get_tracker();
|
|
|
|
+ this.transform_func = (owned)transform;
|
|
|
|
+
|
|
|
|
+ for(int i = 0; i < workers; i++) {
|
|
|
|
+ new Thread<bool>(@"Invercargill Parallel Job Thread #$i", do_work);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private WorkerItem<Tin> next_for_worker() {
|
|
|
|
+ lock(input_tracker) {
|
|
|
|
+ var item = new WorkerItem<Tin>();
|
|
|
|
+ if(input_tracker.has_next()) {
|
|
|
|
+ item.item = input_tracker.get_next();
|
|
|
|
+ return item;
|
|
|
|
+ }
|
|
|
|
+ item.complete = true;
|
|
|
|
+ if(!queue.marked_complete) {
|
|
|
|
+ queue.complete();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return item;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private bool do_work() {
|
|
|
|
+ var job = next_for_worker();
|
|
|
|
+ while(!job.complete) {
|
|
|
|
+ var output = transform_func(job.item);
|
|
|
|
+ queue.push(output);
|
|
|
|
+
|
|
|
|
+ job = next_for_worker();
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override bool has_next() {
|
|
|
|
+ return queue_tracker.has_next();
|
|
|
|
+ }
|
|
|
|
+ public override Tout get_next() {
|
|
|
|
+ return queue_tracker.get_next();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private class WorkerItem<Tin> {
|
|
|
|
+ public Tin? item { get; set; }
|
|
|
|
+ public bool complete { get; set; }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|