如何编写一个没有可变状态的多客户端服务器?

发布于 2024-09-09 03:51:09 字数 309 浏览 5 评论 0原文

我正在研究函数式编程,并在解决一个问题。在没有可变状态的情况下,我该如何执行以下操作?

想象一下我有一个服务器..并且客户端尝试连接..每个客户端给服务器一个数字并被告知当前总数。

现在,如果没有可变状态,服务器就无法保留总数...所以我认为每个客户端实际上是在创建一个包含新总数的新服务器...或者一个保存条目并引用旧服务器的新服务器,以便总数可以是计算出来的。

但是..客户端如何找到服务器?有人必须保留当前的服务器实例..因此他们有一个可变变量“服务器”。

无论我做什么..我总是会得到一个更高范围的可变变量。

想法?

I am looking at functional programming and struggling with one point.. How do I do the following without mutable state?

Imagine I have a server.. and clients try to connect.. and each client gives the server a number and gets told the current total.

Now without mutable state the server can't keep a total... so I am thinking each client is really creating a new server containing a new total.. or a new server holding the entry and referencing the old server so the total can be calculated.

BUT.. how do the client's find the server? Someone has to hold onto the current server instance.. so they have a mutable variable 'server'.

No matter what I do.. I always end up with a mutable variable a the higher scope.

Thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

逆蝶 2024-09-16 03:51:09

您描述的场景可以这样实现(伪代码):

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

let main() = keepTrackOfTotal(0)

这里我们使用递归来获得一个无限循环来跟踪总数,而无需可变变量。

The scenario you describe could be implemented like this (pseudocode):

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

let main() = keepTrackOfTotal(0)

Here we use recursion to get an infinite loop that keeps track of the total, without mutable variables.

葬心 2024-09-16 03:51:09

至少在 Erlang 中,它的完成方式是进程本身有一个名称。

因此,虽然服务器循环不断启动自身的新版本(通过在调用结束时调用相同的函数,如 sepp2k 的优秀伪代码)并将总和作为参数提供,但所有客户端都通过名称联系该进程,所以他们仍然可以找到它。

At least in Erlang the way it's done is that the process itself has a name.

So while the server loop is constantly starting new versions of itself (by calling the same function at the end of the call, like in sepp2k's excellent pseudocode) and feeding in the sum as a parameter, all your clients are contacting that process by name, so they can still find it.

剧终人散尽 2024-09-16 03:51:09

像这样(在 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() 都会返回不可变的服务器对象。
当另一个线程在 Add 方法中工作时,您可以调用 GetTotal() 方法。

Something like this (on C++).
We have static pointer server, each instance of server object is immutable

#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;

Every call of the getInstance() returns of the immutable Server object.
You can call GetTotal() method when another thread work in Add method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文