2010-07-11 12 views
6

मैं कार्यात्मक प्रोग्रामिंग देख रहा हूं और एक बिंदु से संघर्ष कर रहा हूं .. मैं बिना किसी व्यवहार्य स्थिति के निम्नलिखित कैसे कर सकता हूं?मैं एक बहु-क्लाइंट सर्वर कैसे लिख सकता हूं जिसमें उत्परिवर्तनीय स्थिति नहीं है?

कल्पना कीजिए कि मेरे पास एक सर्वर है .. और क्लाइंट कनेक्ट करने का प्रयास करते हैं .. और प्रत्येक क्लाइंट सर्वर को एक नंबर देता है और वर्तमान कुल को बताया जाता है।

अब परिवर्तनीय स्थिति के बिना सर्वर कुल नहीं रख सकता है ... इसलिए मैं सोच रहा हूं कि प्रत्येक क्लाइंट वास्तव में एक नया सर्वर बना रहा है जिसमें एक नया कुल .. या एक नया सर्वर है जो पुराने सर्वर को प्रविष्टि और संदर्भित करता है कुल गणना की जा सकती है।

लेकिन .. ग्राहक को सर्वर कैसे ढूंढता है? किसी को वर्तमान सर्वर इंस्टेंस पर पकड़ना है .. इसलिए उनके पास एक परिवर्तनीय चर 'सर्वर' है।

कोई फर्क नहीं पड़ता कि मैं क्या करता हूं .. मैं हमेशा एक परिवर्तनीय चर के साथ एक उच्च दायरा के साथ समाप्त होता हूं।

विचार?

उत्तर

5

परिदृश्य आप का वर्णन इस (स्यूडोकोड) की तरह लागू किया जा सकता:

let keepTrackOfTotal(total) = 
    let conn = waitForConnection() 
    let x = readIntFrom(conn) 
    let newTotal = total + x 
    writeIntTo(conn, newTotal) 
    keepTrackOfTotal(newTotal) 

let main() = keepTrackOfTotal(0) 

यहाँ हम प्रत्यावर्तन का उपयोग अनंत लूप है कि कुल का ट्रैक रखता है पाने के लिए अस्थायी चर के बिना,।

+0

मैं यह कैसे एकाधिक अनुक्रमिक ग्राहकों के साथ काम करेंगे देख सकते हैं। क्या यह एक मल्टीकोर समानांतर प्रणाली में काम करेगा? क्या यह अनुक्रमिक होने के लिए मजबूर करता है? –

+0

यह अनुक्रमिक होने के लिए मजबूर करता है, क्योंकि यह एक समय में केवल एक कनेक्शन को संभाल सकता है। मल्टीकोर के साथ समस्या यह है कि आप कनेक्शन (कनेक्शन) से इनकार कर सकते हैं। इसके साथ निपटने के लिए अक्सर आपके पास कुछ प्रकार का तंत्र होता है। एरलांग का तंत्र यह है कि आपके सभी ग्राहक आपके सर्वर को एक संदेश भेज दें जो प्रसंस्करण के लिए कतार में रखा जाता है। यह एकमात्र तरीका नहीं है, हालांकि मैं दूसरों से बहुत परिचित नहीं हूं। –

+0

दिलचस्प बात यह है कि यह एक ढेर के रूप में एक परिपत्र समाधान के रूप में ही आप अपने ढेर के लिए दो ग्राहक हैं परिवर्तनशील राज्य है (यानी। एक पुशर और एक खींचने) ... क्योंकि अपरिवर्तनीय ढेर नए स्टैक का उत्पादन जब आप धक्का या पॉप ... इसलिए पुशर और पुलर दोनों एक ही कतार में बात कैसे कर सकते हैं। :) –

3

कम से कम एरलांग में ऐसा करने का तरीका यह है कि प्रक्रिया का नाम ही है।

तो सर्वर लूप लगातार अपने स्वयं के नए संस्करण शुरू कर रहा है (कॉल के अंत में उसी फ़ंक्शन को कॉल करके, sepp2k के उत्कृष्ट छद्म कोड में) और पैरामीटर के रूप में योग में भोजन करके, आपके सभी ग्राहक संपर्क कर रहे हैं नाम से प्रक्रिया, ताकि वे अभी भी इसे पा सकें।

0

ऐसा कुछ (सी ++ पर)। हम स्थिर सूचक सर्वर है, सर्वर वस्तु के प्रत्येक उदाहरण

#include <pthread.h> 
#include <iostream> 
#include <stdlib.h> 
#include <memory> 

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; 

class Server 
{ 
public: 
    Server(int n) : m_n(n){} 
    static void Add(int n) 
    {   
     pthread_mutex_lock(&mutex1); 
     std::auto_ptr<const Server> srv(getInstance()); 
     server = new Server(srv->m_n + n); 
     pthread_mutex_unlock(&mutex1); 
    } 
    static int GetTotal() 
    { 
     std::auto_ptr<const Server> srv(getInstance()); 
     return srv->m_n; 
    } 

private: 

    static const Server* getInstance() 
    { 
     if (server == NULL) 
      server = new Server(0); 

     return new Server(server->m_n); 
    } 
    static volatile const Server* server; 
    int const m_n; 
}; 
volatile const Server* Server::server = NULL; 

getInstance का हर कॉल() अपरिवर्तनीय सर्वर वस्तु के रिटर्न अपरिवर्तनीय है। जब आप कोई अन्य थ्रेड ऐड विधि में काम करते हैं तो आप GetTotal() विधि को कॉल कर सकते हैं।

+1

आपको वास्तव में नहीं मिला हालांकि यहां परिवर्तनशीलता के आसपास। आपने इसे एक परिवर्तनीय 'सर्वर' चर रखने के लिए बस एक परिवर्तनीय' कुल' चर होने से स्थानांतरित कर दिया है। – sepp2k