All Downloads are FREE. Search and download functionalities are using the official Maven repository.

swim.system.DownlinkRelay Maven / Gradle / Ivy

The newest version!
// Copyright 2015-2024 Nstream, inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package swim.system;

import swim.concurrent.Cont;
import swim.concurrent.Stage;

public abstract class DownlinkRelay, View extends DownlinkView> implements Runnable {

  protected final Model model;
  protected final Object views; // View | View[]
  protected final int viewCount;
  protected final int phaseCount;
  protected int viewIndex;
  protected int phase;
  protected boolean preemptive;
  protected Stage stage;

  protected DownlinkRelay(Model model, int minPhase, int phaseCount, Stage stage) {
    this.model = model;
    this.views = model.views;
    if (this.views instanceof DownlinkView) {
      this.viewCount = 1;
    } else if (this.views instanceof DownlinkView[]) {
      this.viewCount = ((DownlinkView[]) this.views).length;
    } else {
      this.viewCount = 0;
    }
    this.phase = minPhase;
    this.phaseCount = phaseCount;
    this.preemptive = true;
    this.stage = stage;
    this.beginPhase(this.phase);
  }

  protected DownlinkRelay(Model model, int phaseCount) {
    this(model, 0, phaseCount, null);
  }

  protected DownlinkRelay(Model model) {
    this(model, 0, 1, null);
  }

  public boolean isDone() {
    return this.phase > this.phaseCount;
  }

  protected void beginPhase(int phase) {
    // hook
  }

  protected boolean runPhase(View view, int phase, boolean preemptive) {
    return true;
  }

  protected void endPhase(int phase) {
    // hook
  }

  protected void done() {
    // hook
  }

  void pass(View view) {
    do {
      if (this.viewIndex < this.viewCount) {
        try {
          if (!this.runPhase(view, this.phase, this.preemptive) && this.preemptive) {
            this.preemptive = false;
            if (this.stage != view.stage) {
              this.stage = view.stage;
              this.stage.execute(this);
              return;
            } else {
              continue;
            }
          }
        } catch (Throwable error) {
          if (Cont.isNonFatal(error)) {
            view.downlinkDidFail(error);
          }
          throw error;
        }
        this.viewIndex += 1;
      } else if (this.phase < this.phaseCount) {
        this.endPhase(this.phase);
        this.viewIndex = 0;
        this.phase += 1;
        this.preemptive = true;
        if (this.phase < this.phaseCount) {
          this.beginPhase(this.phase);
        } else {
          this.endPhase(this.phase);
          this.phase += 1;
          this.done();
          return;
        }
      } else {
        return;
      }
    } while (true);
  }

  @SuppressWarnings("unchecked")
  void pass(DownlinkView[] views) {
    do {
      if (this.viewIndex < this.viewCount) {
        final View view = (View) views[this.viewIndex];
        try {
          if (!this.runPhase(view, this.phase, this.preemptive) && this.preemptive) {
            this.preemptive = false;
            if (this.stage != view.stage) {
              this.stage = view.stage;
              this.stage.execute(this);
              return;
            } else {
              continue;
            }
          }
        } catch (Throwable error) {
          if (Cont.isNonFatal(error)) {
            view.downlinkDidFail(error);
          }
          throw error;
        }
        this.viewIndex += 1;
      } else if (this.phase < this.phaseCount) {
        this.endPhase(this.phase);
        this.viewIndex = 0;
        this.phase += 1;
        this.preemptive = true;
        if (this.phase < this.phaseCount) {
          this.beginPhase(this.phase);
        } else {
          this.endPhase(this.phase);
          this.phase += 1;
          this.done();
          return;
        }
      } else {
        return;
      }
    } while (true);
  }

  @SuppressWarnings("unchecked")
  @Override
  public void run() {
    final Stage stage = this.stage;
    final long t0 = System.nanoTime();
    try {
      if (this.viewCount == 1) {
        this.pass((View) this.views);
      } else if (this.viewCount > 1) {
        this.pass((DownlinkView[]) this.views);
      }
    } catch (Throwable error) {
      if (Cont.isNonFatal(error)) {
        this.model.didFail(error);
      } else {
        throw error;
      }
    }
    final long dt = System.nanoTime() - t0;
    if (stage == null) {
      this.model.accumulateExecTime(dt);
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy