/usr/include/bobcat/sharedmemory is in libbobcat-dev 3.23.01-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
| 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 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | #ifndef INCLUDED_BOBCAT_SHAREDMEMORY_
#define INCLUDED_BOBCAT_SHAREDMEMORY_
#include <ios>
#include <bobcat/fswap>
#include <bobcat/sharedpos>
#include <bobcat/exception>
namespace FBB
{
class SharedSegment;
struct SharedEnum__
{
    enum SizeUnit
    {
        kB = 10,
        MB = 20,
        GB = 30
    };
};
class SharedMemory: public virtual SharedEnum__
{
    friend std::ostream &operator<<(std::ostream &out, 
                                    SharedMemory const &mem);
    enum { PAGESIZE = 1 << 12 };
        // updated by the non-default constructors.
    int d_id = -1;                      // id of SharedSegment
    SharedSegment *d_sharedSegment = 0; // points to the attached shared
                                        //  memory. This is NOT a pointer
                                        // to dynamically allocated memory
                                        // but a static_cast pointer to
                                        // the attached shared data segment
    SharedPos d_pos;
    size_t d_lockCount = 0;             // # of nested locks
    char *d_data = 0;                   // pointer to shared memory data
    public:
        SharedMemory() = default;
        SharedMemory(SharedMemory const &other) = delete;
        SharedMemory(size_t maxSize, SizeUnit sizeUnit,
                     size_t access = 0600);             // 2: creation mode;
        SharedMemory(int id);                           // 3
        ~SharedMemory();
        SharedMemory &operator=(SharedMemory &&tmp);
        std::streamsize blockOffset() const;// offset matching offset(),
                                            // relative to the current data 
                                            // block.
        void clear();                   // clear all existing data and reduce
                                        // until only the segment at 
                                        // d_sharedSegment  
        size_t dataSegmentSize() const;
        int get();                      // get char from d_segmentData 
                                        // locks), or EOF   
        int id() const;                 // id of the d_sharedSegment segment
                // after kill/remove: shared segment is unusable
        void kill();                    // delete all shared segments w/o locks
        std::streamsize maxOffset() const;  
        std::streamsize nReadable() const;  // beyond last readable byte
        std::streamsize offset() const;     // read/write offset relative to
                                            // ios::beg
        char *ptr();                        // 0 if at maxOffset
        int put(int ch);                // put char at d_offset (locks),
                                        // ch == EOF immediately returns EOF 
                                        // read len chars, return nRead or -1, 
                                        // locks
        int read(char *data, std::streamsize len);    
        template <typename Type>
        int read(Type *value);              // 1.f
     
        template <typename Type>            // 2.f
        int read(std::ios::off_type offset, Type *value,
                  std::ios::seekdir origin = std::ios::beg);
                // after kill/remove: shared segment is unusable
        void remove();                  // delete all shared segments.
                                        // returns -1 if inaccessible
        std::ios::pos_type seek(std::ios::off_type offset, 
                                std::ios::seekdir origin = std::ios::beg);
        std::streamsize showmanyc();
        void swap(SharedMemory &other);
        bool truncate(std::streamsize offset);  // nReadable is reduced to 
                                            // offset
                                        // write len bytes at d_offset
                                        // locks, returns #written or -1
        int write(char const *data, std::streamsize len);
        template <typename Type>
        int write(Type const *value);       // 1.f
     
        template <typename Type>            // 2.f
        int write(std::ios::off_type offset, Type const *value,
                  std::ios::seekdir origin = std::ios::beg);
        template <typename SharedType, typename ... Params>
        SharedType *install(std::streamsize *offset, Params &&...params);
    private:
        std::ostream &insert(std::ostream &out) const;
                                        // lockAll: d_lockCount should be 0.
        void lockAll();                 // lock all block[] mutexes
        void unlockAll();               // unlock all block[] mutexes
        void lock(size_t idx);          // (recursively) lock block idx
        void unlock(size_t idx);        // unlock block idx
        void clearAll();                // clear without locking
        bool blockAvailable(size_t idx);
        void map();                     // 1    maps shared data to d_data
        void map(size_t idx);           // 2    only called by load
        int writeBlock(char const *data, size_t len);   // locks, returns 
                                                        // #written or -1
        int readBlock(char *data, size_t len);          // same, but now reads
                                                        // both update offset
        static size_t computeSegmentSize(
                            size_t *nBlocks, 
                            long long maxMemory, SizeUnit sizeUnit);
        void validate() const;
};
inline std::streamsize SharedMemory::blockOffset() const
{
    return d_pos.blockOffset();
}
inline size_t SharedMemory::dataSegmentSize() const
{
    return d_sharedSegment ? d_sharedSegment->segmentSize() : 0;
}
inline int SharedMemory::id() const
{
    return d_id;
}
template <typename SharedType, typename ... Params>
SharedType *SharedMemory::install(std::streamsize *offsetPtr, 
                                  Params &&...params)
{
    size_t segmentSize = dataSegmentSize();
    if (segmentSize == 0)
        throw Exception() << "SharedMemory::install: no memory";
                        // find a suitable offset for the shared memory object
    size_t begin = blockOffset();
    size_t end = (begin + sizeof(SharedType)) % segmentSize;
    if (begin + sizeof(SharedType) != end)
        seek((1 + offset() / segmentSize) * segmentSize);
                                // determine the object's offset and address
    std::streamsize location = offset();
    void *address = ptr();
                                            // go to the object's last byte
    if (address == 0 || seek(sizeof(SharedType) - 1) == -1)
        throw Exception() << "SharedMemory::install: out of memory.";
    
            // make sure shmem knows it exists by writing a byte at its last
            // byte location
    put(0);       
    if (offsetPtr)
        *offsetPtr = location;
            // install the object at 'address'
    return new (address) SharedType(std::forward<Params>(params)...);
}
inline std::streamsize SharedMemory::maxOffset() const
{
    return d_pos.maxOffset();
}
inline std::streamsize SharedMemory::nReadable() const
{
    return d_sharedSegment ? d_sharedSegment->nReadable() : 0;
}
inline std::streamsize SharedMemory::offset() const
{
    return d_pos.offset();
}
inline SharedMemory &SharedMemory::operator=(SharedMemory &&tmp)
{
    swap(tmp);
    return *this;
}
inline std::ostream &operator<<(std::ostream &out, SharedMemory const &mem)
{
    return mem.insert(out);
}
template <typename Type>
inline int SharedMemory::read(Type *value)
{
    return read(reinterpret_cast<char *>(value), sizeof(Type));
}
template <typename Type>
int SharedMemory::read(std::ios::off_type offset, Type *value, 
                        std::ios::seekdir origin) 
{
    if (seek(offset, origin) == -1)
        throw Exception() << "SharedMemory::read: seek to " << offset <<
                                                                "failed";
                            
    return read(value);
}
inline void SharedMemory::swap(SharedMemory &other)
{
    FBB::fswap(*this, other);
}
template <typename Type>
inline int SharedMemory::write(Type const *value)
{
    return write(reinterpret_cast<char const *>(value), sizeof(Type));
}
template <typename Type>
int SharedMemory::write(std::ios::off_type offset, Type const *value, 
                        std::ios::seekdir origin) 
{
    if (seek(offset, origin) == -1)
        throw Exception() << "SharedMemory::write: seek to " << offset <<
                                                                "failed";
    return write(value);
}
} // FBB        
#endif
 |