diff options
Diffstat (limited to 'works/life/computer-network-experiment')
| -rw-r--r-- | works/life/computer-network-experiment/ReadWriteLock.cpp | 1 | ||||
| -rw-r--r-- | works/life/computer-network-experiment/TODO.md | 6 | ||||
| -rw-r--r-- | works/life/computer-network-experiment/server.cpp | 26 | 
3 files changed, 29 insertions, 4 deletions
| diff --git a/works/life/computer-network-experiment/ReadWriteLock.cpp b/works/life/computer-network-experiment/ReadWriteLock.cpp index 3509e0b..46d2857 100644 --- a/works/life/computer-network-experiment/ReadWriteLock.cpp +++ b/works/life/computer-network-experiment/ReadWriteLock.cpp @@ -2,7 +2,6 @@  #include <cassert>
  #include <memory>
 -#include <pthread.h>
  namespace cru {
  ReadWriteLock::ReadWriteLock() {
 diff --git a/works/life/computer-network-experiment/TODO.md b/works/life/computer-network-experiment/TODO.md index 77bf0fc..248a2d7 100644 --- a/works/life/computer-network-experiment/TODO.md +++ b/works/life/computer-network-experiment/TODO.md @@ -1,4 +1,6 @@ -1. Apply read-write lock to connections.
 -2. Remove dead connection from connection list.
 +1. Apply read-write lock to connections. ✅
 +2. Remove dead connection from connection list. ✅
  3. Handle SIGINT gracefully.
  4. Add close method to protocol.
 +5. Add help and exit command.
 +6. Use multiprocess to show output.
 diff --git a/works/life/computer-network-experiment/server.cpp b/works/life/computer-network-experiment/server.cpp index 03d27ad..065687c 100644 --- a/works/life/computer-network-experiment/server.cpp +++ b/works/life/computer-network-experiment/server.cpp @@ -4,6 +4,7 @@  #include "Common.h"
  #include "IO.h"
 +#include "ReadWriteLock.h"
  #include <folly/CancellationToken.h>
  #include <folly/ProducerConsumerQueue.h>
 @@ -26,12 +27,14 @@  const auto bind_address = "127.0.0.1"; // control bind address
  const u_short port = 1234;             // control bind port
 +namespace {
  void PrintHelp() {
    SendOutput(CRUT(
        "Input and run one of following command:\n\t> NOTHING -> Continue and "
        "print new messages.\n\t> list -> List all connected client.\n\t> send "
        "[i] [message] -> Send messages to client with number i.\n"));
  }
 +} // namespace
  struct Connection {
    int id;
 @@ -45,9 +48,24 @@ struct Connection {    folly::CancellationSource cancellation_source;
  };
 +namespace {
 +cru::ReadWriteLock connections_lock;
  std::vector<std::unique_ptr<Connection>> connections;
 +void RemoveConnection(int id) {
 +  connections_lock.WriteLock();
 +  connections.erase(
 +      std::remove_if(connections.begin(), connections.end(),
 +                     [id](const std::unique_ptr<Connection> &connection) {
 +                       return connection->id == id;
 +                     }),
 +      connections.end());
 +
 +  connections_lock.WriteUnlock();
 +}
 +
  void PrintConnections() {
 +  connections_lock.ReadLock();
    if (connections.empty()) {
      SendOutput(CRUT("Currently there is no connection.\n"));
    }
 @@ -58,7 +76,9 @@ void PrintConnections() {                       connection->address_string);
    }
    SendOutput(s);
 +  connections_lock.ReadUnlock();
  }
 +} // namespace
  void ResponseThreadProc(Connection *connection) {
    auto host = ConvertCharString(inet_ntoa(connection->address.sin_addr));
 @@ -120,6 +140,8 @@ void ResponseThreadProc(Connection *connection) {    }
    CloseSocket(connection->socket);
 +
 +  RemoveConnection(connection->id);
  }
  void OnInputLine(StringView line) {
 @@ -164,7 +186,7 @@ void OnInputLine(StringView line) {          [id](const std::unique_ptr<Connection> &c) { return c->id == id; });
      if (i == connections.end()) {
 -      SendOutput(OutputType::Error, CRUT("No connection with such id.!\n"));
 +      SendOutput(OutputType::Error, CRUT("No connection with such id.\n"));
        return;
      }
 @@ -224,6 +246,7 @@ int Main() {        PrintErrorMessageAndExit(CRUT("Failed to accecpt."));
      }
 +    connections_lock.WriteLock();
      connections.push_back(std::make_unique<Connection>());
      const std::unique_ptr<Connection> &connection = connections.back();
 @@ -233,5 +256,6 @@ int Main() {      connection->thread =
          std::thread(ResponseThreadProc, connections.back().get());
      connection->thread.detach();
 +    connections_lock.WriteUnlock();
    }
  }
 | 
