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

io.vlingo.actors.plugin.mailbox.sharedringbuffer.SharedRingBufferMailbox Maven / Gradle / Ivy

Go to download

Type safe Actor Model toolkit for reactive concurrency and resiliency using Java and other JVM languages.

There is a newer version: 1.7.5
Show newest version
// Copyright © 2012-2020 VLINGO LABS. All rights reserved.
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL
// was not distributed with this file, You can obtain
// one at https://mozilla.org/MPL/2.0/.

package io.vlingo.actors.plugin.mailbox.sharedringbuffer;

import io.vlingo.actors.*;
import io.vlingo.common.SerializableConsumer;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

public class SharedRingBufferMailbox implements Mailbox {
  private final AtomicBoolean closed;
  private final Dispatcher dispatcher;
  private final int mailboxSize;
  private final Message[] messages;
  private final boolean notifyOnSend;
  private final AtomicLong sendIndex;
  private final AtomicLong readyIndex;
  private final AtomicLong receiveIndex;

  @Override
  public void close() {
    if (!closed.get()) {
      closed.set(true);
      dispatcher.close();
    }
  }

  @Override
  public boolean isClosed() {
    return closed.get();
  }

  @Override
  public boolean isDelivering() {
    throw new UnsupportedOperationException("SharedRingBufferMailbox does not support this operation.");
  }

  @Override
  public boolean isPreallocated() {
    return true;
  }

  @Override
  public int concurrencyCapacity() {
    return 1;
  }

  @Override
  public void resume(final String name) {
    // TODO: Consider supporting Stowage here
    throw new UnsupportedOperationException("SharedRingBufferMailbox does not support this operation.");
  }

  @Override
  public void send(final Message message) {
    throw new UnsupportedOperationException("Use preallocated mailbox send(Actor, ...).");
  }

  @Override
  public void suspendExceptFor(final String name, final Class... overrides) {
    // TODO: Consider supporting Stowage here
    throw new UnsupportedOperationException("SharedRingBufferMailbox does not support this operation.");
  }

  @Override
  public boolean isSuspended() {
    return false;
  }

  @Override
  public void send(final Actor actor, final Class protocol, final SerializableConsumer consumer, final Returns returns, final String representation) {
    final long messageIndex = sendIndex.incrementAndGet();
    final int ringSendIndex = (int) (messageIndex % mailboxSize);

    int retries = 0;
    while (ringSendIndex == (int) (receiveIndex.get() % mailboxSize)) {
      if (++retries >= mailboxSize) {
        if (closed.get()) {
          return;
        } else {
          retries = 0;
        }
      }
    }

    messages[ringSendIndex].set(actor, protocol, consumer, returns, representation);

    while (!readyIndex.compareAndSet(messageIndex - 1, messageIndex))
      ;

    if (notifyOnSend) {
      dispatcher.execute(this);
    }
  }

  @Override
  public Message receive() {
    final long messageIndex = receiveIndex.get();

    if (messageIndex < readyIndex.get()) {
      final int index = (int) (receiveIndex.incrementAndGet() % mailboxSize);

      return messages[index];
    }

    return null;
  }

  @Override
  public void run() {
    throw new UnsupportedOperationException("SharedRingBufferMailbox does not support this operation.");
  }

  /* @see io.vlingo.actors.Mailbox#pendingMessages() */
  @Override
  public int pendingMessages() {
    throw new UnsupportedOperationException("SharedRingBufferMailbox does not support this operation");
  }

  protected SharedRingBufferMailbox(final Dispatcher dispatcher, final int mailboxSize, final boolean notifyOnSend) {
    this.dispatcher = dispatcher;
    this.mailboxSize = mailboxSize;
    this.closed = new AtomicBoolean(false);
    this.messages = new Message[mailboxSize];
    this.readyIndex = new AtomicLong(-1);
    this.receiveIndex = new AtomicLong(-1);
    this.sendIndex = new AtomicLong(-1);
    this.notifyOnSend = notifyOnSend;

    initPreallocated();
  }

  private void initPreallocated() {
    for (int idx = 0; idx < mailboxSize; ++idx) {
      messages[idx] = new LocalMessage<>(this);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy