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

loci.transmitter.ContextBuilder.scala Maven / Gradle / Ivy

The newest version!
package loci
package transmitter

import Transmittable.Delegating
import Transmittables.{Delegates, Message, None}

import java.util.concurrent.atomic.AtomicLong

import scala.annotation.implicitNotFound
import scala.util.{Failure, Success}

@implicitNotFound("Message for some transmittable not serializable: ${T}")
trait ContextBuilder[T <: Transmittables] {
  def apply(
     transmittables: T,  abstraction: AbstractionRef,
     direction: ContextBuilder.Direction, index: Long = 0L)
  : ContextBuilder.Context[T]
}

object ContextBuilder {
  sealed class Direction private[ContextBuilder]

  val sending = new Direction
  val receiving = new Direction

  sealed abstract class Context[S <: Transmittables](
      val remote: RemoteRef,
      val transmittables: S,
      val index: Long,
      val contexts: Contexts[S])
    extends Context.Providing[S] with Context.Receiving[S] {

    def provide[B, I, R, P, T <: Transmittables](
        value: B)(implicit selector: Selector[B, I, R, P, T, S]) = {
      implicit val context = selector context contexts
      (selector transmittable transmittables) buildIntermediate value
    }

    def receive[B, I, R, P, T <: Transmittables](
        value: I)(implicit selector: Selector[B, I, R, P, T, S]) = {
      implicit val context = selector context contexts
      (selector transmittable transmittables) buildResult value
    }
  }

  implicit def messaging[B, I, R, P, T <: Transmittables](implicit
      contextBuilder: ContextBuilder[T],
      serializer: Serializable[I])
  : ContextBuilder[Message[Transmittable.Aux[B, I, R, P, T]]] = {
    type M = Message[Transmittable.Aux[B, I, R, P, T]]

    new ContextBuilder[M] {
      def apply(
          transmittables: M, abstraction: AbstractionRef,
          direction: Direction, index: Long) = {
        val messagingAbstraction = abstraction derive index.toString
        val transmittable = transmittables.message
        val context = contextBuilder(
          transmittable.transmittables,
          messagingAbstraction derive "~0",
          direction)

        new Context[M](
            abstraction.remote, transmittables, index + 1L,
            new Contexts.SingleMessage(context, index)) with
          Context.Endpoint.MessageImpl[B, I, R, P, T] {

          val sendingTurn = new AtomicLong(1)
          val receivingTurn = new AtomicLong(1)

          def serialize(value: B) = {
            val turn = sendingTurn.getAndIncrement()
            val directedTurn = if (direction == sending) s"+$turn" else s"-$turn"
            implicit val context = contextBuilder(
              transmittable.transmittables,
              messagingAbstraction derive directedTurn,
              direction)
            serializer serialize (transmittable buildIntermediate value)
          }

          def deserialize(value: MessageBuffer) = {
            val turn = receivingTurn.getAndIncrement()
            val directedTurn = if (direction == sending) s"-$turn" else s"+$turn"
            implicit val context = contextBuilder(
              transmittable.transmittables,
              messagingAbstraction derive directedTurn,
              direction)
            (serializer deserialize value) map transmittable.buildResult
          }

          val endpoint = new Endpoint[B, R] {
            val doReceive = Notice.Stream[R]

            val closed = messagingAbstraction.channel.closed

            def close() = messagingAbstraction.channel.close()

            def send(value: B) =
              messagingAbstraction.channel.send(serialize(value))

            val receive = doReceive.notice

            messagingAbstraction.channel.receive foreach { value =>
              deserialize(value) match {
                case Failure(exception) =>
                  logging.warn(s"unprocessed channel message: $value", exception)
                case Success(value) =>
                  doReceive.fire(value)
              }
            }
          }
        }
      }
    }
  }

  implicit def delegating[D <: Delegating](implicit
      contextBuilders: ContextBuilders[Delegates[D]])
  : ContextBuilder[Delegates[D]] =
    new ContextBuilder[Delegates[D]] {
      def apply(
          transmittables: Delegates[D], abstraction: AbstractionRef,
          direction: Direction, index: Long) = {
        val context = contextBuilders(transmittables, abstraction, direction, index)
        new Context[Delegates[D]](abstraction.remote, transmittables, context.index, context) with
          Context.Endpoint.DelegatesImpl[D]
      }
    }

  implicit def none: ContextBuilder[None] =
    new ContextBuilder[None] {
      def apply(
          transmittables: None, abstraction: AbstractionRef,
          direction: Direction, index: Long) =
        new Context[None](abstraction.remote, transmittables, index, Contexts.None) with
          Context.Endpoint.NoneImpl
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy