Skip to content

Commit 76fa7a4

Browse files
authored
Merge pull request #1 from yangosoft/wip/shm-win
Added Windows shared memory
2 parents d60678c + e8173fd commit 76fa7a4

File tree

7 files changed

+313
-8
lines changed

7 files changed

+313
-8
lines changed

CMakeLists.txt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,10 @@ include(CTest)
4040
enable_testing()
4141
endif()
4242

43-
Include(FetchContent)
44-
FetchContent_Declare(
45-
spdlog
46-
GIT_REPOSITORY https://github.com/gabime/spdlog.git
47-
GIT_TAG v1.x
48-
)
4943

50-
FetchContent_MakeAvailable(spdlog)
5144

5245

5346
add_subdirectory(src)
47+
add_subdirectory(examples)
5448

5549

examples/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Include(FetchContent)
2+
FetchContent_Declare(
3+
spdlog
4+
GIT_REPOSITORY https://github.com/gabime/spdlog.git
5+
GIT_TAG v1.x
6+
)
7+
8+
FetchContent_MakeAvailable(spdlog)
9+
10+
add_subdirectory(shared_memory)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
project(example_shared_memory VERSION 1.0.0 LANGUAGES CXX)
2+
3+
4+
add_executable(shared_memory src/main.cpp)
5+
6+
target_link_libraries(shared_memory PRIVATE CPPUTILS2::cpputils2 spdlog::spdlog)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
#ifdef _WIN32
3+
#include <cpputils2/win/shm/shm.hpp>
4+
#else
5+
#include <cpputils2/linux/shm/shm.hpp>
6+
#endif
7+
8+
#include <iostream>
9+
#include <spdlog/spdlog.h>
10+
11+
const int32_t expected = 42;
12+
const std::string file_name("test_shm");
13+
14+
int main(int argc, char** argv) {
15+
SPDLOG_INFO("Test shared memory");
16+
17+
CppUtils2::Shm shm(file_name);
18+
auto ret = shm.allocate(sizeof(int32_t));
19+
if (ret == CppUtils2::Result::RET_ERROR) {
20+
SPDLOG_ERROR("Error");
21+
return 1;
22+
}
23+
24+
void* ptr = shm.get_raw_ptr();
25+
if (ptr == nullptr) {
26+
SPDLOG_ERROR("Error");
27+
return 1;
28+
}
29+
int32_t* ptr_int = reinterpret_cast<int32_t*>(ptr);
30+
SPDLOG_INFO("ptr_int: {}", *ptr_int);
31+
*ptr_int = expected;
32+
33+
int32_t val = *ptr_int;
34+
35+
36+
37+
CppUtils2::Shm shm2("test_shm");
38+
ret = shm2.open_existing(sizeof(int32_t));
39+
if (ret == CppUtils2::Result::RET_ERROR)
40+
{
41+
SPDLOG_ERROR("Error");
42+
return 1;
43+
}
44+
ptr = shm2.get_raw_ptr();
45+
ptr_int = reinterpret_cast<int32_t*>(ptr);
46+
47+
SPDLOG_INFO("ptr_int: {}", *ptr_int);
48+
49+
val = *ptr_int;
50+
51+
SPDLOG_INFO("val: {} expected: {}", val, expected);
52+
if (val != expected) {
53+
SPDLOG_ERROR("Error");
54+
return 1;
55+
}
56+
shm2.close();
57+
shm.close();
58+
shm.unlink();
59+
60+
return 0;
61+
}

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ set(SOURCES_AND_HEADERS
2424
)
2525

