lichao
2021-06-03 8967e7f2f8b94dc032135707e16c8a9f233d0db6
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
 * =====================================================================================
 *
 *       Filename:  shm.h
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2021年03月22日 16时19分21秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Li Chao (), 
 *   Organization:  
 *
 * =====================================================================================
 */
 
#ifndef SHM_6CHO6D6C
#define SHM_6CHO6D6C
 
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/noncopyable.hpp>
#include <string>
 
namespace bhome_shm
{
 
using namespace boost::interprocess;
 
typedef managed_shared_memory mshm_t;
typedef interprocess_mutex Mutex;
typedef scoped_lock<Mutex> Guard;
 
class SharedMemory : public mshm_t
{
    std::string name_;
    Mutex *pmutex_ = 0;
 
    static permissions AllowAll()
    {
        permissions perm;
        perm.set_unrestricted();
        return perm;
    }
    void Swap(SharedMemory &a);
 
public:
    static bool Remove(const std::string &name) { return shared_memory_object::remove(name.c_str()); }
 
    SharedMemory(const std::string &name, const uint64_t size);
    ~SharedMemory();
    std::string name() const { return name_; }
    bool Remove() { return Remove(name()); }
    template <class T, class... Params>
    T *FindOrCreate(const std::string &name, Params &&...params)
    {
        return find_or_construct<T>(name.c_str(), std::nothrow)(std::forward<decltype(params)>(params)...);
    }
    template <class T, class... Params>
    T *Create(const std::string &name, Params &&...params)
    {
        return construct<T>(name.c_str(), std::nothrow)(std::forward<decltype(params)>(params)...);
    }
    template <class T>
    bool Destroy(const std::string &name) { return destroy<T>(name.c_str()); }
 
    void *Alloc(const size_t size)
    {
        Guard lock(*pmutex_);
        return allocate(size, std::nothrow);
    }
    void Dealloc(void *p)
    {
        Guard lock(*pmutex_);
        if (p) { deallocate(p); }
    }
 
    template <class T>
    T *Find(const std::string &name) { return find<T>(name.c_str()).first; }
};
 
enum Mode {
    eOpen = 0,
    eCreate = 1,
    eOpenOrCreate = 2
};
 
// NamedShmObject manages an object in shared memory, but NamedShmObject itself is not in shared memory.
template <class T>
class NamedShmObject : private boost::noncopyable
{
    static std::string ObjName(const std::string &name) { return "obj" + name; }
 
public:
    typedef T Data;
    typedef SharedMemory ShmType;
    ShmType &shm() const { return shm_; }
 
    template <class... Params>
    NamedShmObject(ShmType &segment, const std::string &name, Mode mode, Params &&...t) :
        shm_(segment), name_(name)
    {
        switch (mode) {
        case eOpen:
            pdata_ = shm_.Find<Data>(ObjName(name_));
            break;
        case eCreate:
            pdata_ = shm_.Create<Data>(ObjName(name_), std::forward<decltype(t)>(t)...);
            break;
        case eOpenOrCreate:
            pdata_ = shm_.FindOrCreate<Data>(ObjName(name_), std::forward<decltype(t)>(t)...);
            break;
        default: break;
        }
        if (!IsOk()) {
            throw std::runtime_error("Error: shm can not create/open \"" + name_ + "\"");
        }
    }
 
    NamedShmObject(const int64_t offset, ShmType &segment, const std::string &name) :
        shm_(segment), name_(name)
    {
        pdata_ = reinterpret_cast<Data *>(Addr(shm_.get_address()) + offset);
    }
 
    bool IsOk() const { return pdata_; }
 
    static bool Remove(SharedMemory &shm, const std::string &name) { return shm.Destroy<Data>(ObjName(name)); }
    static Data *Find(SharedMemory &shm, const std::string &name) { return shm.Find<Data>(ObjName(name)); }
    Data *Find(const std::string &name) { return Find(shm_, ObjName(name)); }
    virtual ~NamedShmObject() {}
    std::string name() const { return name_; }
    Data *data() { return pdata_; }
    const Data *data() const { return pdata_; }
    int64_t offset() const { return Addr(pdata_) - Addr(shm_.get_address()); }
    Data *operator->() { return data(); }
    const Data *operator->() const { return data(); }
    bool Remove() { return Remove(shm_, name_); }
 
private:
    static int64_t Addr(const void *p) { return reinterpret_cast<int64_t>(p); }
    ShmType &shm_;
    std::string name_;
    Data *pdata_ = nullptr;
};
 
} // namespace bhome_shm
 
#endif // end of include guard: SHM_6CHO6D6C