2013-01-18 52 views
5

मैं डी के लिए नया हूं और मैं अभ्यास के लिए एक साधारण बहुप्रचारित सर्वर लिख रहा हूं। सी में क्लाइंट हैंडलर थ्रेड्स शुरू करने के लिए एक सामान्य प्रतिमान pthread_create() में नए स्वीकार्य() एड सॉकेट के फ़ाइल डिस्क्रिप्टर को पास करना है, लेकिन डी की std.concurrency.spawn() मुझे सॉकेट पास करने की अनुमति नहीं देगी क्योंकि यह उत्परिवर्तनीय है और दो धागे से सुलभ।उत्परिवर्तनीय थ्रेड-स्थानीय डेटा के लिए उपनाम

बेशक, मैं वास्तव में एक अपरिवर्तनीय सॉकेट नहीं चाहता हूं (यही कारण है कि मैं इसे मुख्य धागे में नहीं डालना चाहता हूं जब तक कि मुझे नहीं करना चाहिए) - मैं एक उत्परिवर्तनीय को पास करना चाहता हूं और इसे प्राप्त करना चाहता हूं मुख्य धागे में गुंजाइश से बाहर जाओ। मैं इसे किस तरह लूं? धागे को सॉकेट का उपयोग करने के लिए (/ can) मैं tid.send(s) का उपयोग करना चाहिए? किसी कारण से जो मेरे लिए बहुत गुस्सा लगता है।

मेरे अब कोड:

void main() { 
    Socket listener = new TcpSocket; 
    ... 
    for (;;) { 
     Socket s = listener.accept(); 
     scope(exit) s.close(); 

     auto tid = spawn(&clientHandler, s); 
    } 
} 

void clientHandler(Socket s) { 
    ... 
} 

कौन सा पैदा करता है: त्रुटि: स्थिर ज़ोर "परिवर्तनशील धागे की स्थानीय डेटा को उपनाम अनुमति नहीं है।" ... यहां से तत्काल: स्पॉन! (सॉकेट)

उत्तर

6

आप ClientHandler में करने के लिए साझा सॉकेट डाली और फिर से वापस करने की जरूरत है

auto tid = spawn(&clientHandler, cast(shared) s); 

void clientHandler(shared Socket s) { 
    Socket sock = cast(Socket)s; 
    scope(exit)sock.close(); 
} 

इस का कारण यह है कि सभी स्थानीय चर अनुमानित साझा या अपरिवर्तनीय कर सकते हैं करने के लिए केवल संदर्भ स्थानीय थ्रेड रहे हैं जब तक निर्दिष्ट shared, और है spawn (या send) के लिए तर्क के रूप में पारित किया जाना चाहिए, जबकि मूल्य (संदर्भ और प्राइमेटिव के बिना structs) ठीक है

आपको अपने वर्तमान कार्यान्वयन के साथ ही हैंडलर को बंद करना चाहिए, सॉकेट की संभावना पहले बंद हो जाएगी newl y spawned thread को

+0

पूरी तरह से काम किया, और अतिरिक्त जानकारी के लिए धन्यवाद! क्या यह ऐसा कुछ करने का बेवकूफ तरीका है, या क्या कोई बेहतर तरीका है? डी में कास्टिंग निश्चित रूप से महसूस करता है जैसे मैं कुछ गलत कर रहा हूं (यानी सी के विपरीत)। – Dan

+0

@Dan पिछली बार मैंने चेक किया (एक साल पहले) 'साझा' के अर्थशास्त्र जहां अच्छी तरह से परिभाषित नहीं किया गया था, मुझे नहीं पता कि तब से –

+1

उसमें से कुछ भी नहीं बदला गया है। लेकिन पूरा डी समुदाय 'साझा' के लिए अच्छी तरह परिभाषित होने का इंतजार कर रहा है। – DejanLekic

1

यहां समस्या सॉकेट नहीं है, जो एक स्थानीय चर है। यह क्लाइंट हैंडलर है, जिसकी घोषणा आपने नहीं दिखाई है, लेकिन स्पष्ट रूप से यह थ्रेड-लोकल है क्योंकि यह त्रुटि संदेश में कहता है, जब प्रति स्वीकृत सॉकेट में नया होना चाहिए। संकेत 'उपनाम' शब्द है, जो & ऑपरेटर को संदर्भित करता है।

+0

चलाने का मौका है, क्षमा करें, मैंने 'क्लाइंट हैंडलर() 'की घोषणा जोड़कर प्रश्न स्पष्ट किया है। यह वैश्विक क्षेत्र में घोषित एक समारोह है, इसलिए शायद मैं मूल रूप से सोचा की तुलना में अधिक उलझन में हूं, लेकिन मुझे संदेह है कि यह प्रश्न में थ्रेड-स्थानीय डेटा है। – Dan

+0

@ डैन ठीक है, तो क्या है? सॉकेट नहीं, जब तक स्कोप() पर कुछ प्रभाव नहीं पड़ता है, जो कुछ भी करता है: मैं कोई 'डी' विशेषज्ञ नहीं हूं। – EJP

+0

'दायरा (निकास)' यह सुनिश्चित करता है कि इस दायरे के अंत में 's.close()' को कॉल किया जाएगा, जावा में 'अंततः' कीवर्ड की तरह। माना जाता है कि यह एक टन का अर्थ नहीं बनाता है जहां मैंने इसे जोड़ा, लेकिन इसे हटाने या इसे कहीं और रखने से संकलन त्रुटि पर कोई प्रभाव नहीं पड़ता है। मैंने पढ़ा है कि [वैश्विक चर] (http://dlang.org/migrate-to-shared.html) स्वचालित रूप से थ्रेड-लोकल में परिवर्तित हो जाते हैं, लेकिन यह फ़ंक्शंस पर लागू नहीं होना चाहिए, और फ़ंक्शन उपनाम को किसी भी दर पर बदलना चाहिए (स्थानीय, मुझे लगता है) lambda अभिव्यक्ति के परिणाम एक ही त्रुटि में परिणाम। – Dan