aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/shmem.cpp
blob: c1f3757546a45f69aa13fd323a384d70a619a47c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
// This file is part of the "winapi-common" project.
// For details, see https://github.com/egor-tensin/winapi-common.
// Distributed under the MIT License.

#include <winapi/error.hpp>
#include <winapi/handle.hpp>
#include <winapi/shmem.hpp>
#include <winapi/utf8.hpp>
#include <winapi/utils.hpp>

#include <boost/config.hpp>

#include <windows.h>

#include <cstddef>
#include <cstdint>
#include <string>
#include <utility>

namespace winapi {
namespace {

void* do_map(const Handle& mapping, std::size_t nb = 0) {
    const auto addr = ::MapViewOfFile(static_cast<HANDLE>(mapping), FILE_MAP_ALL_ACCESS, 0, 0, nb);

    if (addr == NULL) {
        throw error::windows(GetLastError(), "MapViewOfFile");
    }

    return addr;
}

} // namespace

void SharedMemory::Unmap::operator()(void* ptr) const {
    const auto ret = ::UnmapViewOfFile(ptr);
    assert(ret);
    WINAPI_UNUSED_PARAMETER(ret);
};

SharedMemory SharedMemory::create(const std::string& name, std::size_t nb) {
    const auto nb64 = static_cast<std::uint64_t>(nb);
    static_assert(sizeof(nb64) == 2 * sizeof(DWORD), "sizeof(DWORD) != 32");

    const auto nb_low = static_cast<DWORD>(nb64);
    const auto nb_high = static_cast<DWORD>(nb64 >> 32);

    const auto mapping_impl = ::CreateFileMappingW(
        INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, nb_high, nb_low, widen(name).c_str());

    if (mapping_impl == NULL) {
        throw error::windows(GetLastError(), "CreateFileMappingW");
    }

    Handle mapping{mapping_impl};
    const auto addr = do_map(mapping);
    return {std::move(mapping), addr};
}

SharedMemory SharedMemory::open(const std::string& name) {
    const auto mapping_impl = ::OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, widen(name).c_str());

    if (mapping_impl == NULL) {
        throw error::windows(GetLastError(), "OpenFileMappingW");
    }

    Handle mapping{mapping_impl};
    const auto addr = do_map(mapping);
    return {std::move(mapping), addr};
}

SharedMemory::SharedMemory(SharedMemory&& other) BOOST_NOEXCEPT_OR_NOTHROW {
    swap(other);
}

SharedMemory& SharedMemory::operator=(SharedMemory other) BOOST_NOEXCEPT_OR_NOTHROW {
    swap(other);
    return *this;
}

void SharedMemory::swap(SharedMemory& other) BOOST_NOEXCEPT_OR_NOTHROW {
    using std::swap;
    swap(m_handle, other.m_handle);
    swap(m_addr, other.m_addr);
}

} // namespace winapi