2626
if (WIN32)
27-
27+
list(APPEND SOURCES_AND_HEADERS include/cpputils2/win/shm/shm.hpp)
2828
else()
2929
list(APPEND SOURCES_AND_HEADERS
3030
include/cpputils2/linux/net/socket/tcpsocketclient.hpp
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/**
2+
* @file shm.hpp
3+
* @brief Shared memory abstraction for POSIX systems.
4+
*
5+
*
6+
*/
7+
8+
#pragma once
9+
10+
#include "cpputils2/common/types.hpp"
11+
12+
#include <windows.h>
13+
#include <stdio.h>
14+
#include <conio.h>
15+
#include <tchar.h>
16+
17+
namespace CppUtils2
18+
{
19+
20+
21+
class Shm
22+
{
23+
public:
24+
Shm()
25+
: hMapFile(nullptr), pBuf{nullptr}
26+
{
27+
}
28+
29+
Shm(const std::string& file_mem_path)
30+
: mem_path(file_mem_path), hMapFile(nullptr), pBuf{ nullptr }
31+
{
32+
}
33+
34+
/// @brief Open an existing shared memory
35+
/// @param file_mem_path Path to the shared memory
36+
/// @param mem_size Size of the shared memory
37+
/// @return 0 on success, -1 on error
38+
Result open_existing(const std::string& file_mem_path, std::size_t mem_size)
39+
{
40+
mem_path = file_mem_path;
41+
return open_existing(mem_size);
42+
}
43+
44+
/// @brief Open an existing shared memory
45+
/// @param mem_size Size of the shared memory
46+
/// @return 0 on success, -1 on error
47+
Result open_existing(std::size_t mem_size)
48+
{
49+
if (hMapFile != nullptr)
50+
{
51+
return Result::RET_ERROR;
52+
}
53+
int flags = 0;
54+
return shared_open(flags, mem_size);
55+
}
56+
57+
/// @brief Allocate a new shared memory
58+
/// @param mem_size Size of the shared memory
59+
/// @return 0 on success, -1 on error
60+
Result allocate(std::size_t mem_size)
61+
{
62+
if (hMapFile != nullptr)
63+
{
64+
return Result::RET_ERROR;
65+
}
66+
67+
int flags = 1;
68+
69+
return shared_open(flags, mem_size);
70+
}
71+
72+
/// @brief Removes the shared memory file
73+
/// @return 0 on success, -1 on error
74+
Result unlink()
75+
{
76+
if (hMapFile != nullptr)
77+
{
78+
UnmapViewOfFile(pBuf);
79+
CloseHandle(hMapFile);
80+
}
81+
return Result::RET_ERROR;
82+
}
83+
84+
/// @brief Closes the shared memory
85+
void close()
86+
{
87+
if (hMapFile != nullptr)
88+
{
89+
UnmapViewOfFile(pBuf);
90+
CloseHandle(hMapFile);
91+
}
92+
hMapFile = nullptr;
93+
}
94+
95+
/// @brief Get the pointer to the shared memory
96+
/// @return Pointer to the shared memory
97+
void* get_raw_ptr()
98+
{
99+
return pBuf;
100+
}
101+
102+
virtual ~Shm()
103+
{
104+
close();
105+
}
106+
107+
private:
108+
std::string mem_path;
109+
HANDLE hMapFile;
110+
LPVOID pBuf;
111+
112+
Result shared_open(int flags, std::size_t mem_size)
113+
{
114+
if (flags == 1) {
115+
116+
//TCHAR szName[] = TEXT(mem_path.c_str());
117+
118+
hMapFile = CreateFileMappingA(
119+
INVALID_HANDLE_VALUE, // use paging file
120+
nullptr, // default security
121+
PAGE_READWRITE, // read/write access
122+
0, // maximum object size (high-order DWORD)
123+
mem_size, // maximum object size (low-order DWORD)
124+
mem_path.c_str()); // name of mapping object
125+
126+
if (hMapFile == NULL)
127+
{
128+
129+
return Result::RET_ERROR;
130+
}
131+
132+
pBuf = MapViewOfFile(hMapFile, // handle to map object
133+
FILE_MAP_ALL_ACCESS, // read/write permission
134+
0,
135+
0,
136+
mem_size);
137+
138+
if (pBuf == nullptr)
139+
{
140+
//_tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError());
141+
142+
CloseHandle(hMapFile);
143+
144+
return Result::RET_ERROR;
145+
}
146+
147+
}
148+
else {
149+
150+
hMapFile = OpenFileMappingA(
151+
FILE_MAP_ALL_ACCESS, // read/write access
152+
FALSE, // do not inherit the name
153+
mem_path.c_str()); // name of mapping object
154+
155+
if (hMapFile == NULL)
156+
{
157+
//_tprintf(TEXT("Could not open file mapping object (%d).\n"),
158+
// GetLastError());
159+
return Result::RET_ERROR;
160+
}
161+
162+
pBuf = MapViewOfFile(hMapFile, // handle to map object
163+
FILE_MAP_ALL_ACCESS, // read/write permission
164+
0,
165+
0,
166+
mem_size);
167+
168+
if (pBuf == nullptr)
169+
{
170+
//_tprintf(TEXT("Could not map view of file (%d).\n"),
171+
// GetLastError());
172+
173+
CloseHandle(hMapFile);
174+
175+
return Result::RET_ERROR;
176+
}
177+
178+
}
179+
return Result::RET_OK;
180+
}
181+
};
182+
}

src/test/cpputils2_tests.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
#include "cpputils2/linux/shm/shm.hpp"
1818
#endif
1919

20+
#ifdef _WIN32
21+
#include "cpputils2/win/shm/shm.hpp"
22+
#endif
23+
2024
#include <atomic>
2125
#include <chrono>
2226
#include <cstddef>
@@ -139,6 +143,54 @@ namespace
139143

140144
#endif
141145

146+
#ifdef _WIN32
147+
TEST(ExampleSHM, TestSHM) {
148+
CppUtils2::Shm shm("test_shm");
149+
auto ret = shm.allocate(sizeof(int32_t));
150+
EXPECT_NE(ret, CppUtils2::Result::RET_ERROR);
151+
void* ptr = shm.get_raw_ptr();
152+
EXPECT_NE(ptr, nullptr);
153+
int32_t* ptr_int = reinterpret_cast<int32_t*>(ptr);
154+
std::cout << "ptr_int: " << *ptr_int << std::endl;
155+
*ptr_int = 42;
156+
int32_t val = *ptr_int;
157+
EXPECT_EQ(val, 42);
158+
shm.close();
159+
shm.unlink();
160+
EXPECT_TRUE(true);
161+
}
162+
TEST(ExampleShm, TestExisting)
163+
{
164+
CppUtils2::Shm shm("test_shm");
165+
auto ret = shm.allocate(sizeof(int32_t));
166+
EXPECT_NE(ret, CppUtils2::Result::RET_ERROR);
167+
168+
void* ptr = shm.get_raw_ptr();
169+
EXPECT_NE(ptr, nullptr);
170+
int32_t* ptr_int = reinterpret_cast<int32_t*>(ptr);
171+
std::cout << "ptr_int: " << *ptr_int << std::endl;
172+
*ptr_int = 42;
173+
174+
int32_t val = *ptr_int;
175+
EXPECT_EQ(val, 42);
176+
177+
178+
179+
CppUtils2::Shm shm2("test_shm");
180+
ret = shm2.open_existing(sizeof(int32_t));
181+
EXPECT_NE(ret, CppUtils2::Result::RET_ERROR);
182+
ptr = shm2.get_raw_ptr();
183+
ptr_int = reinterpret_cast<int32_t*>(ptr);
184+
std::cout << "ptr_int: " << *ptr_int << std::endl;
185+
186+
val = *ptr_int;
187+
EXPECT_EQ(val, 42);
188+
shm2.close();
189+
shm.close();
190+
shm.unlink();
191+
}
192+
#endif
193+
142194
TEST(ExampleTrigger, TestTrigger)
143195
{
144196
CppUtils2::TriggerWaitable trigger;

0 commit comments

Comments
 (0)