diff --git a/src/Core/Image/Manipulation/ScalingManager.h b/src/Core/Image/Manipulation/ScalingManager.h index 40e154ac..116f8a3f 100644 --- a/src/Core/Image/Manipulation/ScalingManager.h +++ b/src/Core/Image/Manipulation/ScalingManager.h @@ -184,10 +184,7 @@ namespace degate if (project_type == ProjectType::Normal) { // Create a new image directory name. - char dir_name[PATH_MAX]; - snprintf(dir_name, sizeof(dir_name), "scaling_%d.dimg", i); - - path = join_pathes(images[1]->get_path(), std::string(dir_name)); + path = join_pathes(images[1]->get_path(), QString("scaling_%1.dimg").arg(i).toStdString()); // Check if need to create scaled images debug(TM, "create scaled image in %s for scaling factor %d?", path.c_str(), i); diff --git a/src/Core/Image/TileCache.h b/src/Core/Image/TileCache.h index 80e044d3..5d76f1df 100644 --- a/src/Core/Image/TileCache.h +++ b/src/Core/Image/TileCache.h @@ -340,8 +340,7 @@ namespace degate GET_CLOCK(now); // Create a file name from tile number - char filename[PATH_MAX]; - snprintf(filename, sizeof(filename), "%d_%d.dat", x, y); + auto filename = QString("%1_%2.dat").arg(x).arg(y).toStdString(); // If filename/object is not in cache, load the tile typename cache_type::const_iterator iter = cache.find(filename); diff --git a/src/Core/LogicModel/LogicModelHelper.cc b/src/Core/LogicModel/LogicModelHelper.cc index 520e4f53..02202ae1 100644 --- a/src/Core/LogicModel/LogicModelHelper.cc +++ b/src/Core/LogicModel/LogicModelHelper.cc @@ -216,8 +216,7 @@ void load_tile(const QRgb* rba_data, unsigned int tile_y = global_tile_y + local_tile_y; // Create a file name from tile number. - char filename[PATH_MAX]; - snprintf(filename, sizeof(filename), "%d_%d.dat", tile_x, tile_y); + auto filename = QString("%1_%2.dat").arg(tile_x).arg(tile_y).toStdString(); auto data = new BackgroundImage::pixel_type[tile_size * tile_size]; memset(data, @@ -351,9 +350,8 @@ void create_scaled_background_images(const BackgroundImage_shptr& bg_image, unsi h >>= 1u; // create a new image - char dir_name[PATH_MAX]; - snprintf(dir_name, sizeof(dir_name), "scaling_%d.dimg", i); - std::string dir_path = join_pathes(bg_image->get_path(), std::string(dir_name)); + auto dir_path = join_pathes(bg_image->get_path(), QString("scaling_%1.dimg").arg(i).toStdString()); + create_directory(dir_path); reader.device()->seek(0); diff --git a/src/Core/Utils/MemoryMap.h b/src/Core/Utils/MemoryMap.h index aaeb345f..ba82336b 100644 --- a/src/Core/Utils/MemoryMap.h +++ b/src/Core/Utils/MemoryMap.h @@ -24,35 +24,15 @@ #include "Prerequisites.h" #include "Globals.h" -#include "Core/Utils/FileSystem.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + #include -#include - -#if defined(SYS_WINDOWS) -#define NOMINMAX -#include -#include -#define PATH_MAX MAX_PATH -#elif defined(SYS_UNIX) -#include -#include -#include // PATH_MAX for UNIX -#include -#else -#error "Unknown architecture" -#endif +#include + +#include +#include +#include +#include +#include namespace degate { @@ -70,29 +50,21 @@ namespace degate * You should not use this class directly. */ template - class MemoryMap : boost::noncopyable + class MemoryMap : QObject { private: unsigned int width, height; MAP_STORAGE_TYPE storage_type; - std::string filename; - size_t filesize; size_t mem_size; - -#ifdef SYS_WINDOWS - typedef void* fd; - void* mem_file; -#else - typedef int fd; -#endif - - fd file; + QFileDevice* backing_file; T* mem_view; private: + Q_DISABLE_COPY(MemoryMap) + ret_t alloc_memory(); - ret_t map_file(std::string const& filename); + ret_t map_file(QFile* file); void unmap(); void* get_void_ptr(unsigned int x, unsigned int y) const; @@ -170,7 +142,12 @@ namespace degate * @returns Returns a string with the mapped file. If the memory * chunk is heap and not file based, an empty string is returned. */ - std::string const& get_filename() const { return filename; } + std::string const get_filename() const + { + return (backing_file != nullptr) ? + QDir::toNativeSeparators(backing_file->fileName()).toStdString() : + std::string{}; + } /** * Get data (can be null). @@ -183,13 +160,7 @@ namespace degate MemoryMap::MemoryMap(unsigned int width, unsigned int height) : width(width), height(height), storage_type(MAP_STORAGE_TYPE_MEM), - filename(), - filesize(0), mem_size(width * height * sizeof(T)), - file(0), -#ifdef SYS_WINDOWS - mem_file(nullptr), -#endif mem_view(nullptr) { assert(width > 0 && height > 0); @@ -203,13 +174,7 @@ namespace degate MAP_STORAGE_TYPE mode, std::string const& file_to_map) : width(width), height(height), storage_type(mode), - filename(file_to_map), - filesize(0), mem_size(width * height * sizeof(T)), - file(0), -#ifdef SYS_WINDOWS - mem_file(nullptr), -#endif mem_view(nullptr) { assert(mode == MAP_STORAGE_TYPE_PERSISTENT_FILE || mode == MAP_STORAGE_TYPE_TEMP_FILE); @@ -217,21 +182,47 @@ namespace degate assert(width > 0 && height > 0); ret_t ret; - + std::unique_ptr file; if (mode == MAP_STORAGE_TYPE_TEMP_FILE) { // Random filename - std::string fn = get_temp_file_path(); - ret = map_file(fn); - if (RET_IS_NOT_OK(ret)) debug(TM, "Can't open a temp file with pattern %s", fn.c_str()); - assert(RET_IS_OK(ret)); + auto temporary_file = std::make_unique(); + temporary_file->setAutoRemove(true); + if (temporary_file->open()) + { + file = std::move(temporary_file); + } + } + else + { + auto persistent_file = std::make_unique(QString::fromStdString(file_to_map)); + if (persistent_file->open(QFile::ReadWrite)) + { + file = std::move(persistent_file); + } } - else if (mode == MAP_STORAGE_TYPE_PERSISTENT_FILE) + + if (!file) + { + debug(TM, + "Can't open a %s file named \"%s\"", + mode == MAP_STORAGE_TYPE_TEMP_FILE ? "temporary" : "persistent", + mode == MAP_STORAGE_TYPE_TEMP_FILE ? "" : file_to_map.c_str()); + return; + } + + ret = map_file(file.get()); + if (RET_IS_NOT_OK(ret)) { - ret = map_file(file_to_map); - if (RET_IS_NOT_OK(ret)) debug(TM, "Can't open file %s as persistent file", file_to_map.c_str()); - assert(RET_IS_OK(ret)); + debug(TM, "Can't map memory from %s", file->fileName().toLatin1().constData()); + file->close(); } + else + { + backing_file = file.release(); + } + + assert(RET_IS_OK(ret)); } @@ -241,22 +232,12 @@ namespace degate switch (storage_type) { case MAP_STORAGE_TYPE_MEM: - - if (mem_view != nullptr) free(mem_view); - mem_view = nullptr; - + delete[] mem_view; break; - case MAP_STORAGE_TYPE_PERSISTENT_FILE: - - unmap(); - break; + case MAP_STORAGE_TYPE_PERSISTENT_FILE: case MAP_STORAGE_TYPE_TEMP_FILE: - unmap(); - - remove_file(filename); - break; } } @@ -264,52 +245,34 @@ namespace degate template void MemoryMap::unmap() { - if (mem_view) + if (mem_view && backing_file) { -#ifdef SYS_WINDOWS - UnmapViewOfFile(mem_view); -#else - msync(mem_view, filesize, MS_SYNC); - munmap(mem_view, filesize); -#endif + backing_file->unmap(reinterpret_cast(mem_view)); mem_view = nullptr; } -#ifdef SYS_WINDOWS - if (mem_file) - { - CloseHandle(mem_file); - mem_file = nullptr; - } -#endif - - if (file) + if (backing_file && backing_file->isOpen()) { -#ifdef SYS_WINDOWS - CloseHandle(file); -#else - close(file); -#endif - file = 0; + backing_file->close(); + delete backing_file; } - filesize = 0; + backing_file = nullptr; } template ret_t MemoryMap::alloc_memory() { - /* If it is not null, it would indicates, - that there is already any allocation. */ + /* If it is not null, it would indicate that there is already an allocation. */ assert(mem_view == nullptr); assert(is_mem()); - mem_view = (T*)malloc(static_cast(width) * static_cast(height) * sizeof(T)); + mem_view = new (std::nothrow) T[static_cast(width) * static_cast(height)](); assert(mem_view != nullptr); - if (mem_view == nullptr) return RET_MALLOC_FAILED; - - memset(mem_view, 0, static_cast(width) * static_cast(height) * sizeof(T)); + if (mem_view == nullptr) { + return RET_MALLOC_FAILED; + } return RET_OK; } @@ -336,134 +299,33 @@ namespace degate if (mem_view != nullptr) { - unsigned int x, y; - for (y = min_y; y < min_y + height; y++) - memset(get_void_ptr(x, y), 0, width * sizeof(T)); + for (auto y = min_y; y < min_y + height; y++) + memset(get_void_ptr(min_x, y), 0, width * sizeof(T)); } } - /** * Use storage in file as storage for memory map */ template - ret_t MemoryMap::map_file(std::string const& filename) + ret_t MemoryMap::map_file(QFile* file) { + assert(file); assert(is_persistent_file() || is_temp_file()); - this->filename = filename; - -#ifdef SYS_WINDOWS - - file = CreateFileA(filename.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (!file) - { - debug(TM, "can't open file: %s", filename.c_str()); - return RET_ERR; - } - - LARGE_INTEGER res; - if (!GetFileSizeEx(file, &res)) - { - debug(TM, "can't get size of file: %s", filename.c_str()); - return RET_ERR; - } - filesize = static_cast(res.QuadPart); - - if (filesize < mem_size) - { - filesize = mem_size; - - const DWORD ret = SetFilePointer(file, static_cast(filesize - 1), nullptr, FILE_BEGIN); - if (ret == INVALID_SET_FILE_POINTER || ret == ERROR_NEGATIVE_SEEK) - { - debug(TM, "can't set file pointer of file: %s", filename.c_str()); - return RET_ERR; - } - - DWORD dwBytesWritten = 0; - char str[] = " "; - - const bool write_res = WriteFile(file, str, static_cast(strlen(str)), &dwBytesWritten, nullptr); - if (!write_res) - { - debug(TM, "can't write to file: %s", filename.c_str()); - return RET_ERR; - } - } - - mem_file = CreateFileMapping(file, nullptr, PAGE_READWRITE, 0, 0, nullptr); - if (!mem_file) + if (!file->resize(mem_size)) { - debug(TM, "can't map file: %s", filename.c_str()); + debug(TM, "cannot resize file %s", file->fileName().toLatin1().constData()); return RET_ERR; } -#else - - file = open(filename.c_str(), O_RDWR | O_CREAT, 0600); - if (file == -1) - { - debug(TM, "can't open file: %s", filename.c_str()); - return RET_ERR; - } - -#ifdef SYS_APPLE - - struct stat inf; - if (fstat(file, &inf) < 0) - -#else - - struct stat64 inf; - if (fstat64(file, &inf) < 0) - -#endif - { - debug(TM, "can't get the size of file: %s", filename.c_str()); - return RET_ERR; - } - - filesize = inf.st_size; - - if (filesize < mem_size) - { - filesize = mem_size; - lseek(file, filesize - 1, SEEK_SET); - if (write(file, " ", 1) != 1) - { - debug(TM, "can't open file: %s", filename.c_str()); - return RET_ERR; - } - } - -#endif - - assert(filesize >= mem_size); - -#ifdef SYS_WINDOWS - - mem_view = (T*)MapViewOfFile(mem_file, FILE_MAP_ALL_ACCESS, 0, 0, mem_size); - - if (!mem_view) + mem_view = reinterpret_cast(file->map(0, file->size())); + if (mem_view == nullptr) { - debug(TM, "can't create memory map"); + debug(TM, "cannot create memory map"); return RET_ERR; } -#else - - mem_view = (T*)mmap(nullptr, filesize, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, file, 0); - - if (mem_view == (void*)(-1)) - { - debug(TM, "can't create memory map"); - return RET_ERR; - } - -#endif - return RET_OK; } diff --git a/tests/src/MemoryMapTests.cc b/tests/src/MemoryMapTests.cc index 1d32faaa..7695e60e 100644 --- a/tests/src/MemoryMapTests.cc +++ b/tests/src/MemoryMapTests.cc @@ -20,6 +20,7 @@ */ #include "Core/Utils/MemoryMap.h" +#include "Core/Utils/FileSystem.h" #include "catch.hpp"