抛弃GdCpp*.dll/pdb历史重新建库。libhv和Sqlite的dll保留
This commit is contained in:
391
source/Mem/CImageBuf.cpp
Normal file
391
source/Mem/CImageBuf.cpp
Normal file
@@ -0,0 +1,391 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "Mem\CImageBuf.h"
|
||||
#include <Windows.h>
|
||||
#include "GdCpp.h"
|
||||
//#include "json.h"
|
||||
#include "aLog.h"
|
||||
#include <cstdio> // FILE, _wfopen_s, fwrite, fclose
|
||||
|
||||
// 颜色类型与BPP的对应关系
|
||||
std::map<uint32_t, uint32_t> sImageInfo::MapColor2BBP;
|
||||
// 颜色类型与BPP的对应关系
|
||||
std::map<uint32_t, uint32_t> sImageInfo::MapBBP2Color;
|
||||
|
||||
static RGBQUAD bmiColors[256] = { 0 };
|
||||
|
||||
bool CImageBuf::saveBMP(const wchar_t* filename)
|
||||
{
|
||||
if (!filename) return false;
|
||||
|
||||
FILE* f = nullptr;
|
||||
errno_t err = _wfopen_s(&f, filename, L"wb"); // 二进制写入,覆盖创建
|
||||
if (err != 0 || !f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
do {
|
||||
BITMAPFILEHEADER fileheader = {};
|
||||
BITMAPINFOHEADER infoheader = {};
|
||||
static const char _blank[2] = { 0 };
|
||||
|
||||
// 填充信息头
|
||||
infoheader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
infoheader.biWidth = Width;
|
||||
infoheader.biHeight = -Height; // top-down BMP
|
||||
infoheader.biPlanes = 1;
|
||||
infoheader.biBitCount = BPP * 8;
|
||||
infoheader.biCompression = BI_RGB; // 0 = BI_RGB
|
||||
infoheader.biSizeImage = LineSize * Height;
|
||||
infoheader.biXPelsPerMeter = 3780;
|
||||
infoheader.biYPelsPerMeter = 3780;
|
||||
infoheader.biClrUsed = 0;
|
||||
infoheader.biClrImportant = 0;
|
||||
|
||||
// 文件头
|
||||
fileheader.bfType = 0x4D42; // 'BM' = 19778
|
||||
fileheader.bfReserved1 = 0;
|
||||
fileheader.bfReserved2 = 0;
|
||||
|
||||
// 计算像素数据偏移
|
||||
if (BPP == 3) {
|
||||
fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2; // +2 for alignment
|
||||
}
|
||||
else if (BPP == 1) {
|
||||
fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD) + 2;
|
||||
}
|
||||
else {
|
||||
// 不支持的 BPP
|
||||
break;
|
||||
}
|
||||
|
||||
fileheader.bfSize = fileheader.bfOffBits + infoheader.biSizeImage;
|
||||
|
||||
// 写入文件头
|
||||
if (fwrite(&fileheader, sizeof(fileheader), 1, f) != 1) break;
|
||||
if (fwrite(&infoheader, sizeof(infoheader), 1, f) != 1) break;
|
||||
|
||||
// 写入调色板(仅 8-bit)
|
||||
if (BPP == 1) {
|
||||
if (bmiColors[255].rgbRed == 0) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
bmiColors[i].rgbRed = (BYTE)i;
|
||||
bmiColors[i].rgbGreen = (BYTE)i;
|
||||
bmiColors[i].rgbBlue = (BYTE)i;
|
||||
bmiColors[i].rgbReserved = 0;
|
||||
}
|
||||
}
|
||||
if (fwrite(bmiColors, sizeof(RGBQUAD), 256, f) != 256) break;
|
||||
}
|
||||
|
||||
// 写入对齐填充(2 字节)
|
||||
if (fwrite(_blank, sizeof(_blank), 1, f) != 1) break;
|
||||
|
||||
// 写入像素数据
|
||||
if (fwrite(Addr(), 1, infoheader.biSizeImage, f) != infoheader.biSizeImage) break;
|
||||
|
||||
ret = true;
|
||||
} while (0);
|
||||
|
||||
// 错误处理:记录失败原因(可选)
|
||||
if (!ret) {
|
||||
alog->error(L"Failed to write BMP file: {}", filename);
|
||||
}
|
||||
|
||||
if (f) fclose(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 保存原始数据
|
||||
bool CImageBuf::saveRaw(std::wstring& filename)
|
||||
{
|
||||
if (filename.empty()) return false;
|
||||
|
||||
FILE* f = nullptr;
|
||||
errno_t err = _wfopen_s(&f, filename.c_str(), L"wb");
|
||||
if (err != 0 || !f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t written = fwrite(Addr(), 1, ImageSize, f);
|
||||
fclose(f);
|
||||
|
||||
return (written == ImageSize);
|
||||
}
|
||||
|
||||
// 从 std::wstring 加载原始数据
|
||||
bool CImageBuf::loadRaw(std::wstring& filename)
|
||||
{
|
||||
if (filename.empty()) return false;
|
||||
|
||||
FILE* f = nullptr;
|
||||
errno_t err = _wfopen_s(&f, filename.c_str(), L"rb");
|
||||
if (err != 0 || !f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t read = fread(Addr(), 1, ImageSize, f);
|
||||
fclose(f);
|
||||
|
||||
return (read == ImageSize);
|
||||
}
|
||||
|
||||
// 从 const wchar_t* 加载原始数据
|
||||
bool CImageBuf::loadRaw(const wchar_t* filename)
|
||||
{
|
||||
if (!filename) return false;
|
||||
|
||||
FILE* f = nullptr;
|
||||
errno_t err = _wfopen_s(&f, filename, L"rb");
|
||||
if (err != 0 || !f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t read = fread(Addr(), 1, ImageSize, f);
|
||||
fclose(f);
|
||||
|
||||
return (read == ImageSize);
|
||||
}
|
||||
|
||||
void CImageBuf::debugCopyErr(int err, const char* exinfo)
|
||||
{
|
||||
/*switch(err){
|
||||
case Ok:
|
||||
break;
|
||||
case Err_DstWidth:
|
||||
qsError() << exinfo << "dest w is larger than width";
|
||||
break;
|
||||
case Err_DstHeight:
|
||||
qsError() << exinfo << "dest y is larger than height";
|
||||
break;
|
||||
case Warn_CropWidth:
|
||||
qsWarn() << exinfo << "image is croped in width";
|
||||
break;
|
||||
case Warn_CropHeight:
|
||||
qsWarn() << exinfo << "image is croped in height";
|
||||
break;
|
||||
}*/
|
||||
}
|
||||
///将来源目标图像缓冲区的(sx,sy,sw,sh)区域的数据复制到目标图像缓冲区的(dx,dy)处。两者的bpp必须相同
|
||||
int CImageBuf::copy(CImageBuf* src, int sx, int sy, int sw, int sh, CImageBuf* dst, int dx, int dy, const char* debugstr)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t* sp = src->getAddr(sx, sy);
|
||||
uint8_t* dp = dst->getAddr(dx, dy);
|
||||
|
||||
int dw = dst->Width - dx; //目标缓冲区可写的宽度
|
||||
int dh = dst->Height - dy; //目标缓冲区可写的高度
|
||||
do {
|
||||
if (dw <= 0) {
|
||||
ret = Err_DstWidth; //dx超出了目标缓冲区的范围
|
||||
break;
|
||||
}
|
||||
if (dh <= 0) {
|
||||
ret = Err_DstHeight; //dy超出了目标缓冲区的范围
|
||||
break;
|
||||
}
|
||||
|
||||
//判断宽度是否超出
|
||||
if (sw > dw) {
|
||||
sw = dw;
|
||||
ret = Warn_CropWidth;
|
||||
}
|
||||
if (sh > dh) {
|
||||
sh = dh;
|
||||
ret = Warn_CropHeight;
|
||||
}
|
||||
size_t line = size_t(sw * src->BPP);
|
||||
for (int h = 0; h < sh; h++) {
|
||||
memcpy(dp, sp, line);
|
||||
sp += src->LineSize;
|
||||
dp += dst->LineSize;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (debugstr) {
|
||||
debugCopyErr(ret, debugstr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CImageBuf::copy(CImageBuf* src, int sx, int sy, int sw, int sh, uint8_t* dst)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t* sp = src->getAddr(sx, sy);
|
||||
uint8_t* dp = dst;
|
||||
|
||||
|
||||
do {
|
||||
size_t line = size_t(sw * src->BPP);
|
||||
for (int h = 0; h < sh; h++) {
|
||||
memcpy(dp, sp, line);
|
||||
sp += src->LineSize;
|
||||
dp += line;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/// buf1,buf2数值相加平均写到dst,长度为line
|
||||
static void meanline(uint8_t* buf1, uint8_t* buf2, uint8_t* dst, int line)
|
||||
{
|
||||
for (int i = 0; i < line; i++) {
|
||||
*dst++ = uint8_t((uint32_t(*buf1++) + uint32_t(*buf2++)) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
///叠加图片,颜色值各取1/2
|
||||
int CImageBuf::overlay(CImageBuf* src, int sx, int sy, int sw, int sh, CImageBuf* dst, int dx, int dy, const char* debugstr)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t* sp = src->getAddr(sx, sy);
|
||||
uint8_t* dp = dst->getAddr(dx, dy);
|
||||
|
||||
int dw = dst->Width - dx; //目标缓冲区可写的宽度
|
||||
int dh = dst->Height - dy; //目标缓冲区可写的高度
|
||||
do {
|
||||
if (dw <= 0) {
|
||||
ret = Err_DstWidth; //dx超出了目标缓冲区的范围
|
||||
break;
|
||||
}
|
||||
if (dh <= 0) {
|
||||
ret = Err_DstHeight; //dy超出了目标缓冲区的范围
|
||||
break;
|
||||
}
|
||||
|
||||
//判断宽度是否超出
|
||||
if (sw > dw) {
|
||||
sw = dw;
|
||||
ret = Warn_CropWidth;
|
||||
}
|
||||
if (sh > dh) {
|
||||
sh = dh;
|
||||
ret = Warn_CropHeight;
|
||||
}
|
||||
size_t line = size_t(sw * src->BPP);
|
||||
// 创建临时行
|
||||
uint8_t* tmpline = new uint8_t[size_t(line)];
|
||||
for (int h = 0; h < sh; h++) {
|
||||
meanline(dp, sp, dp, int(line));
|
||||
sp += src->LineSize;
|
||||
dp += dst->LineSize;
|
||||
}
|
||||
delete[] tmpline;
|
||||
} while (0);
|
||||
|
||||
if (debugstr) {
|
||||
debugCopyErr(ret, debugstr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CImageBuf::fill4(uint32_t val)
|
||||
{
|
||||
auto* pline = Addr();
|
||||
switch (BPP) {
|
||||
case 1: { //一次算4个像素
|
||||
val &= 0xFF;
|
||||
uint32_t v = val | val << 8 | val << 16 | val << 24;
|
||||
for (int h = 0; h < Height; h++) {
|
||||
auto p = (uint32_t*)pline;
|
||||
for (int i = 0; i < Width / 4; i++) *p++ = v;
|
||||
|
||||
pline += LineSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: { //一次算4个像素
|
||||
val &= 0xFFFFFF;
|
||||
uint32_t v1 = val | val << 24;
|
||||
uint32_t v2 = (val >> 8) | (val << 16);
|
||||
uint32_t v3 = (val >> 16) | (val << 8);
|
||||
for (int h = 0; h < Height; h++) {
|
||||
auto p = (uint32_t*)pline;
|
||||
for (int i = 0; i < Width / 4; i++) {
|
||||
*p++ = v1;
|
||||
*p++ = v2;
|
||||
*p++ = v3;
|
||||
}
|
||||
pline += LineSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {//一次算1个像素
|
||||
for (int h = 0; h < Height; h++) {
|
||||
auto p = (uint32_t*)pline;
|
||||
for (int i = 0; i < Width; i++) *p++ = val;
|
||||
pline += LineSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// 填充颜色,要求4像素对齐
|
||||
void CImageBuf::fill4(uint32_t val, int x, int y, int W, int H)
|
||||
{
|
||||
auto* pline = getAddr(x, y);
|
||||
switch (BPP) {
|
||||
case 1: { //一次算4个像素
|
||||
val &= 0xFF;
|
||||
uint32_t v = val | val << 8 | val << 16 | val << 24;
|
||||
for (int h = 0; h < H; h++) {
|
||||
auto p = (uint32_t*)pline;
|
||||
for (int i = 0; i < W / 4; i++) *p++ = v;
|
||||
|
||||
pline += LineSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: { //一次算4个像素
|
||||
val &= 0xFFFFFF;
|
||||
uint32_t v1 = val | val << 24;
|
||||
uint32_t v2 = (val >> 8) | (val << 16);
|
||||
uint32_t v3 = (val >> 16) | (val << 8);
|
||||
for (int h = 0; h < H; h++) {
|
||||
auto p = (uint32_t*)pline;
|
||||
for (int i = 0; i < W / 4; i++) {
|
||||
*p++ = v1;
|
||||
*p++ = v2;
|
||||
*p++ = v3;
|
||||
}
|
||||
pline += LineSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {//一次算1个像素
|
||||
for (int h = 0; h < H; h++) {
|
||||
auto p = (uint32_t*)pline;
|
||||
for (int i = 0; i < W; i++) *p++ = val;
|
||||
pline += LineSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//cv::Mat toMat(const CImageBuf& img)
|
||||
//{
|
||||
// switch (img.BytePerPix)
|
||||
// {
|
||||
// case 1:
|
||||
// return cv::Mat(img.Height, img.Width, CV_8UC1, img.Addr, img.LineSize);
|
||||
// case 2:
|
||||
// return cv::Mat(img.Height, img.Width, CV_8UC2, img.Addr, img.LineSize);
|
||||
// case 3:
|
||||
// return cv::Mat(img.Height, img.Width, CV_8UC3, img.Addr, img.LineSize);
|
||||
// case 4:
|
||||
// return cv::Mat(img.Height, img.Width, CV_8UC4, img.Addr, img.LineSize);
|
||||
// default:
|
||||
// return cv::Mat();
|
||||
// }
|
||||
//}
|
||||
|
||||
478
source/Mem/CMem.cpp
Normal file
478
source/Mem/CMem.cpp
Normal file
@@ -0,0 +1,478 @@
|
||||
#include "pch.h"
|
||||
#include "Mem\CMem.h"
|
||||
#include <Windows.h>
|
||||
#include "AlignSize.h"
|
||||
//#include "CSystemSemaphore.h"
|
||||
#include "aLog.h"
|
||||
|
||||
// 静态成员变量
|
||||
size_t CMemUsage::totalContainerSize=0;
|
||||
size_t CMemUsage::totalMemSize=0;
|
||||
std::list<CMemUsage*> CMemUsage::MemList;
|
||||
std::mutex CMemUsage::MemListLock;
|
||||
|
||||
std::mutex CMem::uplocker;
|
||||
|
||||
|
||||
void CMemUsage::report(std::wstring& str)
|
||||
{
|
||||
std::lock_guard guard(MemListLock); // 加锁
|
||||
_updateUsage();
|
||||
str = L"内存使用统计:\n";
|
||||
for (auto mem : MemList)
|
||||
{
|
||||
if(mem->memName.empty()) {
|
||||
str += fmt::format(L"未命名, {}, {}k/{}k, {}M/{}M\n", mem->memType.c_str(), mem->memSize / 1_K, mem->containerSize / 1_K, mem->memSize / 1_M, mem->containerSize / 1_M);
|
||||
}else {
|
||||
str += fmt::format(L"{}, {}, {}k/{}k, {}M/{}M\n", mem->memName.c_str(), mem->memType.c_str(), mem->memSize / 1_K, mem->containerSize / 1_K, mem->memSize / 1_M, mem->containerSize / 1_M);
|
||||
}
|
||||
}
|
||||
|
||||
str += fmt::format(L"\n总内存:{}M/{}M\n", totalMemSize / 1_M, totalContainerSize / 1_M);
|
||||
}
|
||||
|
||||
|
||||
bool CMem::_allocVirtual(void* addr, size_t size, bool commit)
|
||||
{
|
||||
const DWORD flag = (commit) ? (MEM_RESERVE | MEM_COMMIT) : MEM_RESERVE;
|
||||
// 执行windows api
|
||||
Addr = static_cast<uint8_t*>(VirtualAlloc(
|
||||
addr, // 0: 系统自动分配地址, 其他值:指定未使用的内存地址
|
||||
size, // Size of allocation
|
||||
flag,
|
||||
PAGE_READWRITE)); //只支持Read + Write,未考虑其他情况
|
||||
// 结果
|
||||
if (Addr) { // 分配成功
|
||||
containerSize = size;
|
||||
memSize = (commit) ? size : 0;
|
||||
selfAlloc = true;
|
||||
return true;
|
||||
}
|
||||
else { // 调用处来处理不成功的情况,这里不管
|
||||
containerSize = 0;
|
||||
memSize = 0;
|
||||
selfAlloc = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* CMem::allocVirtual(size_t size)
|
||||
{
|
||||
// 执行windows api
|
||||
return static_cast<uint8_t*>(VirtualAlloc(
|
||||
nullptr, // 0: 系统自动分配地址, 其他值:指定未使用的内存地址
|
||||
size, // Size of allocation
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE)); //只支持Read + Write,未考虑其他情况
|
||||
}
|
||||
|
||||
void CMem::freeVirtual(uint8_t* addr)
|
||||
{
|
||||
if(addr) VirtualFree(addr, 0, MEM_RELEASE);
|
||||
// 未处理失败情况,假设不会失败
|
||||
// 此处addr未清零,在dealloc()中清零
|
||||
}
|
||||
|
||||
bool CMem::_allocUpperVirtual(size_t size, bool commit)
|
||||
{
|
||||
const DWORD flag = (commit) ? (MEM_RESERVE | MEM_TOP_DOWN | MEM_COMMIT) : (MEM_RESERVE | MEM_TOP_DOWN);
|
||||
// 执行windows api
|
||||
Addr = static_cast<uint8_t*>(VirtualAlloc(
|
||||
nullptr, // System selects address
|
||||
size, // Size of allocation
|
||||
flag,
|
||||
PAGE_READWRITE)); //只支持Read + Write,未考虑其他情况
|
||||
// 结果
|
||||
if (Addr) {
|
||||
containerSize = size;
|
||||
memSize = 0;
|
||||
selfAlloc = true;
|
||||
return true;
|
||||
}
|
||||
else { // 调用处来处理不成功的情况,这里不管
|
||||
containerSize = 0;
|
||||
memSize = 0;
|
||||
selfAlloc = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 分配虚拟内存
|
||||
bool CWinMem::alloc(void* addr, size_t container, size_t size)
|
||||
{
|
||||
// addr可以为0或指定某个未分配的地址
|
||||
ASSERT(container != 0); //虚拟内存大小,不能为0
|
||||
ASSERT(size <= container);//物理内存大小不超过虚拟内存大小,可以为0
|
||||
|
||||
AlignUp(container, 64 * 1024); // 调整虚拟内存大小对齐到64k。win默认按64k分配虚拟内存
|
||||
AlignUp(size, 4 * 1024); // 调整物理内存大小对齐到4k。win默认按4k分配物理内存
|
||||
|
||||
if (size == 0) {
|
||||
return _allocVirtual(addr, container, false); // 不分配物理内存
|
||||
} else if (size == container) {
|
||||
return _allocVirtual(addr, container, true); // 分配全部物理内存
|
||||
} else {
|
||||
const bool ret = _allocVirtual(addr, container, false);
|
||||
if (!ret) {
|
||||
selfAlloc = false;
|
||||
return false;
|
||||
}
|
||||
if (nullptr != VirtualAlloc(Addr, size, MEM_COMMIT, PAGE_READWRITE)) { // 分配指定大小的物理内存
|
||||
memSize = size;
|
||||
selfAlloc = true;
|
||||
} else {
|
||||
selfAlloc = true; // 虽然没有物理内存, 分到虚拟内存了也算selfAlloc
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWinMem::allocUpper(size_t container, size_t size)
|
||||
{
|
||||
ASSERT(container != 0);
|
||||
ASSERT(size <= container);
|
||||
|
||||
AlignUp(container, 64_K);
|
||||
AlignUp(size, 4_K);
|
||||
|
||||
std::lock_guard guard(uplocker);
|
||||
|
||||
if (size == 0) {
|
||||
return _allocUpperVirtual(container, false);
|
||||
}
|
||||
else if (size == container) {
|
||||
return _allocUpperVirtual(container, true);
|
||||
}
|
||||
else {
|
||||
const bool ret = _allocUpperVirtual(container, false);
|
||||
if (!ret) {
|
||||
selfAlloc = false;
|
||||
return false;
|
||||
}
|
||||
if (nullptr != VirtualAlloc(Addr, size, MEM_COMMIT, PAGE_READWRITE)) {
|
||||
memSize = size;
|
||||
selfAlloc = true;
|
||||
}
|
||||
else {
|
||||
selfAlloc = true; // 虽然没有物理内存, 分到虚拟内存了也算selfAlloc
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 调整大小不影响containerSize、Addr和selfAlloc
|
||||
bool CWinMem::resize(size_t size)
|
||||
{
|
||||
if (containerSize == 0) return false;
|
||||
AlignUp(size, 4 * 1024);
|
||||
if (size > containerSize) return false;
|
||||
if (size == memSize) {
|
||||
return true;
|
||||
}
|
||||
else if (size > memSize) {
|
||||
if (nullptr != VirtualAlloc(Addr + memSize, size - memSize, MEM_COMMIT, PAGE_READWRITE)) {
|
||||
memSize = size;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
VirtualFree(Addr + size, memSize - size, MEM_DECOMMIT); // 有多的释放掉
|
||||
memSize = size;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// 调整大小不影响containerSize、Addr和selfAlloc
|
||||
bool CWinMem::reserve(size_t size)
|
||||
{
|
||||
if (containerSize == 0) return false;
|
||||
AlignUp(size, 4 * 1024);
|
||||
if (size > containerSize) return false;
|
||||
if (size == memSize) return true;
|
||||
else if (size > memSize) {
|
||||
if (nullptr != VirtualAlloc(Addr + memSize, size - memSize, MEM_COMMIT, PAGE_READWRITE)) {
|
||||
memSize = size;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}else {
|
||||
//VirtualFree(Addr + size, memSize - size, MEM_DECOMMIT); // 有多的不释放
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CWinMem::dealloc()
|
||||
{
|
||||
if (Addr) {
|
||||
VirtualFree(Addr, 0, MEM_RELEASE); // 只能release整个区域
|
||||
}
|
||||
CMem::dealloc();
|
||||
}
|
||||
|
||||
std::wstring CWinMem::details()
|
||||
{
|
||||
std::wstring str = fmt::format(L"虚拟内存地址:{}, 大小{}M,物理内存大小{}M\n", (void*)Addr, containerSize / 1_M, memSize / 1_M);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CFileMapMem2::allocNamed(const std::wstring& name, size_t container, size_t size)
|
||||
{
|
||||
// 确认调用前的状态,避免逻辑错误
|
||||
ASSERT(hand == nullptr); // 未创建内存映射文件
|
||||
ASSERT(containerSize == 0); // 未映射文件
|
||||
ASSERT(allMem.containerSize == 0); // 未分配虚拟内存
|
||||
ASSERT(allMem.Addr == nullptr);
|
||||
ASSERT(memSize == 0); // 未映射文件
|
||||
// 确认参数有效
|
||||
ASSERT(container > 0);
|
||||
ASSERT(isAlign(container, 64_K));
|
||||
ASSERT(size ==0);
|
||||
|
||||
_nativeKey = std::wstring(L"Ks_Grabber_MemMapFile_") + name;
|
||||
|
||||
std::lock_guard guard(uplocker);
|
||||
|
||||
allMem.Addr = static_cast<uint8_t*>(VirtualAlloc(
|
||||
nullptr, // System selects address
|
||||
container * 2, // Size of allocation
|
||||
MEM_RESERVE | MEM_TOP_DOWN,
|
||||
PAGE_READWRITE)); //只支持Read + Write,未考虑其他情况
|
||||
|
||||
if(!allMem.Addr) return false;
|
||||
|
||||
allMem.containerSize = container * 2;
|
||||
allMem.memSize = 0;
|
||||
|
||||
// Create the file mapping.
|
||||
hand = CreateFileMapping(INVALID_HANDLE_VALUE
|
||||
, nullptr
|
||||
, PAGE_READWRITE | SEC_COMMIT // 不能加SEC_NOCACHE
|
||||
, container >> 32, container & 0xFFFFFFFFu,
|
||||
_nativeKey.c_str());
|
||||
|
||||
if (!hand) {
|
||||
VirtualFree(allMem.Addr, 0, MEM_RELEASE); // 释放虚拟内存空间
|
||||
allMem.containerSize = 0;
|
||||
selfAlloc = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 供外部访问的内存属性
|
||||
Addr = nullptr; //地址后面mapFile()时再计算,反正只有映射了才能真正访问到。
|
||||
containerSize = container; // 容量可以先保存下来。
|
||||
memSize = 0;
|
||||
memName = name;
|
||||
selfAlloc = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CFileMapMem2::dealloc()
|
||||
{
|
||||
std::lock_guard guard(uplocker);
|
||||
unmapFile(false);
|
||||
|
||||
if(hand)
|
||||
{
|
||||
CloseHandle(hand);
|
||||
hand = nullptr;
|
||||
}
|
||||
selfAlloc = false;
|
||||
}
|
||||
|
||||
bool CFileMapMem2::resize(size_t size)
|
||||
{
|
||||
std::lock_guard guard(uplocker);
|
||||
if (containerSize == 0) return false;
|
||||
if (size > containerSize) return false;
|
||||
|
||||
if (size == 0) {
|
||||
if (memSize == containerSize) {
|
||||
unmapFile(true);
|
||||
}
|
||||
else if (memSize == 0) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else if (size == containerSize) {
|
||||
if (memSize == containerSize) {
|
||||
return true; // nothing todo
|
||||
}
|
||||
else if (memSize == 0) {
|
||||
return mapFile();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFileMapMem2::mapFile()
|
||||
{
|
||||
ASSERT(hand != nullptr);
|
||||
ASSERT(allMem.containerSize > 0);
|
||||
|
||||
size_t fileSize = allMem.containerSize / 2;
|
||||
size_t halfSize1 = fileSize / 2;
|
||||
AlignDown(halfSize1, 64_K);
|
||||
size_t halfSize2 = allMem.containerSize/2 - halfSize1;
|
||||
|
||||
ULARGE_INTEGER fileOffset1, fileOffset2;
|
||||
fileOffset1.QuadPart = 0;
|
||||
fileOffset2.QuadPart = halfSize1;
|
||||
VirtualFree(allMem.Addr, 0, MEM_RELEASE); // 释放虚拟内存空间
|
||||
//但内存总容量allMem.containerSize保持不变
|
||||
|
||||
// 内存 映像文件
|
||||
// -------------
|
||||
// | 2 |
|
||||
// ============== --- ==============
|
||||
// | 1 | | 1 |
|
||||
// -------------- --------------
|
||||
// | 2 | | 2 |
|
||||
// ============== --- ==============
|
||||
// | 1 |
|
||||
// --------------
|
||||
Addr = (uint8_t*)MapViewOfFileEx(hand, FILE_MAP_ALL_ACCESS
|
||||
, fileOffset1.HighPart, fileOffset1.LowPart
|
||||
, fileSize, allMem.Addr + halfSize2);
|
||||
|
||||
if(!Addr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
containerSize = memSize = allMem.containerSize/2;
|
||||
|
||||
BottomMem.Addr = (uint8_t*)MapViewOfFileEx(hand, FILE_MAP_READ
|
||||
, fileOffset1.HighPart, fileOffset1.LowPart
|
||||
, halfSize1, allMem.Addr + halfSize2 + fileSize);
|
||||
|
||||
TopMem.Addr = (uint8_t*)MapViewOfFileEx(hand, FILE_MAP_READ
|
||||
, fileOffset2.HighPart, fileOffset2.LowPart
|
||||
, halfSize2, allMem.Addr);
|
||||
|
||||
if(!TopMem.Addr || !BottomMem.Addr) // 前面成功了,这里不大可能失败,稳妥起见加上
|
||||
{
|
||||
UnmapViewOfFile(Addr);
|
||||
Addr = nullptr;
|
||||
containerSize = memSize = 0;
|
||||
|
||||
if (TopMem.Addr) UnmapViewOfFile(TopMem.Addr);
|
||||
if (BottomMem.Addr) UnmapViewOfFile(BottomMem.Addr);
|
||||
|
||||
TopMem.dealloc();
|
||||
BottomMem.dealloc();
|
||||
return false;
|
||||
}else
|
||||
{
|
||||
TopMem.containerSize = halfSize2;
|
||||
TopMem.memSize = 0;
|
||||
BottomMem.containerSize = halfSize1;
|
||||
TopMem.memSize = 0;
|
||||
}
|
||||
verifyMap();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CFileMapMem2::unmapFile(bool realloc)
|
||||
{
|
||||
if (containerSize == 0 || hand == nullptr) return;
|
||||
|
||||
if (memSize == containerSize) {
|
||||
if (TopMem.Addr) UnmapViewOfFile(TopMem.Addr);
|
||||
if (BottomMem.Addr) UnmapViewOfFile(BottomMem.Addr);
|
||||
if (Addr) UnmapViewOfFile(Addr);
|
||||
|
||||
TopMem.dealloc();
|
||||
BottomMem.dealloc();
|
||||
|
||||
Addr = nullptr;
|
||||
containerSize = memSize = 0;
|
||||
|
||||
if (realloc) {
|
||||
_allocVirtual(allMem.Addr, allMem.containerSize, false);
|
||||
}
|
||||
else {
|
||||
allMem.dealloc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CFileMapMem2::verifyMap(bool compare_content)
|
||||
{
|
||||
ASSERT(hand != nullptr);
|
||||
// 验证容量
|
||||
ASSERT(containerSize != 0);
|
||||
ASSERT(memSize = containerSize);
|
||||
ASSERT(containerSize = allMem.containerSize / 2);
|
||||
ASSERT(TopMem.containerSize + BottomMem.containerSize == containerSize);
|
||||
// 验证地址
|
||||
ASSERT(allMem.Addr);
|
||||
ASSERT(TopMem.Addr == allMem.Addr);
|
||||
ASSERT(Addr == allMem.Addr + TopMem.containerSize);
|
||||
ASSERT(BottomMem.Addr = Addr + containerSize);
|
||||
// 验证内容
|
||||
bool succ = true;
|
||||
if(compare_content)
|
||||
{
|
||||
uint64_t* p = (uint64_t*)(Addr);
|
||||
for(int i=0; i<containerSize/8; i++)
|
||||
{
|
||||
*p++ = i;
|
||||
}
|
||||
if (memcmp(Addr, BottomMem.Addr, BottomMem.containerSize) != 0)
|
||||
{
|
||||
alog->error("memcmp(Addr, BottomMem.Addr, BottomMem.containerSize) != 0");
|
||||
succ = false;
|
||||
}
|
||||
else {
|
||||
alog->info("底部映射验证通过");
|
||||
}
|
||||
|
||||
if (memcmp(Addr + BottomMem.containerSize, TopMem.Addr, TopMem.containerSize) != 0)
|
||||
{
|
||||
alog->error("Addr + BottomMem.containerSize, TopMem.Addr, TopMem.containerSize) != 0");
|
||||
succ = false;
|
||||
}
|
||||
else {
|
||||
alog->info("顶部映射验证通过");
|
||||
}
|
||||
}
|
||||
return succ;
|
||||
}
|
||||
|
||||
std::wstring CFileMapMem2::details()
|
||||
{
|
||||
std::wstring str = fmt::format(L"虚拟内存地址:{}, 大小{}M\n", (void *)allMem.Addr, allMem.containerSize/1_M);
|
||||
|
||||
str += fmt::format(L"数据内存地址:{}, 偏移量:{}M,大小{}M\n", (void*)Addr, (Addr - allMem.Addr) / 1_M, memSize / 1_M);
|
||||
str += fmt::format(L"底部内存地址:{}, 偏移量:{:4d}M,大小{:4d}M,映射到偏移量{:4d}M\n"
|
||||
, (void*)BottomMem.Addr, (BottomMem.Addr - allMem.Addr) / 1_M, BottomMem.containerSize / 1_M, (Addr - allMem.Addr) / 1_M);
|
||||
str += fmt::format(L"顶部内存地址:{}, 偏移量:{:4d}M,大小{:4d}M,映射到偏移量{:4d}M\n"
|
||||
, (void*)TopMem.Addr, (TopMem.Addr - allMem.Addr) / 1_M, TopMem.containerSize / 1_M, (TopMem.containerSize+ BottomMem.containerSize) / 1_M);
|
||||
|
||||
return str;
|
||||
}
|
||||
2
source/Mem/CStack.cpp
Normal file
2
source/Mem/CStack.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "pch.h"
|
||||
#include "Mem\CStack.h"
|
||||
Reference in New Issue
Block a user