2011-09-03 16 views
12

में स्काला @suspendable विधि मैं एक नींद समारोह है लगता है।परिवर्तित एक भविष्य

def future(targetFunc: (Int => Unit @suspendable)) : (Int => Future) = { 
    .... 
} 

class Future { 
    def await : Unit @suspendable = { 
    .... 
    } 
} 

आप इस तरह कुछ करने के लिए सक्षम होना चाहिए:

reset { 
    val sleepAsync = future(sleep) 
    val future1 = sleepAsync(2000) 
    val future2 = sleepAsync(3000) 
    future1.await 
    future2.await 
    /* finishes after a delay of 3000 */ 
} 

sleepAsync करने के लिए दो कॉल सीधे वापस जाने के लिए दिखाई देनी चाहिए और भविष्य # करने के लिए दो कॉल का इंतजार ब्लॉक करने के लिए दिखाई देनी चाहिए। बेशक वे सभी वास्तव में रीसेट के अंत से गिर जाते हैं और देरी के बाद निरंतरता को कॉल करने के लिए कोड जिम्मेदार होता है।

अन्यथा समानांतर में दो @ सस्पेंडेबल फ़ंक्शंस चलाने के लिए एक वैकल्पिक तरीका है और दोनों को पूरा करने की प्रतीक्षा करें?

मैं क्या मैं करना चाहता हूँ की एक कंकाल के साथ एक compilable सार है: https://gist.github.com/1191381

+0

मैंने यह लिखा: https://gist.github.com/1191571 जो काम करता प्रतीत होता है लेकिन यह काफी जटिल लगता है। मुझे लगता है कि मुझे ऐसा करने का एक आसान तरीका याद आ रहा है। – benmmurphy

+0

को यह भी मिला: http://days2011.scala-lang.org/node/138/288 जो इसे और अधिक अच्छी तरह से करने लगता है। – benmmurphy

+0

क्या आपके पास "जीतने" उत्तर के लिए प्राथमिकता है? मुझे बक्षीस पुरस्कार देने की जरूरत है। –

उत्तर

1

मुझे यकीन है कि मैं पूरी तरह से सवाल समझ में नहीं हूँ, लेकिन यहाँ एक कोशिश है:

import scala.util.continuations._ 

class Future(thread: Thread) { 
    def await = thread.join 
} 

object Future { 

    def sleep(delay: Long) = Thread.sleep(delay) 

    def future[A,B](f: A => B) = (a: A) => shift { k: (Future => Unit) => 
    val thread = new Thread { override def run() { f(a) } } 
    thread.start() 

    k(new Future(thread)) 
    } 

    def main(args:Array[String]) = reset { 
    val sleepAsync = future(sleep) 
    val future1 = sleepAsync(2000) // returns right away 
    val future2 = sleepAsync(3000) // returns right away 
    future1.await // returns after two seconds 
    future2.await // returns after an additional one second 
    // finished after a total delay of three seconds 
    } 
} 

यहाँ, Future उदाहरण Thread पर हैंडल से अधिक कुछ नहीं है, इसलिए आप इसे समाप्त होने तक ब्लॉक करने के लिए join विधि का उपयोग कर सकते हैं।

future समारोह प्रकार A => B के एक समारोह लेता है, और एक फ़ंक्शन, जो जब एक A के साथ आपूर्ति की "futured" समारोह को चलाने के लिए एक धागा शुरू होगा, और एक Future, जो वापस इंजेक्ट किया जाता है में यह लपेट निरंतरता में, इस प्रकार इसे val future1 पर असाइन किया गया।

क्या यह कहीं भी आप के लिए जा रहे थे के करीब है?

+0

मैं धागे – benmmurphy

+0

के बजाय निरंतरता का उपयोग करना चाहता था, हालांकि आप चाहें तो निरंतरताएं चला सकते हैं, लेकिन किसी भी तरह उन्हें वर्तमान धागे से बाहर निकलने की आवश्यकता है (अन्यथा कुल रन टाइम 3000 एमएस के बजाय 5000 एमएस होगा)। अभ्यास में आप शायद अपने 'थ्रेड' उदाहरण बनाने के बजाय थ्रेड पूल का उपयोग करेंगे। आप 'भविष्य 1' और 'भविष्य 2' को कैसे चला सकते हैं? – earldouglas

+0

आह। मैं चाहता हूं कि भविष्य एक निलंबित कार्य करने में सक्षम हो, सामान्य कार्य नहीं – benmmurphy

2
object Forks { 

    import scala.util.continuations._ 

    case class Forker(forks: Vector[() => Unit @suspendable]) { 
    def ~(block: => Unit @suspendable): Forker = Forker(forks :+ (() => block)) 
    def joinIf(pred: Int => Boolean): Unit @suspendable = shift { k: (Unit => Unit) => 
     val counter = new java.util.concurrent.atomic.AtomicInteger(forks.size) 
     forks foreach { f => 
     reset { 
      f() 
      if (pred(counter.decrementAndGet)) k() 
     } 
     } 
    } 
    def joinAll() = joinIf(_ == 0) 
    def joinAny() = joinIf(_ == forks.size - 1) 
    } 

    def fork(block: => Unit @suspendable): Forker = Forker(Vector(() => block)) 
} 

फोर्क() का उपयोग करके, अब हम कई "निलंबन" का इंतजार कर सकते हैं। निलंबन के साथ चेन करने के लिए ~() का उपयोग करें। सभी Susendables के लिए प्रतीक्षा करने के लिए joinAll() का उपयोग करें और केवल एक के लिए प्रतीक्षा करने के लिए कोई() शामिल हों। जुड़ें रणनीति को अनुकूलित करने के लिए joinIf() का उपयोग करें।

object Tests extends App { 

    import java.util.{Timer, TimerTask} 
    import scala.util.continuations._ 

    implicit val timer = new Timer 

    def sleep(ms: Int)(implicit timer: Timer): Unit @suspendable = { 
    shift { k: (Unit => Unit) => 
     timer.schedule(new TimerTask { 
     def run = k() 
     }, ms) 
    } 
    } 

    import Forks._ 

    reset { 
    fork { 
     println("sleeping for 2000 ms") 
     sleep(2000) 
     println("slept for 2000 ms") 
    } ~ { 
     println("sleeping for 4000 ms") 
     sleep(4000) 
     println("slept for 4000 ms") 
    } joinAll() 
    println("and we are done") 
    } 
    println("outside reset") 
    readLine 
    timer.cancel 
} 

और यह आउटपुट है। कार्यक्रम समय पर शुरू होता है टी:

sleeping for 2000 ms 
sleeping for 4000 ms 
outside reset   <<<<<< T + 0 second 
slept for 2000 ms  <<<<<< T + 2 seconds 
slept for 4000 ms  <<<<<< T + 4 seconds 
and we are done  <<<<<< T + 4 seconds 
संबंधित मुद्दे