Samchon Framework for CPP  1.0.0
CalculatorServer.hpp
1 #pragma once
2 #include <samchon/protocol/Server.hpp>
3 
4 #include <unordered_set>
5 #include <samchon/library/RWMutex.hpp>
6 
7 namespace samchon
8 {
9 namespace examples
10 {
11 namespace calculator
12 {
13  class CalculatorServer;
14  class CalculatorClient;
15 
16  class CalculatorClient
17  : public protocol::IProtocol
18  {
19  private:
20  CalculatorServer *server;
21  std::shared_ptr<protocol::ClientDriver> driver;
22 
23  public:
24  /* ------------------------------------------------------------------
25  CONSTRUCTORS
26  ------------------------------------------------------------------ */
27  CalculatorClient(CalculatorServer *server, std::shared_ptr<protocol::ClientDriver> driver)
28  {
29  this->server = server;
30  this->driver = driver;
31  };
32  virtual ~CalculatorClient() = default;
33 
34  /* ------------------------------------------------------------------
35  INVOKE MESSAGE CHAIN
36  ------------------------------------------------------------------ */
37  virtual void sendData(std::shared_ptr<protocol::Invoke> invoke) override
38  {
39  driver->sendData(invoke);
40  };
41  virtual void replyData(std::shared_ptr<protocol::Invoke> invoke) override
42  {
43  if (invoke->getListener() == "computePlus")
44  {
45  double x = invoke->front()->getValue<double>();
46  double y = invoke->front()->getValue<double>();
47 
48  computePlus(x, y);
49  }
50  else if (invoke->getListener() == "computeMinus")
51  {
52  double x = invoke->front()->getValue<double>();
53  double y = invoke->front()->getValue<double>();
54 
55  computeMinus(x, y);
56  }
57  else
58  ((protocol::IProtocol*)server)->replyData(invoke);
59  };
60 
61  private:
62  /* ------------------------------------------------------------------
63  PROCEDURES
64  ------------------------------------------------------------------ */
65  void computePlus(double x, double y)
66  {
67  sendData(std::make_shared<protocol::Invoke>("printPlus", x, y, x + y));
68  };
69  void computeMinus(double x, double y)
70  {
71  sendData(std::make_shared<protocol::Invoke>("printPlus", x, y, x - y));
72  };
73  };
74 
75  class CalculatorServer
76  : public protocol::Server,
77  public protocol::IProtocol
78  {
79  private:
80  std::unordered_set<std::shared_ptr<CalculatorClient>> clients;
81  library::RWMutex mtx;
82 
83  public:
84  /* ------------------------------------------------------------------
85  CONSTRUCTORS
86  ------------------------------------------------------------------ */
87  CalculatorServer() : protocol::Server()
88  {
89  };
90  virtual ~CalculatorServer() = default;
91 
92  protected:
93  void addClient(std::shared_ptr<protocol::ClientDriver> driver) override
94  {
95  // CREATE CLIENT OBJECT AND ENROLL TO SET CONTAINER
96  std::shared_ptr<CalculatorClient> client(new CalculatorClient(this, driver));
97  library::UniqueWriteLock uk(mtx);
98  {
99  clients.insert(client);
100  }
101  uk.unlock();
102 
103  // LISTEN FROM THE CLIENT
104  driver->listen(client.get());
105 
106  // WHEN DISCONNECTED, ERASE CLIENT OBJECT FROM THE SET CONTAINER
107  uk.lock();
108  clients.erase(client);
109  };
110 
111  public:
112  /* ------------------------------------------------------------------
113  INVOKE MESSAGE CHAIN
114  ------------------------------------------------------------------ */
115  virtual void sendData(std::shared_ptr<protocol::Invoke> invoke)
116  {
117  std::vector<std::thread> threads;
118  library::UniqueReadLock uk(mtx);
119  {
120  threads.reserve(clients.size());
121  for (auto it = clients.begin(); it != clients.end(); it++)
122  threads.emplace_back(&CalculatorClient::sendData, it->get());
123  }
124  uk.unlock();
125 
126  for (auto it = threads.begin(); it != threads.end(); it++)
127  it->join();
128  };
129  virtual void replyData(std::shared_ptr<protocol::Invoke> invoke)
130  {
131  if (invoke->getListener() == "computeMultiply")
132  {
133  double x = invoke->front()->getValue<double>();
134  double y = invoke->front()->getValue<double>();
135 
136  computeMultiply(x, y);
137  }
138  else if (invoke->getListener() == "computeDivide")
139  {
140  double x = invoke->front()->getValue<double>();
141  double y = invoke->front()->getValue<double>();
142 
143  computeDivide(x, y);
144  }
145  };
146 
147  private:
148  /* ------------------------------------------------------------------
149  PROCEDURES
150  ------------------------------------------------------------------ */
151  void computeMultiply(double x, double y)
152  {
153  sendData(std::make_shared<protocol::Invoke>("printMultiply", x, y, x * y));
154  };
155  void computeDivide(double x, double y)
156  {
157  sendData(std::make_shared<protocol::Invoke>("printDivide", x, y, x / y));
158  };
159 
160  public:
161  /* ------------------------------------------------------------------
162  MAIN
163  ------------------------------------------------------------------ */
164  static void main()
165  {
166  CalculatorServer server;
167  server.open(17823);
168  };
169  };
170 };
171 };
172 };
virtual void replyData(std::shared_ptr< Invoke >)=0
virtual void sendData(std::shared_ptr< Invoke >)=0