Skip to content
SlickQuantPublic

About

C++ header-only, cross-platform shared memory

Resources

Stars

6 stars

Watchers

0 watching

Forks

Repository files navigation

slick-shm

A modern C++17 header-only, cross-platform shared memory library.

License: MIT Header-only CI GitHub release

Features

  • Header-only: No compilation required, just include and use
  • Cross-platform: Works on Windows, Linux, and macOS
  • Modern C++17: Uses modern C++ features and idioms
  • RAII: Automatic resource management
  • Hybrid error handling: Both exception and no-throw variants
  • Type-safe: Clean, type-safe API
  • Creator tracking: Know if you created or opened existing shared memory via is_creator()
  • Well-tested: Comprehensive test suite with Catch2
  • Well-documented: Extensive API documentation and examples

Platform Support

Platform Implementation Status
Windows CreateFileMapping / MapViewOfFile Supported
Linux POSIX shm_open / mmap Supported
macOS POSIX shm_open / mmap Supported

Quick Start

Installation

vcpkg

Install with vcpkg:

# Install from vcpkg
vcpkg install slick-shm

# Or add to vcpkg.json manifest
{
  "dependencies": ["slick-shm"]
}

Then in your CMakeLists.txt:

find_package(slick-shm CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE slick::shm)

Header-Only (Manual)

Copy the include/slick directory into your project and include the header:

#include <slick/shm/shared_memory.hpp>

CMake FetchContent

include(FetchContent)

# Skip slick-shm's tests, examples, and install target
set(SLICK_SHM_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(SLICK_SHM_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(SLICK_SHM_INSTALL OFF CACHE BOOL "" FORCE)
FetchContent_Declare(
    slick-shm
    GIT_REPOSITORY https://github.com/SlickQuant/slick-shm.git
    GIT_TAG v0.1.0  # See https://github.com/SlickQuant/slick-shm/releases for latest version
)
FetchContent_MakeAvailable(slick-shm)

target_link_libraries(your_target PRIVATE slick::shm)

CMake Integration

# Option 1: Add as subdirectory
add_subdirectory(path/to/slick-shm)
target_link_libraries(your_target PRIVATE slick::shm)

# Option 2: Install and find_package
find_package(slick-shm REQUIRED)
target_link_libraries(your_target PRIVATE slick::shm)

Basic Usage

Writer Process

#include <slick/shm/shared_memory.hpp>
#include <cstring>

int main() {
    using namespace slick::shm;

    // Create shared memory
    shared_memory shm("my_shm", 1024, create_only);

    // Write data
    const char* message = "Hello, World!";
    std::memcpy(shm.data(), message, std::strlen(message) + 1);

    return 0;
}

Reader Process

#include <slick/shm/shared_memory.hpp>
#include <iostream>

int main() {
    using namespace slick::shm;

    // Open existing shared memory
    shared_memory shm("my_shm", open_existing, access_mode::read_only);

    // Read data
    const char* message = static_cast<const char*>(shm.data());
    std::cout << message << std::endl;

    // Remove the segment (required on POSIX, a no-op on Windows)
    shared_memory::remove("my_shm");

    return 0;
}

Building

Requirements

  • C++17 compatible compiler
    • GCC 7+ or Clang 5+ (Linux/macOS)
    • MSVC 2017+ or MinGW (Windows)
  • CMake 3.14+ (only for building the examples and tests)

Build Instructions

# Clone the repository
git clone https://github.com/SlickQuant/slick-shm.git
cd slick-shm

# Create build directory
mkdir build && cd build

# Configure
cmake ..

# Build
cmake --build .

# Run tests
ctest --output-on-failure

# Install (optional)
cmake --install . --prefix /usr/local

CMake Options

  • SLICK_SHM_BUILD_EXAMPLES (default: ON): build the example programs
  • SLICK_SHM_BUILD_TESTS (default: ON): build the unit tests
  • SLICK_SHM_INSTALL (default: ON): generate the install target

Documentation

API Overview

Core Classes

shared_memory

Owns a mapped segment. The destructor unmaps and closes it.

// Create new shared memory
shared_memory shm("name", 1024, create_only);

// Open existing shared memory
shared_memory shm("name", open_existing);

// Create or open
shared_memory shm("name", 1024, open_or_create);

// Access data
void* ptr = shm.data();
size_t size = shm.size();

// Check validity
if (shm.is_valid()) { /* ... */ }

// Static utilities
shared_memory::remove("name");
bool exists = shared_memory::exists("name");

shared_memory_view

A non-owning view of a mapped segment.

shared_memory shm("name", 1024, create_only);
shared_memory_view view(shm);  // Cheap to copy

Copying a view never allocates. It holds only data, size, mode, and a borrowed name pointer, so it's cheap to pass by value into worker threads or hot paths. The name() pointer belongs to the shared_memory object (or caller-provided buffer) the view was built from, so that source must outlive the view.

You can still move the source. shared_memory keeps its name in address-stable storage, so a view stays valid when its source is moved or move-assigned, even when a std::vector<shared_memory> reallocates. Building a view from a temporary won't compile.

Error Handling

Exception-Based

try {
    shared_memory shm("test", 1024, create_only);
} catch (const shared_memory_error& e) {
    std::cerr << "Error: " << e.what() << std::endl;
    if (e.code() == errc::already_exists) {
        // Handle specific error
    }
}

No-Throw Variant

shared_memory shm("test", 1024, create_only,
                  access_mode::read_write, std::nothrow);

if (!shm.is_valid()) {
    std::cerr << "Error: " << shm.last_error().message() << std::endl;
}

Examples

The examples directory has three programs:

Build and run:

cd build
./examples/basic_writer    # In one terminal
./examples/basic_reader    # In another terminal

Testing

The tests use Catch2:

cd build
ctest --output-on-failure

They cover:

  • Create/open operations
  • Error handling (exceptions and no-throw)
  • Move semantics
  • Cross-process communication
  • Platform-specific behavior

Platform-Specific Notes

Windows

  • Backed by the system paging file
  • Names are used as-is. You can prefix them with Global\, Local\, or Session\<id>\
  • The kernel frees the segment when the last handle closes

Linux/macOS (POSIX)

  • Uses shm_open() / mmap(), backed by tmpfs on Linux
  • The library adds the leading / for you
  • You must call shared_memory::remove() to delete a segment. Closing every handle doesn't
  • Name length limits:
    • macOS: 31 characters, counting the / prefix
    • Linux: 255 characters
    • For portable code, keep names to 30 characters or fewer

See platform_notes.md for the details.

Best Practices

  1. Keep names short (30 characters or fewer) and alphanumeric so they work everywhere.
  2. Call remove() when you're done. Windows doesn't need it, but POSIX does.
  3. Synchronize access to the data with std::atomic or your own locking.
  4. Check for errors, either by catching exceptions or by calling is_valid().
  5. Pass shared_memory_view to code that uses the memory but shouldn't own it.
  6. Trust size(), not your request. With open_or_create or open_always an existing segment may keep its own size, so size() can be smaller than what you asked for. Use create_only when the size must be exact. See Sizing an existing segment.

License

MIT. See LICENSE.

Contributing

Issues and pull requests are welcome.

Author

Slick Quant

Acknowledgments

  • Inspired by Boost.Interprocess
  • Tested with Catch2

About

C++ header-only, cross-platform shared memory

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages