Passing implicit ExecutionContext to contained objects/called methods

前端 未结 1 1421
说谎
说谎 2021-01-02 17:30

I\'m creating an async library using Scala 2.10 futures. The constructor for the library takes a sequence of user-defined objects that implement a certain trait, and then a

相关标签:
1条回答
  • 2021-01-02 18:24

    The implicit scope includes companion objects and type parameters of base classes.

    Or, library.submit(new library.Processor { def process() ... }).

    This works, but wasn't my first thought, which was to be more clever:

    import concurrent._
    import concurrent.duration._
    
    class Library(implicit xc: ExecutionContext = ExecutionContext.global) {
      trait Processor {
        implicit val myxc: ExecutionContext = xc
        def process(i: Future[Int]): Future[Int]
      }
    
      def submit(p: Processor) = p process future(7)
    }
    
    object Test extends App {
      val library = new Library
      val p = new library.Processor {
        def process(i: Future[Int]) = for (x <- i) yield 2 * x
      }
      val res = library submit p
      val z = Await result (res, 10.seconds)
      Console println z
    }
    

    Update:

    import concurrent._
    import concurrent.duration._
    import java.util.concurrent.Executors
    
    class Library()(implicit xc: ExecutionContext = ExecutionContext.global) {
      trait Processor {
        implicit val myxc: ExecutionContext = xc
        def process(i: Future[Int]): Future[Int]
      }
    
      def submit(p: Processor) = p process future(7)
    }
    
    object ctx {
      val xc = ExecutionContext fromExecutorService Executors.newSingleThreadExecutor
    }
    object library1 extends Library
    object library2 extends Library()(ctx.xc)
    object p extends library1.Processor {
      def process(i: Future[Int]) = for (x <- i) yield 2 * x
    }
    object q extends library2.Processor {
      def process(i: Future[Int]) = for (x <- i) yield 3 * x
    }
    
    object Test extends App {
      val res = library1 submit p
      //val oops = library2 submit p
      //val oops = library1 submit q
      val z = Await result (res, 10.seconds)
      Console println z
      Console println (Await result (library2 submit q, 10.seconds))
      ctx.xc.shutdownNow()
    }
    

    It isn't much of a stretch to:

    class Library(implicit xc: ExecutionContext = ExecutionContext.global) {
    
      def submit(p: Processor): Future[Int] = p dueProcess future(7)
    }
    trait Processor {
      implicit var myxc: ExecutionContext = _
      def dueProcess(i: Future[Int])(implicit xc: ExecutionContext) = {
        myxc = xc
        process(i)
      }
      protected def process(i: Future[Int]): Future[Int]
    }
    
    object ctx {
      val xc = ExecutionContext fromExecutorService Executors.newSingleThreadExecutor
    }
    object Test extends App {
      def db() = Console println (new Throwable().getStackTrace mkString ("TRACE [\n  ", "\n  ", "\n]"))
      val library = new Library()(ctx.xc)
      val p = new Processor {
        protected def process(i: Future[Int]) = for (x <- i) yield { db(); 2 * x }
      }
      val res = library submit p
      val z = Await result (res, 10.seconds)
      Console println z
      ctx.xc.shutdownNow()
    }
    
    0 讨论(0)
提交回复
热议问题