Skip to content

Commit

Permalink
Implement multithreading on server
Browse files Browse the repository at this point in the history
  • Loading branch information
mezzode committed Nov 11, 2019
1 parent e65981e commit 05c9569
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 25 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ CTestTestfile.cmake
_deps
.vs
out
CMakeSettings.json
12 changes: 12 additions & 0 deletions client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,15 @@ void sendHeader(HANDLE h, string key) {
}
cout << "Sent header." << endl;
}

bool awaitSendSuccess(HANDLE h) {
std::vector<char> buf(bufSize);

DWORD bytesRead;
const BOOL readSuccess = ReadFile(h, buf.data(), buf.size(), &bytesRead, nullptr); // Use ReadFileEx for async
if (!readSuccess) {
throw GetLastError();
}

return string{ buf.data(), bytesRead } == saveSuccessStatus;
}
4 changes: 3 additions & 1 deletion client.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using std::string;

void sendHeader(HANDLE h, string key);
bool awaitSendSuccess(HANDLE h);

template <class T>
void send(string key, T data) {
Expand Down Expand Up @@ -41,9 +42,10 @@ void send(string key, T data) {

sendHeader(h, key);
sendData(h, data);
const bool success = awaitSendSuccess(h);

CloseHandle(h);
cout << "Send success." << endl;
cout << "Send " << (success ? "success" : "fail") << endl;
}

template<class T>
Expand Down
2 changes: 2 additions & 0 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ struct Action {
archive(type, key);
}
};

const std::string saveSuccessStatus{ "saveSuccess" };
68 changes: 44 additions & 24 deletions server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//

#include <windows.h>
#include <thread>
#include <sstream>
#include <unordered_map>
#include <string>
Expand All @@ -15,40 +16,42 @@ int main()
{
cout << "I am the server." << endl;

// TODO: add mutex. stl allows multiple threads reading and one writing
auto store = unordered_map<string, string>{};

const DWORD pipeMode{ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT };
// don't use PIPE_NOWAIT for async, see https://docs.microsoft.com/en-us/windows/win32/ipc/synchronous-and-overlapped-input-and-output

const HANDLE h{ CreateNamedPipe(
pipeName,
PIPE_ACCESS_DUPLEX,
pipeMode,
PIPE_UNLIMITED_INSTANCES,
bufSize,
bufSize,
0,
nullptr
) };
if (h == INVALID_HANDLE_VALUE) {
throw GetLastError();
}

while (TRUE) {
const DWORD pipeMode{ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT };
const HANDLE h{ CreateNamedPipe(
pipeName,
PIPE_ACCESS_DUPLEX,
pipeMode,
PIPE_UNLIMITED_INSTANCES,
bufSize,
bufSize,
0,
nullptr
) };
if (h == INVALID_HANDLE_VALUE) {
throw GetLastError();
}

const BOOL success = ConnectNamedPipe(h, nullptr);
if (!success) {
cout << "0x" << hex << GetLastError() << endl;
throw GetLastError();
}
cout << "Connected." << endl;

read(h, store);

const BOOL dSuccess = DisconnectNamedPipe(h);
if (!dSuccess) {
cout << "0x" << hex << GetLastError() << endl;
throw GetLastError();
}
// create a separate thread so can handle clients asynchronously
thread{[h, &store]() {
read(h, store);
const BOOL dSuccess = DisconnectNamedPipe(h);
if (!dSuccess) {
cout << "0x" << hex << GetLastError() << endl;
throw GetLastError();
}
CloseHandle(h);
}}.detach();
}
}

Expand All @@ -59,6 +62,7 @@ void read(HANDLE h, Store &store) {
cout << "Saving data for key " << action.key << endl;
store[action.key] = readData(h);
cout << "Saved data for key " << action.key << endl;
saveSuccess(h);
break;
}
case Type::Get: {
Expand All @@ -70,6 +74,22 @@ void read(HANDLE h, Store &store) {
}
}

void saveSuccess(HANDLE h) {
DWORD bytesWritten{ 0 };
const BOOL success = WriteFile(
h,
&saveSuccessStatus[0],
saveSuccessStatus.size(),
&bytesWritten,
nullptr
);
FlushFileBuffers(h);
if (!success) {
cout << "0x" << hex << GetLastError() << endl;
throw GetLastError();
}
}

void returnData(HANDLE h, string data) {
DWORD bytesWritten{ 0 };
const BOOL success = WriteFile(
Expand Down
1 change: 1 addition & 0 deletions server.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ void read(HANDLE h, Store &store);
Action readHeader(HANDLE h);
string readData(HANDLE h);
void returnData(HANDLE h, string data);
void saveSuccess(HANDLE h);

0 comments on commit 05c9569

Please sign in to comment.