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

monix.execution.internal.collection.queues.FromCircularQueue.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2014-2019 by The Monix Project Developers.
 * See the project homepage at: https://monix.io
 *
 * 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 monix.execution.internal.collection.queues

import monix.execution.ChannelType
import monix.execution.ChannelType.{SingleConsumer, SingleProducer}
import monix.execution.internal.atomic.UnsafeAccess
import monix.execution.internal.collection.LowLevelConcurrentQueue
import org.jctools.queues.ConcurrentCircularArrayQueue
import sun.misc.Unsafe
import scala.collection.mutable

private[internal] abstract class FromCircularQueue[A](queue: ConcurrentCircularArrayQueue[A])
  extends LowLevelConcurrentQueue[A] {

  def fenceOffer(): Unit
  def fencePoll(): Unit

  final def isEmpty: Boolean =
    queue.isEmpty

  final def offer(elem: A): Int =
    if (queue.offer(elem)) 0 else 1

  final def poll(): A =
    queue.poll()

  final def clear(): Unit =
    queue.clear()

  final def drainToBuffer(buffer: mutable.Buffer[A], limit: Int): Int = {
    val consume = new QueueDrain[A](buffer)
    queue.drain(consume, limit)
    consume.count
  }
}

private[internal] object FromCircularQueue {
  /**
    * Builds a [[FromCircularQueue]] instance.
    */
  def apply[A](queue: ConcurrentCircularArrayQueue[A], ct: ChannelType): FromCircularQueue[A] =
    ct match {
      case ChannelType.MPMC =>
        new MPMC[A](queue)
      case ChannelType.MPSC =>
        if (UnsafeAccess.HAS_JAVA8_INTRINSICS) new Java8MPSC[A](queue)
        else new Java7[A](queue, ct)
      case ChannelType.SPMC =>
        if (UnsafeAccess.HAS_JAVA8_INTRINSICS) new Java8SPMC[A](queue)
        else new Java7[A](queue, ct)
      case ChannelType.SPSC =>
        if (UnsafeAccess.HAS_JAVA8_INTRINSICS) new Java8SPSC[A](queue)
        else new Java7[A](queue, ct)
    }

  private final class MPMC[A](queue: ConcurrentCircularArrayQueue[A]) extends FromCircularQueue[A](queue) {

    def fenceOffer(): Unit = ()
    def fencePoll(): Unit = ()
  }

  private final class Java8SPMC[A](queue: ConcurrentCircularArrayQueue[A]) extends FromCircularQueue[A](queue) {

    private[this] val UNSAFE =
      UnsafeAccess.getInstance().asInstanceOf[Unsafe]

    def fenceOffer(): Unit = UNSAFE.fullFence()
    def fencePoll(): Unit = ()
  }

  private final class Java8MPSC[A](queue: ConcurrentCircularArrayQueue[A]) extends FromCircularQueue[A](queue) {

    private[this] val UNSAFE =
      UnsafeAccess.getInstance().asInstanceOf[Unsafe]

    def fenceOffer(): Unit = ()
    def fencePoll(): Unit = UNSAFE.fullFence()
  }

  private final class Java8SPSC[A](queue: ConcurrentCircularArrayQueue[A]) extends FromCircularQueue[A](queue) {

    private[this] val UNSAFE =
      UnsafeAccess.getInstance().asInstanceOf[Unsafe]

    def fenceOffer(): Unit = UNSAFE.fullFence()
    def fencePoll(): Unit = UNSAFE.fullFence()
  }

  private final class Java7[A](queue: ConcurrentCircularArrayQueue[A], ct: ChannelType)
    extends FromCircularQueue[A](queue) {

    def fenceOffer(): Unit =
      if (ct.producerType == SingleProducer) {
        raise()
      }

    def fencePoll(): Unit =
      if (ct.consumerType == SingleConsumer) {
        raise()
      }

    private def raise(): Unit = {
      throw new IllegalAccessException("Unsafe.fullFence not supported on this platform! (please report bug)")
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy