2013-07-25 14 views
6

Scala 2.10 futures kullanarak bir uyumsuz kütüphanesi oluşturuyorum. Kütüphane için kurucu, belirli bir özelliği uygulayan bir dizi kullanıcı tanımlı nesneler alır ve daha sonra kütüphane sınıfındaki bir metot, birtakım verileri kullanıcı tanımlı objelere tek tek gönderir. Kullanıcının, ana örneği ayarlarken async işlemleri için ExecutionContext sağlamasını ve ardından, kullanıcı bağlamında nesnelerin gerektiği şekilde geçirilmesini sağlamak için bu bağlamı istiyorum. Basitleştirilmiş (? Sözde) kodu:Kapsanan ExecutionContext içeriğinde bulunan nesneler/yöntemler deneniyor

case class Response(thing: String) 

class LibraryObject(stack: Seq[Processor])(implicit context: ExecutionContext) { 
    def entryPoint(data: String): Future[Response] = { 
    val response = Future(Response("")) 
    stack.foldLeft(response) { (resp, proc) => proc.process(data, resp) } 
    } 
} 

trait Processor { 
    def process(data: String, resp: Future[Response]): Future[Response] 
} 

Böyle bir şey kullanılmış olabilir:

class ThingProcessor extends Processor { 
    override def process(data: String, response: Future[Response]) = { 
    response map { _.copy(thing = "THE THING") } 
    } 
} 

class PassThroughProcessor extends Processor { 
    override def process(request: Request, response: Future[Response]) = { 
    response 
    } 
} 

object TheApp extends App { 
    import ExecutionContext.Implicits.global 

    val stack = List(
    new ThingProcessor, 
    new PassThroughProcessor 
) 
    val libObj = new LibraryObject(stack) 

    val futureResponse = libObj.entryPoint("http://some/url") 

    // ... 
} 

Ben ThingProcessor için bir derleme hatası alıyorum:

örtük bir ExecutionContext bulamıyor ya kendiniz ister veya ExecutionContext.Implicits.global

Sorum ben örtülü olarak kullanıcı tanımlı nesneler (ThingProcessor ve PassThroughProcessor) veya kullanıcıyı (kim sınıfları yazılı olacak) bu konuda endişe yapmadan kendi yöntemlerine LibraryObject sahiptir ExecutionContext olduğunu arz, nasıl olduğunu - yani

class MyFirstProcessor(implicit context: ExecutionContext) 

veya

override def process(...)(implicit context: ExecutionContext) = { ... } 

cevap

5

örtülü kapsam arkadaşı nesneleri ve baz türü parametrelerini içerir: Ben kullanıcı değil yazmak zorunda yaptığını tercih ediyorum, demek sınıflar.

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

Bu çalışır, ancak daha zeki olacaktı benim ilk düşünce, değildi:

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 
} 

Güncelleme: Bir streç kadar çok değil

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() 
} 

:

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() 
} 
+1

Bu, singleton nesneleri için geçerli olmayacak ... açık bir çözüm bulabilir misiniz? –

+0

@ pagoda_5b güncellemeyi mi kastediyorsunuz? Açıkça düşünmüyorsam özür dilerim. –

+0

Evet, oldukça kaygan görünüyor ve hoşuma gidiyor. –

İlgili konular