|
- #pragma once
-
- #include <atomic>
- #include <mutex>
- #include <condition_variable>
-
- /**
- * Messaging protocol between client and server.
- *
- * This protocol has the following goals:
- * It is easy to implement.
- * It is easy to understand.
- * It is thread safe.
- * The client's thread will never block.
- *
- * Basics of the protocol:
- * Client initiates all communication.
- * For every message sent client -> server, the server will send once back.
- * The message objects are owned by whoever created them. Passing
- * a message does not transfer ownership.
- * Only one message may be "in play" at a time. Until the client
- * receives a reply from the server, it may not send another message.
- */
-
-
- /**
- * Base class for messages passed between client and server threads.
- * Receivers of message will typically examine the "type", and down-cast
- * based on that.
- */
- class ThreadMessage
- {
- public:
- enum class Type
- {
- TEST1,
- TEST2,
- NOISE // used by ColoredNoise
- };
- ThreadMessage(Type t) : type(t)
- {
- ++_dbgCount;
- }
- virtual ~ThreadMessage()
- {
- --_dbgCount;
- }
-
- const Type type;
- static std::atomic<int> _dbgCount;
- };
-
- /**
- * ThreadServer and ThreadClient do not refer to each other directly.
- * Instead, they both maintain pointers to ThreadSharedState.
- * All communication between thread goes through here.
- */
- class ThreadSharedState
- {
- public:
- ThreadSharedState()
- {
- ++_dbgCount;
- serverRunning.store(false);
- serverStopRequested.store(false);
- mailboxClient2Server.store(nullptr);
- mailboxServer2Client.store(nullptr);
- }
- ~ThreadSharedState()
- {
- --_dbgCount;
- }
- std::atomic<bool> serverRunning;
- std::atomic<bool> serverStopRequested;
- static std::atomic<int> _dbgCount;
-
- /**
- * If return false, message not sent.
- * otherwise message send, and msg may be reused.
- */
- bool client_trySendMessage(ThreadMessage* msg);
-
- ThreadMessage* client_pollMessage();
- void client_askServerToStop();
-
- void server_sendMessage(ThreadMessage* msg);
-
- /**
- * returned message is a pointer to a message that we "own"
- * temporarily (sender may modify it, but won't delete it).
- *
- * if null returned, a shutdown has been requested
- */
- ThreadMessage* server_waitForMessageOrShutdown();
-
-
- private:
-
- /**
- * This mutex protects all the private state
- */
- std::mutex mailboxMutex;
-
- /** The message in the mailbox.
- * This is an object by whoever created it. Ownership of message
- * is not passed.
- * TODO: given that a mutex protects us, we have no reason to use atomics here
- */
- std::atomic<ThreadMessage*> mailboxClient2Server;
- std::atomic<ThreadMessage*> mailboxServer2Client;
-
- std::condition_variable mailboxCondition;
- };
|