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

swim.system.LaneView Maven / Gradle / Ivy

// 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 java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import swim.api.Downlink;
import swim.api.Lane;
import swim.api.agent.AgentContext;
import swim.api.policy.Policy;
import swim.concurrent.Schedule;
import swim.concurrent.Stage;
import swim.store.StoreBinding;
import swim.uri.Uri;

public abstract class LaneView extends AbstractTierBinding implements Lane {

  protected volatile Object observers; // Observer | Observer[]

  public LaneView(Object observers) {
    this.observers = observers;
  }

  @Override
  public TierContext tierContext() {
    return null;
  }

  public abstract AgentContext agentContext();

  public abstract LaneBinding laneBinding();

  public LaneContext laneContext() {
    return this.laneBinding().laneContext();
  }

  public abstract LaneBinding createLaneBinding();

  @SuppressWarnings("unchecked")
  public  T unwrapLane(Class laneClass) {
    if (laneClass.isAssignableFrom(this.getClass())) {
      return (T) this;
    } else {
      return null;
    }
  }

  @SuppressWarnings("unchecked")
  public  T bottomLane(Class laneClass) {
    if (laneClass.isAssignableFrom(this.getClass())) {
      return (T) this;
    } else {
      return null;
    }
  }

  @Override
  public LaneAddress cellAddress() {
    return this.laneContext().cellAddress();
  }

  @Override
  public final String edgeName() {
    return this.laneContext().edgeName();
  }

  @Override
  public final Uri meshUri() {
    return this.laneContext().meshUri();
  }

  @Override
  public final Uri hostUri() {
    return this.laneBinding().hostUri();
  }

  @Override
  public final Uri nodeUri() {
    return this.laneBinding().nodeUri();
  }

  @Override
  public final Uri laneUri() {
    return this.laneBinding().laneUri();
  }

  @Override
  public abstract void close();

  @Override
  public LaneView observe(Object newObserver) {
    do {
      final Object oldObservers = LaneView.OBSERVERS.get(this);
      final Object newObservers;
      if (oldObservers == null) {
        newObservers = newObserver;
      } else if (!(oldObservers instanceof Object[])) {
        final Object[] newArray = new Object[2];
        newArray[0] = oldObservers;
        newArray[1] = newObserver;
        newObservers = newArray;
      } else {
        final Object[] oldArray = (Object[]) oldObservers;
        final int oldCount = oldArray.length;
        final Object[] newArray = new Object[oldCount + 1];
        System.arraycopy(oldArray, 0, newArray, 0, oldCount);
        newArray[oldCount] = newObserver;
        newObservers = newArray;
      }
      if (LaneView.OBSERVERS.compareAndSet(this, oldObservers, newObservers)) {
        break;
      }
    } while (true);
    return this;
  }

  @Override
  public LaneView unobserve(Object oldObserver) {
    do {
      final Object oldObservers = LaneView.OBSERVERS.get(this);
      final Object newObservers;
      if (oldObservers == null) {
        break;
      } else if (!(oldObservers instanceof Object[])) {
        if (oldObservers == oldObserver) { // found as sole observer
          newObservers = null;
        } else {
          break; // not found
        }
      } else {
        final Object[] oldArray = (Object[]) oldObservers;
        final int oldCount = oldArray.length;
        if (oldCount == 2) {
          if (oldArray[0] == oldObserver) { // found at index 0
            newObservers = oldArray[1];
          } else if (oldArray[1] == oldObserver) { // found at index 1
            newObservers = oldArray[0];
          } else {
            break; // not found
          }
        } else {
          int i = 0;
          while (i < oldCount) {
            if (oldArray[i] == oldObserver) { // found at index i
              break;
            }
            i += 1;
          }
          if (i < oldCount) {
            final Object[] newArray = new Object[oldCount - 1];
            System.arraycopy(oldArray, 0, newArray, 0, i);
            System.arraycopy(oldArray, i + 1, newArray, i, oldCount - 1 - i);
            newObservers = newArray;
          } else {
            break; // not found
          }
        }
      }
      if (LaneView.OBSERVERS.compareAndSet(this, oldObservers, newObservers)) {
        break;
      }
    } while (true);
    return this;
  }

  public void laneDidFail(Throwable error) {
    // hook
  }

  @Override
  public Policy policy() {
    return this.laneContext().policy();
  }

  @Override
  public Schedule schedule() {
    return this.laneContext().schedule();
  }

  @Override
  public Stage stage() {
    return this.laneContext().stage();
  }

  @Override
  public StoreBinding store() {
    return this.laneContext().store();
  }

  @Override
  public LinkBinding bindDownlink(Downlink downlink) {
    return this.laneContext().bindDownlink(downlink);
  }

  @Override
  public void openDownlink(LinkBinding link) {
    this.laneContext().openDownlink(link);
  }

  @Override
  public void closeDownlink(LinkBinding link) {
    this.laneContext().closeDownlink(link);
  }

  @Override
  public void pushDown(Push push) {
    this.laneContext().pushDown(push);
  }

  @Override
  public void reportDown(Metric metric) {
    this.laneContext().reportDown(metric);
  }

  @Override
  public void openMetaDownlink(LinkBinding downlink, NodeBinding metaDownlink) {
    this.laneBinding().openMetaDownlink(downlink, metaDownlink);
  }

  @Override
  public void trace(Object message) {
    this.laneBinding().trace(message);
  }

  @Override
  public void debug(Object message) {
    this.laneBinding().debug(message);
  }

  @Override
  public void info(Object message) {
    this.laneBinding().info(message);
  }

  @Override
  public void warn(Object message) {
    this.laneBinding().warn(message);
  }

  @Override
  public void error(Object message) {
    this.laneBinding().error(message);
  }

  @Override
  public void fail(Object message) {
    this.laneBinding().fail(message);
  }

  static final AtomicReferenceFieldUpdater OBSERVERS =
      AtomicReferenceFieldUpdater.newUpdater(LaneView.class, Object.class, "observers");

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy