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

it.unibo.scafi.lib.DynamicCode.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2016-2019, Roberto Casadei, Mirko Viroli, and contributors.
 * See the LICENSE file distributed with this work for additional information regarding copyright ownership.
*/

package it.unibo.scafi.lib

trait StdLibDynamicCode {
  self: StandardLibrary.Subcomponent =>

  trait DynamicCode extends FieldUtils {
    self: FieldCalculusSyntax =>

    /**
      * Mobile functions `fun` should be transferable (i.e., no closures etc), aggregate functions.
      * - If they do note use `aggregate`, they might try to align with functions of other versions,
      *   causing unexpected behaviours and errors.
      */
    final case class Fun[T,R](ver: Int, fun: (T)=>R)

    type Injecter[T,R] = () => Fun[T,R]

    /**
      * Enacts a simple gossip process that supports spreading updated versions of functions.
      * NOTE: different functions running in different parts of the system means that
      * the system is partitioned (by the function identity).
      */
    def up[T,R](injecter: Injecter[T,R]): Fun[T,R] = rep(Fun[T,R](Int.MinValue, _ => ???)){ case f =>
      foldhood(injecter())((f1,f2) => if(f1.ver>=f2.ver) f1 else f2)(nbr{f})
    }

    import Builtins.Bounded

    def exec[T,R:Bounded](procs: List[Fun[T,R]], arg: T, maxVer: Int, curVer: Int, numNbrs: Int, Null: R): (R,Int) = {
      val Fun(headVer,headFun) = procs.head
      // If the version of the head of the list is >= of the min version exec by any neighbour, let's run it
      val curOutcome =
        branch(headVer >= minHood(nbr(curVer))){ headFun.apply(arg) }{ Null }
      // If the version of the head of the list is lower than max, let's recur
      val next =
        branch(headVer < maxVer){ exec(procs.tail, arg, maxVer, curVer, numNbrs, Null) }{ (Null,-1) }
      // If this is the max version and every device has it, let's run it,
      //  otherwise let's return next, i.e., the most up-to-date result
      mux(next._2 < 0 & numNbrs==includingSelf.sumHood(nbr(1))){ (curOutcome, headVer) }{ next }
    }

    def safeUp[T,R:Bounded](injecter: Injecter[T,R], arg: T, Null: R): R =
      rep((List[Fun[T,R]](), -1, -1, Null)) { case (procs, maxVer, curVer, field) =>
        val (newMaxVer, nProcs) = includingSelf.maxHoodSelector(nbr{maxVer})(nbr{(maxVer, procs)})
        val (nnewMaxVer, nnProcs) = branch(injecter().ver > newMaxVer){
          (injecter().ver, nProcs++List(injecter()))
        }{
          (newMaxVer, nProcs)
        }
        val x = exec(nnProcs, arg, nnewMaxVer, curVer, includingSelf.sumHood(nbr(1)), Null)
        (nnProcs, nnewMaxVer, x._2, x._1)
      }._4
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy