2012-02-07 11 views
9

मैं नेटटी लाइब्रेरी (गिटहब से संस्करण 4) का उपयोग कर रहा हूं। यह स्कैला में बहुत अच्छा काम करता है, लेकिन मुझे उम्मीद है कि मेरी लाइब्रेरी असीमित प्रतीक्षा के लिए निरंतरता उत्तीर्ण शैली का उपयोग करने में सक्षम होगी।नेटटी/एनआईओ श्रोताओं के साथ स्कैला निरंतरता का उपयोग

Netty साथ परंपरागत रूप से आप (एक उदाहरण अतुल्यकालिक आपरेशन कनेक्ट) कुछ इस तरह करना होगा:

//client is a ClientBootstrap 
val future:ChannelFuture = client.connect(remoteAddr); 
future.addListener(new ChannelFutureListener { 
    def operationComplete (f:ChannelFuture) = { 
     //here goes the code that happens when the connection is made 
    } 
}) 

आप किसी लाइब्रेरी (जो मैं कर रहा हूँ) तो आप मूल रूप से उपयोगकर्ता की अनुमति के लिए तीन सरल विकल्प हैं कार्यान्वित कर रहे हैं तो कनेक्शन के बाद सामान करने के लिए लाइब्रेरी का:

  1. बस अपनी कनेक्ट विधि से चैनलफ्यूचर वापस करें और उपयोगकर्ता को इसके साथ सौदा करने दें - यह नेटटी से बहुत अधिक अमूर्तता प्रदान नहीं करता है।
  2. एक चैनलफ्यूचरलिस्टर को अपनी कनेक्ट विधि के पैरामीटर के रूप में लें और इसे चैनलफ़्यूचर में श्रोता के रूप में जोड़ें।
  3. अपने कनेक्ट विधि का एक पैरामीटर के रूप में एक कॉलबैक फ़ंक्शन वस्तु ले लो और फोन है कि ChannelFutureListener आपके द्वारा बनाए गए के भीतर से

मैं क्या कर रहा हूँ (यह कुछ हद तक Node.js की तरह एक कॉलबैक चालित शैली के लिए होगा) करने का प्रयास चौथा विकल्प है; मैंने इसे ऊपर की गिनती में शामिल नहीं किया क्योंकि यह आसान नहीं है।

मैं पुस्तकालय के उपयोग के लिए कुछ हद तक एक अवरुद्ध पुस्तकालय तरह बनाने के लिए स्केला सीमांकित निरंतरता का उपयोग करना चाहते हैं, लेकिन यह पर्दे के पीछे nonblocking किया जाएगा:

class MyLibraryClient { 
    def connect(remoteAddr:SocketAddress) = { 
     shift { retrn: (Unit => Unit) => { 
       val future:ChannelFuture = client.connect(remoteAddr); 
       future.addListener(new ChannelFutureListener { 
        def operationComplete(f:ChannelFuture) = { 
         retrn(); 
        } 
       }); 
      } 
     } 
    } 
} 

कल्पना कीजिए अन्य पढ़ें/लिखें आपरेशनों में लागू किया जा रहा वही फैशन इस किया जा रहा है के लक्ष्य को उपयोगकर्ता के कोड अधिक इस तरह दिख सकता है कि:

reset { 
    val conn = new MyLibraryClient(); 
    conn.connect(new InetSocketAddress("127.0.0.1", 1337)); 
    println("This will happen after the connection is finished"); 
} 

दूसरे शब्दों में, कार्यक्रम एक सरल अवरुद्ध शैली कार्यक्रम की तरह दिखाई देगा लेकिन पर्दे के पीछे क्या कोई अवरुद्ध या सूत्रण नहीं होगा ।

जिस समस्या में मैं दौड़ रहा हूं वह यह है कि मैं पूरी तरह से समझ नहीं पा रहा हूं कि सीमित निरंतरता का प्रकार कैसे काम करता है। जब मैं इसे उपर्युक्त तरीके से कार्यान्वित करने का प्रयास करता हूं, तो संकलक शिकायत करता है कि मेरा operationComplete कार्यान्वयन वास्तव में Unit के बजाय देता है। मुझे लगता है कि स्कैला के सीपीएस में एक "गॉचाचा" है जिसमें आपको shift विधि के रिटर्न प्रकार को @suspendable के साथ एनोटेट करना होगा, जो reset तक कॉल स्टैक पास कर लेता है, लेकिन ऐसा लगता है कि मेल करने का कोई तरीका नहीं है कि एक पूर्व-मौजूदा जावा लाइब्रेरी के साथ जिसमें सीमित निरंतरता की कोई अवधारणा नहीं है।

