Ottimizzare C++/Tecniche generali di ottimizzazione/Input/Output: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Riga 58:
#define MEMORY_FILE_HPP
 
#include <cstringstddef.h> // foror <cstddef> and using std::size_t
/*
Riga 72:
class InputMemoryFile {
public:
explicit InputMemoryFile(const char *pathname);
~InputMemoryFile();
const char* data() const { return data_; }
Riga 79:
const char* data_;
size_t size_;
#if defined(__unix___WIN32)
int file_handle_;
#elif defined(_WIN32)
typedef void* HANDLE;
HANDLE file_handle_;
HANDLE file_mapping_handle_;
#else
int file_handle_;
#error Only Posix or Windows systems can use memory-mapped files.
#endif
};
Line 103 ⟶ 101:
part of the file. The resulting size can be retrieved
using the "size" function.
The "reserve" grows the phisicalphysical file to the specified number of bytes.
The size of the resulting file can be retrieved using "capacity".
Memory mapped files cannot be shrinkedshrunk;
a value smaller than the current capacity is ignored.
The "capacity()" function return the size the physical file has at this time.
Line 114 ⟶ 112:
public:
enum e_open_mode {
if_exists_fail_else_create
if_exists_fail_if_not_exists_create,
,if_exists_keep_else_fail
if_exists_keep_if_dont_exists_fail,
,if_exists_keep_else_create
if_exists_keep_if_dont_exists_create,
,if_exists_truncate_else_fail
if_exists_truncate_if_not_exists_fail,
,if_exists_truncate_else_create
if_exists_truncate_if_not_exists_create,
};
MemoryFile(const char *pathname, e_open_mode open_mode);
Line 132 ⟶ 130:
size_t size_;
size_t capacity_;
#if defined(__unix___WIN32)
int file_handle_;
#elif defined(_WIN32)
typedef void * HANDLE;
HANDLE file_handle_;
HANDLE file_mapping_handle_;
#else
int file_handle_;
#error Only Posix or Windows systems can use memory-mapped files.
#endif
};
#endif // MEMORY_FILE_HPP
</source>
 
Line 149 ⟶ 145:
<source lang=cpp>
#include "memory_file.hpp"
#if defined(__unix___WIN32)
// our typedefs MemoryFile::HANDLE and InputMemoryFile::HANDLE play nice with typedef HANDLE
#include <windows.h>
#else
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#elif defined(_WIN32)
#include <windows.h>
#endif
Line 160 ⟶ 158:
data_(0),
size_(0),
#if defined(__unix___WIN32)
file_handle_(-1)
{
file_handle_ = ::open(pathname, O_RDONLY);
if (file_handle_ == -1) return;
struct stat sbuf;
if (::fstat(file_handle_, &sbuf) == -1) return;
data_ = static_cast<const char*>(::mmap(
0, sbuf.st_size, PROT_READ, MAP_SHARED, file_handle_, 0));
if (data_ == MAP_FAILED) data_ = 0;
else size_ = sbuf.st_size;
#elif defined(_WIN32)
file_handle_(INVALID_HANDLE_VALUE),
file_mapping_handle_(INVALID_HANDLE_VALUE)
#else
file_handle_(-1)
#endif
{
#if defined(_WIN32)
file_handle_ = ::CreateFile(pathname, GENERIC_READ,
FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
Line 184 ⟶ 175:
file_mapping_handle_, FILE_MAP_READ, 0, 0, 0));
if (data_) size_ = ::GetFileSize(file_handle_, 0);
#else
file_handle_ = ::open(pathname, O_RDONLY);
if (file_handle_ == -1) return;
struct stat sbuf;
if (::fstat(file_handle_, &sbuf) == -1) return;
data_ = static_cast<const char*>(::mmap(
0, sbuf.st_size, PROT_READ, MAP_SHARED, file_handle_, 0));
if (data_ == MAP_FAILED) data_ = 0;
else size_ = sbuf.st_size;
#endif
}
InputMemoryFile::~InputMemoryFile() {
#if defined(__unix___WIN32)
::munmap(const_cast<char*>(data_), size_);
::close(file_handle_);
#elif defined(_WIN32)
::UnmapViewOfFile(data_);
::CloseHandle(file_mapping_handle_);
::CloseHandle(file_handle_);
#else
::munmap(const_cast<char*>(data_), size_);
::close(file_handle_);
#endif
}
 
#include <iostream>
MemoryFile::MemoryFile(const char *pathname, e_open_mode open_mode):
data_(0),
size_(0),
#if defined(__unix___WIN32)
file_handle_(-1)
{
int posix_open_mode = O_RDWR;
switch (open_mode)
{
case if_exists_fail_if_not_exists_create:
posix_open_mode |= O_EXCL | O_CREAT;
break;
case if_exists_keep_if_dont_exists_fail:
break;
case if_exists_keep_if_dont_exists_create:
posix_open_mode |= O_CREAT;
break;
case if_exists_truncate_if_not_exists_fail:
posix_open_mode |= O_TRUNC;
break;
case if_exists_truncate_if_not_exists_create:
posix_open_mode |= O_TRUNC | O_CREAT;
break;
default: return;
}
const size_t min_file_size = 4096;
file_handle_ = ::open(pathname, posix_open_mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (file_handle_ == -1) return;
struct stat sbuf;
if (::fstat(file_handle_, &sbuf) == -1) return;
size_t initial_file_size = sbuf.st_size;
size_t adjusted_file_size = initial_file_size == 0 ? min_file_size : initial_file_size;
::ftruncate(file_handle_, adjusted_file_size);
data_ = static_cast<char*>(::mmap(
0, adjusted_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, file_handle_, 0));
if (data_ == MAP_FAILED) data_ = 0;
else {
size_ = initial_file_size;
capacity_ = adjusted_file_size;
}
#elif defined(_WIN32)
file_handle_(INVALID_HANDLE_VALUE),
file_mapping_handle_(INVALID_HANDLE_VALUE)
#else
file_handle_(-1)
#endif
{
#if defined(_WIN32)
int windows_open_mode;
switch (open_mode)
{
case if_exists_fail_if_not_exists_createif_exists_fail_else_create:
windows_open_mode = CREATE_NEW;
break;
case if_exists_keep_if_dont_exists_failif_exists_keep_else_fail:
windows_open_mode = OPEN_EXISTING;
break;
case if_exists_keep_if_dont_exists_createif_exists_keep_else_create:
windows_open_mode = OPEN_ALWAYS;
break;
case if_exists_truncate_if_not_exists_failif_exists_truncate_else_fail:
windows_open_mode = TRUNCATE_EXISTING;
break;
case if_exists_truncate_if_not_exists_createif_exists_truncate_else_create:
windows_open_mode = CREATE_ALWAYS;
break;
Line 275 ⟶ 241:
file_mapping_handle_, FILE_MAP_WRITE, 0, 0, 0));
if (data_) {
size_ = initial_file_size;
capacity_ = adjusted_file_size;
}
#else
int posix_open_mode = O_RDWR;
switch (open_mode)
{
case if_exists_fail_else_create:
posix_open_mode |= O_EXCL | O_CREAT;
break;
case if_exists_keep_else_fail:
break;
case if_exists_keep_else_create:
posix_open_mode |= O_CREAT;
break;
case if_exists_truncate_else_fail:
posix_open_mode |= O_TRUNC;
break;
case if_exists_truncate_else_create:
posix_open_mode |= O_TRUNC | O_CREAT;
break;
default: return;
}
const size_t min_file_size = 4096;
file_handle_ = ::open(pathname, posix_open_mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (file_handle_ == -1) return;
struct stat sbuf;
if (::fstat(file_handle_, &sbuf) == -1) return;
size_t initial_file_size = sbuf.st_size;
size_t adjusted_file_size = (initial_file_size == 0) ? min_file_size : initial_file_size;
::ftruncate(file_handle_, adjusted_file_size);
data_ = static_cast<char*>(::mmap(
0, adjusted_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, file_handle_, 0));
if (data_ == MAP_FAILED) data_ = 0;
else {
size_ = initial_file_size;
capacity_ = adjusted_file_size;
Line 288 ⟶ 289:
void MemoryFile::reserve(size_t new_capacity) {
if (new_capacity <= capacity_) return;
#if defined(__unix___WIN32)
::munmap(data_, size_);
::ftruncate(file_handle_, new_capacity);
data_ = static_cast<char*>(::mmap(
0, new_capacity, PROT_READ | PROT_WRITE, MAP_SHARED, file_handle_, 0));
if (data_ == MAP_FAILED) data_ = 0;
capacity_ = new_capacity;
#elif defined(_WIN32)
::UnmapViewOfFile(data_);
::CloseHandle(file_mapping_handle_);
Line 303 ⟶ 297:
data_ = static_cast<char*>(::MapViewOfFile(
file_mapping_handle_, FILE_MAP_WRITE, 0, 0, 0));
#else
::munmap(data_, size_);
::ftruncate(file_handle_, new_capacity);
data_ = static_cast<char*>(::mmap(
0, new_capacity, PROT_READ | PROT_WRITE, MAP_SHARED, file_handle_, 0));
if (data_ == MAP_FAILED) data_ = 0;
capacity_ = new_capacity;
#endif
}
 
MemoryFile::~MemoryFile() {
#if defined(__unix___WIN32)
::munmap(data_, size_);
if (size_ != capacity_)
{
::ftruncate(file_handle_, size_);
}
::close(file_handle_);
#elif defined(_WIN32)
::UnmapViewOfFile(data_);
::CloseHandle(file_mapping_handle_);
Line 323 ⟶ 317:
}
::CloseHandle(file_handle_);
#else
::munmap(data_, size_);
if (size_ != capacity_)
{
::ftruncate(file_handle_, size_);
}
::close(file_handle_);
#endif
}
 
bool MemoryFile::flush() {
#if defined(__unix___WIN32)
return ::msync(data_, size_, MS_SYNC) == 0;
#elif defined(_WIN32)
return ::FlushViewOfFile(data_, size_) != 0;
#else
return ::msync(data_, size_, MS_SYNC) == 0;
#endif
}
Line 339 ⟶ 340:
<source lang=cpp>
#include "memory_file.hpp"
#include <iostream> // for std::cerr
 
// TODO review interface, reader cannot tell what CopyFile(backupfile, preciousfile, false) will do
bool CopyFile(const char* source, const char* dest, bool overwrite)
{
Line 346 ⟶ 348:
if (! source_mf.data()) return false;
MemoryFile dest_mf(dest, overwrite ?
MemoryFile::if_exists_truncate_if_not_exists_createif_exists_truncate_else_create :
MemoryFile::if_exists_fail_if_not_exists_createif_exists_fail_else_create);
if (! dest_mf.data()) return false;
dest_mf.resize(source_mf.size());
Line 357 ⟶ 359:
 
int main() {
if (! CopyFile("memory_file_test.cpp", "copy.tmp", true)) {
std::cerr << "Copy failed" << std::endl;
return 1;