snippetcppMinor
Using C++11 move semantics to implement state pattern
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:
Implementation
Common base class
Some of
The default constructor calls
```
namespace {
int createSocket()
{
int fd = socket( AF_INET, S
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.
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.