मुझे लगता है कि वास्तव में इसके आसपास एक रास्ता होना चाहिए - अगर स्वार निरंतर क्रमबद्ध कर सकता है और नेटवर्क पर उन्हें कहीं और गणना करने के लिए जाम कर सकता है, तो बस पूर्व-मौजूदा जावा क्लास से निरंतरता को कॉल करना संभव है। लेकिन मैं यह नहीं समझ सकता कि यह कैसे किया जा सकता है। ऐसा करने के लिए मुझे स्कैला में नेटटी के पूरे हिस्सों को फिर से लिखना होगा?

+0

मैं howto स्केला सामान को ठीक पता नहीं है, लेकिन मैं अपने विचार के खिलाफ सुझाव देते हैं। मुझे बताने दीजिए कि क्यों। लेकिन उपयोगकर्ता को आपके libary की एसिंक प्रकृति के "अनजान" बनाने के लिए आप उसे बताएंगे कि श्रोता कोड में "अवरुद्ध" कॉल करना ठीक है। असल में वह नहीं जानता कि वह श्रोताओं में भी अपना कोड लिखता है। श्रोता में अवरुद्ध कॉल करने से सभी प्रकार की समस्याएं हो सकती हैं। समस्या जो आप अधिकतर बार देखेंगे वह यह है कि यह अन्य io-कार्यों को "धीमा" करता है और इसलिए troughput को सीमित करता है। –

+1

आपके पास एक अच्छा बिंदु है, लेकिन मैं असहमत हूं। मुझे लगता है कि मेरी लाइब्रेरी का उपयोगकर्ता, यदि मेरे अलावा कोई भी है, तो शायद यह समझना होगा कि 'रीसेट' किस प्रकार से शुरू होता है, और इस प्रकार यह समझ जाएगा कि कॉल गैर-अवरुद्ध हैं। यह वास्तव में ए के लिए एक तरीका है ए) सीमित निरंतरता की गहरी समझ प्राप्त करें, और बी) क्लीनर तरीके से कॉलबैक-संचालित कोड को लिखने के साथ प्रयोग करें। – Jeremy

उत्तर

4

मुझे शुरू होने पर Scala's continuations के इस स्पष्टीकरण को बहुत उपयोगी पाया गया। विशेष रूप से उन हिस्सों पर ध्यान दें जहां वह shift[A, B, C] और reset[B, C] बताते हैं। operationComplete के अंतिम विवरण के रूप में एक डमी null जोड़ना चाहिए।

बीटीडब्ल्यू, आपको retrn() को अन्य reset के अंदर डालने की आवश्यकता है यदि इसमें shift इसके अंदर घोंसला हो।

संपादित करें: यहाँ एक काम उदाहरण

import scala.util.continuations._ 
import java.util.concurrent.Executors 

object Test { 

    val execService = Executors.newFixedThreadPool(2) 

    def main(args: Array[String]): Unit = { 
    reset { 
     val conn = new MyLibraryClient(); 
     conn.connect("127.0.0.1"); 
     println("This will happen after the connection is finished"); 
    } 
    println("Outside reset"); 
    } 
} 

class ChannelFuture { 
    def addListener(listener: ChannelFutureListener): Unit = { 
    val future = this 
    Test.execService.submit(new Runnable { 
     def run(): Unit = { 
     listener.operationComplete(future) 
     } 
    }) 
    } 
} 

trait ChannelFutureListener { 
    def operationComplete(f: ChannelFuture): Unit 
} 

class MyLibraryClient { 
    def connect(remoteAddr: String): [email protected][Unit] = { 
    shift { 
     retrn: (Unit => Unit) => { 
     val future: ChannelFuture = new ChannelFuture() 
     future.addListener(new ChannelFutureListener { 
      def operationComplete(f: ChannelFuture): Unit = { 
      println("operationComplete starts") 
      retrn(); 
      null 
      } 
     }); 
     } 
    } 
    } 
} 
एक संभव उत्पादन के साथ

है:

Outside reset 
operationComplete starts 
This will happen after the connection is finished 
+0

वास्तव में यह संकलक को खुश बनाता है और यहां तक ​​कि ठीक से काम करने लगता है। मुझे लगता है कि कुंजी यह है कि आपने अनाम 'चैनलफ्यूचर लिस्टनर' के बाहर 'शिफ्ट' को स्थानांतरित किया है और 'ऑपरेशन पूर्ण' के अंदर से निरंतरता को कॉल करने के लिए बंद कर दिया है। मुझे यकीन नहीं है कि मैं समझता हूं कि यह क्यों काम करता है और दूसरा तरीका नहीं है, लेकिन मैं इसे ले जाऊंगा। धन्यवाद! – Jeremy

+0

और यह स्कैला की निरंतरताओं के बारे में बहुत अच्छा पढ़ा गया है। उन्हें निरंतरता के बारे में scala-lang.org पृष्ठ से बेकार उदाहरणों को हटा देना चाहिए, और उन्हें आपके द्वारा लिंक किए गए लेख से प्रतिस्थापित करना चाहिए। – Jeremy

+0

@ जेरेमी हाँ, वह लेख बहुत अच्छा है :) – shams

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