Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,10 @@ include(CTest)
enable_testing()
endif()

Include(FetchContent)
FetchContent_Declare(
spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog.git
GIT_TAG v1.x
)

FetchContent_MakeAvailable(spdlog)


add_subdirectory(src)
add_subdirectory(examples)


10 changes: 10 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Include(FetchContent)
FetchContent_Declare(
spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog.git
GIT_TAG v1.x
)

FetchContent_MakeAvailable(spdlog)

add_subdirectory(shared_memory)
6 changes: 6 additions & 0 deletions examples/shared_memory/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
project(example_shared_memory VERSION 1.0.0 LANGUAGES CXX)


add_executable(shared_memory src/main.cpp)

target_link_libraries(shared_memory PRIVATE CPPUTILS2::cpputils2 spdlog::spdlog)
61 changes: 61 additions & 0 deletions examples/shared_memory/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

#ifdef _WIN32
#include <cpputils2/win/shm/shm.hpp>
#else
#include <cpputils2/linux/shm/shm.hpp>
#endif

#include <iostream>
#include <spdlog/spdlog.h>

const int32_t expected = 42;
const std::string file_name("test_shm");

int main(int argc, char** argv) {
SPDLOG_INFO("Test shared memory");

CppUtils2::Shm shm(file_name);
auto ret = shm.allocate(sizeof(int32_t));
if (ret == CppUtils2::Result::RET_ERROR) {
SPDLOG_ERROR("Error");
return 1;
}

void* ptr = shm.get_raw_ptr();
if (ptr == nullptr) {
SPDLOG_ERROR("Error");
return 1;
}
int32_t* ptr_int = reinterpret_cast<int32_t*>(ptr);
SPDLOG_INFO("ptr_int: {}", *ptr_int);
*ptr_int = expected;

int32_t val = *ptr_int;



CppUtils2::Shm shm2("test_shm");
ret = shm2.open_existing(sizeof(int32_t));
if (ret == CppUtils2::Result::RET_ERROR)
{
SPDLOG_ERROR("Error");
return 1;
}
ptr = shm2.get_raw_ptr();
ptr_int = reinterpret_cast<int32_t*>(ptr);

SPDLOG_INFO("ptr_int: {}", *ptr_int);

val = *ptr_int;

SPDLOG_INFO("val: {} expected: {}", val, expected);
if (val != expected) {
SPDLOG_ERROR("Error");
return 1;
}
shm2.close();
shm.close();
shm.unlink();

return 0;
}
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ set(SOURCES_AND_HEADERS
)

if (WIN32)

