Пример #1
0
Optional<Reflector> Reflector::create(size_t size)
{
    static const char *path = "reflector.shm";
    FileDescriptor fd;
    void *lower = nullptr;
    void *upper = nullptr;
    void *both = nullptr;
    int sts = -1;

    if ((size == 0) || (size % 4096)) {
        return Optional<Reflector>();
    }

    fd.reset(shm_open(path, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR));
    if (fd.empty()) {
        return Optional<Reflector>();
    }

    sts = shm_unlink(path);
    if (sts < 0) {
        return Optional<Reflector>();
    }

    sts = ftruncate(fd.get(), size);
    if (sts < 0) {
        return Optional<Reflector>();
    }
    
    both = mmap(nullptr, size * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0);
    if (both == MAP_FAILED) {
        return Optional<Reflector>();
    }

    lower = mremap(both, size * 2, size, 0);
    if (lower == MAP_FAILED) {
        sts = munmap(both, size * 2);
        assert(sts >= 0);
        return Optional<Reflector>();
    }
    else if (lower != both) {
        sts = munmap(lower, size);
        assert(sts);
        return Optional<Reflector>();
    }

    upper = static_cast<uint8_t*>(lower) + size;
    upper = mmap(upper, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd.get(), 0);
    if (upper == MAP_FAILED) {
        sts = munmap(lower, size);
        assert(sts >= 0);
        return Optional<Reflector>();
    }

    return Optional<Reflector>(Reflector(std::move(fd), lower, size));
}