Ottimizzare C++/Tecniche generali di ottimizzazione/Input/Output: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
Riga 58:
#define MEMORY_FILE_HPP
#include <
/*
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(
typedef void* HANDLE;
HANDLE file_handle_;
HANDLE file_mapping_handle_;
#else
int file_handle_;
#endif
};
Line 103 ⟶ 101:
part of the file. The resulting size can be retrieved
using the "size" function.
The "reserve" grows the
The size of the resulting file can be retrieved using "capacity".
Memory mapped files cannot be
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_keep_else_fail
,if_exists_keep_else_create
,if_exists_truncate_else_fail
,if_exists_truncate_else_create
};
MemoryFile(const char *pathname, e_open_mode open_mode);
Line 132 ⟶ 130:
size_t size_;
size_t capacity_;
#if defined(
typedef void * HANDLE;
HANDLE file_handle_;
HANDLE file_mapping_handle_;
#else
int file_handle_;
#endif
};
#endif // MEMORY_FILE_HPP
</source>
Line 149 ⟶ 145:
<source lang=cpp>
#include "memory_file.hpp"
#if defined(
// 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>
#endif
Line 160 ⟶ 158:
data_(0),
size_(0),
#if defined(
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(
::UnmapViewOfFile(data_);
::CloseHandle(file_mapping_handle_);
::CloseHandle(file_handle_);
#else
::munmap(const_cast<char*>(data_), size_);
::close(file_handle_);
#endif
}
MemoryFile::MemoryFile(const char *pathname, e_open_mode open_mode):
data_(0),
size_(0),
#if defined(
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
windows_open_mode = CREATE_NEW;
break;
case
windows_open_mode = OPEN_EXISTING;
break;
case
windows_open_mode = OPEN_ALWAYS;
break;
case
windows_open_mode = TRUNCATE_EXISTING;
break;
case
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(
::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(
::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(
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::
MemoryFile::
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;
|