HiveBrain v1.2.0
Get Started
← Back to all entries
snippetcppMinor

Using C++11 move semantics to implement state pattern

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
implementsemanticsmoveusingstatepattern

Problem

I'm implementing a C++ layer on top of the sockets api of the OS (i.e. man 7 socket)1. Tcp sockets go through various states. Using the RAII principle leads to distinguishing the states: unconnected2, bound_to_address, listening and connected. To implement this I use move semantics and constructed to move construct on class of object from an other one:

Implementation

Common base class Socket:

class Socket {
    public:
        explicit Socket(int filedescriptor);
        Socket(Socket&& other);
        Socket& operator=(Socket&& other);
        virtual ~Socket();

        int getFiledescriptor() const;

    private:
        Socket() = delete;
        // Sockets can only be moved copying is not allowed
        Socket(const Socket&) = delete;
        Socket& operator=(const Socket&) = delete;

        static const int NO_FILE = -2;
        private std::atomic filedescriptor;
};


Some of Socket's methods implemented:

Socket::Socket(int filedescriptor_)
    : filedescriptor { filedescriptor_ }
{
    // intentionally left blank
}

Socket::Socket(Socket&& other)
    : filedescriptor { other.filedescriptor.exchange(NO_FILE) }
{
    // intentionally left blank
}

Socket::~Socket()
{
    if (filedescriptor >= 0)
    {
        close(filedescriptor);
        // handle error
    }
}


UnconnectedSocket represents opened sockets that are not yet connected to an other socket or bound to an address:

class UnconnectedSocket: public Socket
{
    public:
        UnconnectedSocket();
        UnconnectedSocket(UnconnectedSocket&& other);
        UnconnectedSocket& operator=(UnconnectedSocket&& other);
        virtual ~UnconnectedSocket();

    private:
        UnconnectedSocket(const UnconnectedSocket&) = delete;
        UnconnectedSocket& operator=(UnconnectedSocket&) = delete;
};


The default constructor calls int socket(int domain, int type, int protocol):

```
namespace {
int createSocket()
{
int fd = socket( AF_INET, S

Solution

I feel as if separating the state description/object/variables from the actual operations feels better--personally, I've coded a state machine for a CAD drawing program in an old, domain-specific form of Lisp that's missing a lot of the OOP and RAII concepts from C++, but I still managed to create a good state machine that was easier to debug by passing around a list of parameters that described the state of the state machine, coding in transitions inside the state functions.

I would say that it would be good to parametrize your state into a variable or external structure instead of derived classes--inheritance, dynamic behavior, and polymorphism can be quite hairy if you keep trying to do this. This way, you won't have to create new classes every time you need to expand or fix behavior, and you won't have to look through multiple classes or files when you have a behavior error--instead, I might code the different states as function objects or closures and then go on from there.

Perhaps what you could do is to call different functions based on the current state, and attach references to the resources you need to pass between states; perhaps you could even move from them as well.

Context

StackExchange Code Review Q#93567, answer score: 3

Revisions (0)

No revisions yet.