win_xept.hpp -一个基本的windows异常
#include "../utl_macro.hpp"
namespace xept
{
using win_t = struct utl_exception // utl_exception randomly generates a name
// this hides exception names from rtti
{
DWORD e = GetLastError( );
};
}ramfile.hpp -在ram中需要数据的任何类型文件的接口。
#pragma once
class ramfile_t
{
public:
virtual std::uintmax_t size( ) = 0;
virtual std::vector< std::byte > raw( ) = 0;
virtual void overwrite( std::vector< std::byte > const & raw,
std::size_t const & off = 0 ) = 0;
virtual void set( std::vector< std::byte > const & raw ) = 0;
};ramfile_xept.hpp -基本的ramfile异常
#include "../win_xept.hpp"
namespace xept
{
using ramfile_t = struct utl_exception:
win_t
{ };
}ramfile_disk.hpp -磁盘的基本文件
class ramfile_disk_t:
public ramfile_t
{
public:
ramfile_disk_t( std::filesystem::path path ):
path( std::move( path ) ),
file_guard( file_locks[ this->path.c_str( ) ] )
{
assert( path.is_absolute( ) );
}
std::uintmax_t size( ) final
{
return std::filesystem::file_size( path );
}
std::vector< std::byte > raw( ) final
{
std::basic_ifstream< std::byte > file( path,
std::ofstream::binary );
assert( file.is_open( )
&& file.good( ) );
file.seekg( 0 );
return std::vector< std::byte >( std::istreambuf_iterator< std::byte >( file ),
std::istreambuf_iterator< std::byte >( ) );
}
void set( std::vector< std::byte > const & data ) final
{
std::basic_ofstream< std::byte > file( path,
std::ofstream::binary | std::ofstream::trunc );
assert( file.is_open( )
&& file.good( ) );
file.write( data.data( ),
data.size( ) );
}
void overwrite( std::vector< std::byte > const & data,
std::size_t const & off = 0 ) final
{
std::basic_ofstream< std::byte > file( path,
std::ofstream::binary );
assert( file.is_open( )
&& file.good( ) );
file.seekp( off ).write( data.data( ),
data.size( ) );
}
void set_attr( bool readonly,
bool hidden )
{
DWORD attr = 0;
if ( readonly )
attr |= FILE_ATTRIBUTE_READONLY;
if ( hidden )
attr |= FILE_ATTRIBUTE_HIDDEN;
if ( 0 == SetFileAttributes( path.c_str( ),
attr
? attr
: FILE_ATTRIBUTE_NORMAL ) )
throw xept::ramfile_disk_attr_t( );
}
protected:
std::filesystem::path path;
private:
using file_locks_t = std::unordered_map< std::wstring_view,
std::mutex >;
static file_locks_t file_locks;
std::lock_guard< file_locks_t::mapped_type > file_guard;
};ramfile_disk_xept.hpp -可从ramfile_disk抛出的异常
#include "ramfile_xept.h"
namespace xept
{
using ramfile_disk_attr_t = struct utl_exception:
ramfile_t
{ };
}发布于 2020-07-11 09:05:05
设计:设计非常糟糕。多想想你打算如何使用它。目前,它容易出现死锁。
例如,在同一文件的代码中的两个不同位置创建两个ramfile_disk_t实例。第二个实例将被阻塞,直到第一个实例完成。这就是你想要的吗?这是您希望使用代码的唯一方式吗?
至少添加如下选项:
Technical问题:
#include "../win_xept.hpp"。假设某个地方有另一个win_xept.hpp文件,用户添加了一个包含路径,这会导致加载错误的win_xept.hpp。这导致了腐败。如果有什么需要的话,您最好为所有的代码文件创建一个额外的文件夹,这样才更安全。所以你总是包括#include "my_codebase/current_project/win_xept.hpp"。作为奖励,您的代码将得到更好的组织。create函数,根据用户的请求实例化实现。这样,用户在任何时候都不需要包含实现的头。ramfile_t是一个具有虚拟函数的类。因此,它应该有一个虚拟析构函数(virtual ~ramfile_t() = default)。对于纯抽象类尤其如此。另外,你真的认为你会有更多的这个类的实现,为什么还要考虑这个接口呢?ramfile_disk_t与静态成员file_locks存在数据竞争问题。每次访问它时,都应该使用互斥锁来保护它。fread或iostream的read,而不是基于迭代器的方法。至少做些测试。overwrite方法中是否有任何理由将D36作为const引用传递?只需通过值std::size_t off传递它;不仅通过引用传递速度更慢,而且当您试图在异步线程中调度函数时,它就会变得很麻烦。https://codereview.stackexchange.com/questions/245298
复制相似问题