Как я могу записать мультиклиент-сервер, который не имеет изменяемого состояния?

Я смотрю на функциональное программирование и борюсь с одной точкой.. Как я делаю следующее без изменяемого состояния?

Предположите, что у меня есть сервер.. и клиенты пытаются соединиться.. и каждый клиент дает серверу число и сказан текущее общее количество.

Теперь без изменяемого состояния сервер не может сохранить общее количество..., таким образом, я думаю, что каждый клиент действительно создает новый сервер, содержащий новое общее количество.. или может быть вычислен новый сервер, содержащий запись и ссылающийся на старый сервер так общее количество.

НО.. как клиент находит сервер? Кто-то должен держать на текущий экземпляр сервера.. таким образом, у них есть изменяемый переменный 'сервер'.

Независимо от того, что я делаю.. Я всегда заканчиваю с изменяемой переменной более высокий объем.

Мысли?

6
задан Nigel Thorne 11 July 2010 в 12:42
поделиться

3 ответа

Описанный вами сценарий может быть реализован следующим образом (псевдокод):

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

let main() = keepTrackOfTotal(0)

Здесь мы используем рекурсию, чтобы получить бесконечный цикл, который отслеживает общее количество без изменяемых переменных.

5
ответ дан 16 December 2019 в 21:33
поделиться

По крайней мере, в Erlang это делается так, что сам процесс имеет имя.

Таким образом, пока цикл сервера постоянно запускает новые версии самого себя (вызывая ту же функцию в конце вызова, как в отличном псевдокоде sepp2k) и вводя сумму в качестве параметра, все ваши клиенты связываются с этим процессом. по имени, чтобы они все еще могли его найти.

3
ответ дан 16 December 2019 в 21:33
поделиться

Примерно так (на C ++). У нас есть сервер со статическим указателем, каждый экземпляр объекта сервера неизменен

#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 () возвращает неизменяемый объект Server. Вы можете вызвать метод GetTotal (), когда другой поток работает в методе Add.

0
ответ дан 16 December 2019 в 21:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: