/* PIP - Platform Independent Primitives File Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "piincludes_p.h" #include "pisharedmemory.h" #include "pipropertystorage.h" #if defined(LINUX) || defined(MAC_OS) # define SHM_POSIX #endif #ifdef WINDOWS #endif #if defined(QNX) || defined(ANDROID) #endif #ifdef MAC_OS //# include #endif #ifdef SHM_POSIX # include # include # include #endif /*! \class PISharedMemory * \brief Shared memory * * \section PISharedMemory_sec0 Synopsis * This class provide access to local file. You can manipulate * binary content or use this class as text stream. To binary * access there are function \a read(), \a write(), and many * \a writeBinary() functions. For write variables to file in * their text representation threr are many "<<" operators. * * \section PISharedMemory_sec1 Position * Each opened file has a read/write position - logical position * in the file content you read from or you write to. You can * find out current position with function \a pos(). Function * \a seek(llong position) move position to position "position", * \a seekToBegin() move position to the begin of file, * \a seekToEnd() move position to the end of file. * */ REGISTER_DEVICE(PISharedMemory) PRIVATE_DEFINITION_START(PISharedMemory) PIByteArray name; #ifdef WINDOWS HANDLE map; void * data; #endif #ifdef SHM_POSIX void * data; bool owner; #endif PRIVATE_DEFINITION_END(PISharedMemory) PISharedMemory::PISharedMemory(): PIIODevice() { initPrivate(); dsize = 65536; } PISharedMemory::PISharedMemory(const PIString & shm_name, int size, PIIODevice::DeviceMode mode): PIIODevice(shm_name, mode) { initPrivate(); dsize = size; if (!shm_name.isEmpty()) open(); } PISharedMemory::~PISharedMemory() { stop(); close(); } bool PISharedMemory::openDevice() { close(); //piCoutObj << "try open" << path() << dsize; #ifdef WINDOWS PRIVATE->name = ("PIP_SHM_" + path()).toByteArray(); PRIVATE->name.push_back(0); const char * nm = (const char *)PRIVATE->name.data(); PRIVATE->map = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, nm); //piCoutObj << "open map =" << ullong(PRIVATE->map); if (!PRIVATE->map) { PRIVATE->map = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)dsize, nm); //piCoutObj << "create map =" << ullong(PRIVATE->map); if (!PRIVATE->map) { piCoutObj << "CreateFileMapping error," << errorString(); return false; } } PRIVATE->data = MapViewOfFile(PRIVATE->map, FILE_MAP_ALL_ACCESS, 0, 0, dsize); if (!PRIVATE->data) { CloseHandle(PRIVATE->map); piCoutObj << "MapViewOfFile error," << errorString(); return false; } //piCout << PRIVATE->map << PRIVATE->data; #endif #ifdef SHM_POSIX PRIVATE->name = ("/pip_shm_" + path()).toByteArray(); PRIVATE->name.push_back(0); int fd = shm_open((const char *)PRIVATE->name.data(), O_RDWR, 0777); //piCoutObj << "try open" << PICoutManipulators::Hex << fd; if (fd < 0) { //piCoutObj << "shm_open error," << errorString(); fd = shm_open((const char *)PRIVATE->name.data(), O_RDWR | O_CREAT, 0777); //piCoutObj << "try create" << PICoutManipulators::Hex << (m | O_CREAT) << fd; if (fd < 0) { piCoutObj << "shm_open error," << errorString(); return false; } PRIVATE->owner = true; //piCoutObj << "created" << fd; } if (fd >= 0) ftruncate(fd, dsize); PRIVATE->data = mmap(0, dsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); ::close(fd); if (PRIVATE->data == MAP_FAILED) { piCoutObj << "mmap error," << errorString(); return false; } //piCoutObj << "opened" << PRIVATE->data; #endif return true; } bool PISharedMemory::closeDevice() { #ifdef WINDOWS if (PRIVATE->data) UnmapViewOfFile(PRIVATE->data); if (PRIVATE->map) CloseHandle(PRIVATE->map); #endif #ifdef SHM_POSIX //piCoutObj << "close" << PIString(PRIVATE->name) << PRIVATE->data; if (PRIVATE->data) munmap(PRIVATE->data, dsize); if (PRIVATE->owner) { //piCout << "unlink" << PIString(PRIVATE->name); shm_unlink((const char *)PRIVATE->name.data()); } //if (fd > 0) #endif initPrivate(); return true; } PIString PISharedMemory::constructFullPathDevice() const { PIString ret; ret << path() << ":" << dsize; return ret; } void PISharedMemory::configureFromFullPathDevice(const PIString & full_path) { initPrivate(); PIStringList pl = full_path.split(":"); for (int i = 0; i < pl.size_s(); ++i) { PIString p(pl[i]); switch (i) { case 0: setPath(p); break; case 1: dsize = p.toInt(); break; } } } PIPropertyStorage PISharedMemory::constructVariantDevice() const { PIPropertyStorage ret; ret.addProperty("path", path()); ret.addProperty("size", dsize); return ret; } void PISharedMemory::configureFromVariantDevice(const PIPropertyStorage & d) { setPath(d.propertyValueByName("path").toString()); setSize(d.propertyValueByName("size").toInt()); } void PISharedMemory::initPrivate() { #ifdef WINDOWS PRIVATE->map = 0; PRIVATE->data = 0; #endif #ifdef SHM_POSIX PRIVATE->data = 0; PRIVATE->owner = false; #endif } PIByteArray PISharedMemory::readAll() { if (dsize <= 0) return PIByteArray(); #ifdef WINDOWS if (!PRIVATE->data) return PIByteArray(); #endif #ifdef SHM_POSIX if (!PRIVATE->data) return PIByteArray(); #endif PIByteArray a(dsize); read(a.data(), a.size_s()); return a; } llong PISharedMemory::size() const { if (isClosed()) return -1; return dsize; } void PISharedMemory::setSize(llong s) { bool o = isOpened(); if (o) close(); dsize = s; if (o) open(); } int PISharedMemory::read(void * read_to, int max_size) { return read(read_to, max_size, 0); } int PISharedMemory::read(void * read_to, int max_size, int offset) { #ifdef WINDOWS if (!PRIVATE->data) return -1; CopyMemory(read_to, &(((char*)(PRIVATE->data))[offset]), max_size); return max_size; #endif #ifdef SHM_POSIX if (!PRIVATE->data) return -1; memcpy(read_to, &(((char*)(PRIVATE->data))[offset]), max_size); return max_size; #endif return -1; } int PISharedMemory::write(const void * data, int max_size) { return write(data, max_size, 0); } int PISharedMemory::write(const void * data, int max_size, int offset) { #ifdef WINDOWS if (!PRIVATE->data) return -1; CopyMemory(&(((char*)(PRIVATE->data))[offset]), data, max_size); return max_size; #endif #ifdef SHM_POSIX if (!PRIVATE->data) return -1; memcpy(&(((char*)(PRIVATE->data))[offset]), data, max_size); return max_size; #endif return -1; }