2013-07-25 7 views
6

मैं स्कैला 2.10 वायदा का उपयोग कर एसिंक लाइब्रेरी बना रहा हूं। लाइब्रेरी के लिए कन्स्ट्रक्टर उपयोगकर्ता परिभाषित ऑब्जेक्ट्स का एक अनुक्रम लेता है जो एक निश्चित विशेषता को लागू करता है, और उसके बाद लाइब्रेरी क्लास पर एक विधि उपयोगकर्ता द्वारा परिभाषित वस्तुओं में एक-एक करके कुछ डेटा भेजती है। मैं चाहता हूं कि उपयोगकर्ता मुख्य उदाहरण स्थापित करते समय एसिंक ऑपरेशंस के लिए ExecutionContext प्रदान करें, और उसके बाद उस संदर्भ के लिए उपयोगकर्ता द्वारा परिभाषित वस्तुओं में आवश्यक हो। सरलीकृत (? छद्म) कोड:निहित ऑब्जेक्ट्स को कॉन्टेक्स्ट करने के लिए निहित ऑब्जेक्ट्स/कॉल विधियों

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] 
} 

वह कुछ इस तरह इस्तेमाल किया जा सकता है:

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") 

    // ... 
} 

मैं ThingProcessor के लिए एक संकलन त्रुटि मिलती है:

एक अंतर्निहित ExecutionContext नहीं खोजा जा सका , या तो खुद को एक की आवश्यकता है या ExecutionContext.Implicits.global

आयात करें

मेरे सवाल है, मैं कैसे परोक्ष की आपूर्ति करते हैं उपयोगकर्ता परिभाषित वस्तुओं (ThingProcessor और PassThroughProcessor) या उपयोगकर्ता (जो कक्षाओं लेखन किया जाएगा) इसके बारे में चिंता किए बिना उनके तरीकों को LibraryObject है ExecutionContext कि - जो है कहने के लिए, मैं पसंद करेंगे उपयोगकर्ता था कि नहीं लिखने की आवश्यकता:

class MyFirstProcessor(implicit context: ExecutionContext) 

या

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

उत्तर

5

निहित गुंजाइश साथी वस्तुओं और आधार के प्रकार के पैरामीटर शामिल कक्षाएं।

या, पुस्तकालय.submit (नई लाइब्रेरी.प्रोसेसर {डीफ़ प्रक्रिया() ...})।

यह काम करता है, लेकिन मेरा पहला विचार, अधिक चतुर होना था जो नहीं था:

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 
} 

अद्यतन:

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

यह सिंगलटन वस्तुओं के लिए नहीं करेगा, स्पष्ट रूप से ... क्या आप एक कामकाज के बारे में सोच सकते हैं? –

+0

@ pagoda_5b क्या आप अपडेट की तरह हैं? अगर मैं स्पष्ट रूप से सोच नहीं रहा हूं तो अग्रिम क्षमा करें। –

+0

हाँ, बहुत चिकना दिखता है और मुझे यह पसंद है। –

संबंधित मुद्दे