list(APPEND SOURCES_AND_HEADERS include/cpputils2/win/shm/shm.hpp)
else()
list(APPEND SOURCES_AND_HEADERS
include/cpputils2/linux/net/socket/tcpsocketclient.hpp
Expand Down
182 changes: 182 additions & 0 deletions src/include/cpputils2/win/shm/shm.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/**
* @file shm.hpp
* @brief Shared memory abstraction for POSIX systems.
*
*
*/

#pragma once

#include "cpputils2/common/types.hpp"

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

namespace CppUtils2
{


class Shm
{
public:
Shm()
: hMapFile(nullptr), pBuf{nullptr}
{
}

Shm(const std::string& file_mem_path)
: mem_path(file_mem_path), hMapFile(nullptr), pBuf{ nullptr }
{
}

/// @brief Open an existing shared memory
/// @param file_mem_path Path to the shared memory
/// @param mem_size Size of the shared memory
/// @return 0 on success, -1 on error
Result open_existing(const std::string& file_mem_path, std::size_t mem_size)
{
mem_path = file_mem_path;
return open_existing(mem_size);
}

/// @brief Open an existing shared memory
/// @param mem_size Size of the shared memory
/// @return 0 on success, -1 on error
Result open_existing(std::size_t mem_size)
{
if (hMapFile != nullptr)
{
return Result::RET_ERROR;
}
int flags = 0;
return shared_open(flags, mem_size);
}

/// @brief Allocate a new shared memory
/// @param mem_size Size of the shared memory
/// @return 0 on success, -1 on error
Result allocate(std::size_t mem_size)
{
if (hMapFile != nullptr)
{
return Result::RET_ERROR;
}

int flags = 1;

return shared_open(flags, mem_size);
}

/// @brief Removes the shared memory file
/// @return 0 on success, -1 on error
Result unlink()
{
if (hMapFile != nullptr)
{
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
}
return Result::RET_ERROR;
}

/// @brief Closes the shared memory
void close()
{
if (hMapFile != nullptr)
{
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
}
hMapFile = nullptr;
}

/// @brief Get the pointer to the shared memory
/// @return Pointer to the shared memory
void* get_raw_ptr()
{
return pBuf;
}

virtual ~Shm()
{
close();
}

private:
std::string mem_path;
HANDLE hMapFile;
LPVOID pBuf;

Result shared_open(int flags, std::size_t mem_size)
{
if (flags == 1) {

//TCHAR szName[] = TEXT(mem_path.c_str());

hMapFile = CreateFileMappingA(
INVALID_HANDLE_VALUE, // use paging file
nullptr, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
mem_size, // maximum object size (low-order DWORD)
mem_path.c_str()); // name of mapping object

if (hMapFile == NULL)
{

return Result::RET_ERROR;
}

pBuf = MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
mem_size);

if (pBuf == nullptr)
{
//_tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError());

CloseHandle(hMapFile);

return Result::RET_ERROR;
}

}
else {

hMapFile = OpenFileMappingA(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
mem_path.c_str()); // name of mapping object

if (hMapFile == NULL)
{
//_tprintf(TEXT("Could not open file mapping object (%d).\n"),
// GetLastError());
return Result::RET_ERROR;
}

pBuf = MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
mem_size);

if (pBuf == nullptr)
{
//_tprintf(TEXT("Could not map view of file (%d).\n"),
// GetLastError());

CloseHandle(hMapFile);

return Result::RET_ERROR;
}

}
return Result::RET_OK;
}
};
}
52 changes: 52 additions & 0 deletions src/test/cpputils2_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
#include "cpputils2/linux/shm/shm.hpp"
#endif

#ifdef _WIN32
#include "cpputils2/win/shm/shm.hpp"
#endif

#include <atomic>
#include <chrono>
#include <cstddef>
Expand Down Expand Up @@ -139,6 +143,54 @@ namespace

#endif

#ifdef _WIN32
TEST(ExampleSHM, TestSHM) {
CppUtils2::Shm shm("test_shm");
auto ret = shm.allocate(sizeof(int32_t));
EXPECT_NE(ret, CppUtils2::Result::RET_ERROR);
void* ptr = shm.get_raw_ptr();
EXPECT_NE(ptr, nullptr);
int32_t* ptr_int = reinterpret_cast<int32_t*>(ptr);
std::cout << "ptr_int: " << *ptr_int << std::endl;
*ptr_int = 42;
int32_t val = *ptr_int;
EXPECT_EQ(val, 42);
shm.close();
shm.unlink();
EXPECT_TRUE(true);
}
TEST(ExampleShm, TestExisting)
{
CppUtils2::Shm shm("test_shm");
auto ret = shm.allocate(sizeof(int32_t));
EXPECT_NE(ret, CppUtils2::Result::RET_ERROR);

void* ptr = shm.get_raw_ptr();
EXPECT_NE(ptr, nullptr);
int32_t* ptr_int = reinterpret_cast<int32_t*>(ptr);
std::cout << "ptr_int: " << *ptr_int << std::endl;
*ptr_int = 42;

int32_t val = *ptr_int;
EXPECT_EQ(val, 42);



CppUtils2::Shm shm2("test_shm");
ret = shm2.open_existing(sizeof(int32_t));
EXPECT_NE(ret, CppUtils2::Result::RET_ERROR);
ptr = shm2.get_raw_ptr();
ptr_int = reinterpret_cast<int32_t*>(ptr);
std::cout << "ptr_int: " << *ptr_int << std::endl;

val = *ptr_int;
EXPECT_EQ(val, 42);
shm2.close();
shm.close();
shm.unlink();
}
#endif

TEST(ExampleTrigger, TestTrigger)
{
CppUtils2::TriggerWaitable trigger;
Expand Down
Loading