Skip to content

Commit

Permalink
メモリー使用量の削減
Browse files Browse the repository at this point in the history
  • Loading branch information
udaken committed May 1, 2018
1 parent 58c3a24 commit da02330
Show file tree
Hide file tree
Showing 2 changed files with 305 additions and 86 deletions.
200 changes: 191 additions & 9 deletions Gfl.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#pragma once
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#include "libgfl.h"
#include <vector>
#include <memory>
#include <cassert>
#include <map>
#include <set>

//#include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib")
Expand All @@ -16,6 +22,34 @@ LWSTDAPI_(LPWSTR) PathCombineW(__out_ecount(MAX_PATH) LPWSTR pszDest, __in_opt
LWSTDAPI_(BOOL) PathAppendA(__inout_ecount(MAX_PATH) LPSTR pszPath, __in LPCSTR pMore);
LWSTDAPI_(BOOL) PathAppendW(__inout_ecount(MAX_PATH) LPWSTR pszPath, __in LPCWSTR pMore);

#if defined(_DEBUG) || defined(DEBUG)
// Debugのとき
#define TRACE(x) OutputDebugString(x)
#define TRACE0(x) OutputDebugString(x)
#define TRACE1(x, a) OutputDebugString(x, a)
#define TRACE2(x, a, b) OutputDebugString(x, a, b)
#define TRACE3(x, a, b, c) OutputDebugString(x, a, b, c)
#define TRACE4(x, a, b, c, d) OutputDebugString(x, a, b, c, d)
#else
// Releaseのとき
#define TRACE(x)
#define TRACE0(x)
#define TRACE1(x, a)
#define TRACE2(x, a, b)
#define TRACE3(x, a, b, c)
#define TRACE4(x, a, b, c, d)
#endif

inline void OutputDebugStr(LPCSTR pszFormat, ...)
{
va_list argp;
char pszBuf[256];
va_start(argp, pszFormat);
vsprintf_s(pszBuf, pszFormat, argp);
va_end(argp);
OutputDebugStringA(pszBuf);
}

enum class GflError : GFL_INT16
{
NoError = GFL_NO_ERROR,
Expand Down Expand Up @@ -61,19 +95,22 @@ class GflLibrary final
public:
GflLibrary() noexcept
{
WCHAR buf[MAX_PATH] = {};
if (g_hModule)
{
WCHAR buf[MAX_PATH] = {};
::GetModuleFileName(g_hModule, buf, _countof(buf));
::PathRemoveFileSpecW(buf);
::PathAppendW(buf, L"libgfl340.dll");
hLibgfl = ::LoadLibrary(buf);
}
::PathAppendW(buf, L"libgfl340.dll");
hLibgfl = ::LoadLibrary(buf);

if (hLibgfl)
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

#define GETPROCADDRESS(hModule, _f) reinterpret_cast<decltype(&_f)>(::GetProcAddress(hLibgfl, #_f))
LibraryInit = GETPROCADDRESS(hLibgfl, gflLibraryInit);
LibraryInitEx = GETPROCADDRESS(hLibgfl, gflLibraryInitEx);
LibraryExit = GETPROCADDRESS(hLibgfl, gflLibraryExit);
EnableLZW = GETPROCADDRESS(hLibgfl, gflEnableLZW);
FreeFileInformation = GETPROCADDRESS(hLibgfl, gflFreeFileInformation);
Expand All @@ -89,11 +126,15 @@ class GflLibrary final
GetFileInformation = GETPROCADDRESS(hLibgfl, gflGetFileInformation);
LoadBitmapFromMemory = GETPROCADDRESS(hLibgfl, gflLoadBitmapFromMemory);
LoadBitmap = GETPROCADDRESS(hLibgfl, gflLoadBitmap);
Alloc = GETPROCADDRESS(hLibgfl, gflMemoryAlloc);
Realloc = GETPROCADDRESS(hLibgfl, gflMemoryRealloc);
Free = GETPROCADDRESS(hLibgfl, gflMemoryFree);
#undef GETPROCADDRESS
}
}
~GflLibrary() noexcept
{
_CrtDumpMemoryLeaks();
if (hLibgfl)
::FreeLibrary(hLibgfl);
}
Expand All @@ -102,6 +143,7 @@ class GflLibrary final
return hLibgfl != nullptr;
}
decltype(::gflLibraryInit) *LibraryInit = nullptr;
decltype(::gflLibraryInitEx) *LibraryInitEx = nullptr;
decltype(::gflLibraryExit) *LibraryExit = nullptr;
decltype(::gflEnableLZW) *EnableLZW = nullptr;
decltype(::gflFreeFileInformation) *FreeFileInformation = nullptr;
Expand All @@ -117,7 +159,11 @@ class GflLibrary final
decltype(::gflGetFileInformation) *GetFileInformation = nullptr;
decltype(::gflLoadBitmapFromMemory) *LoadBitmapFromMemory = nullptr;
decltype(::gflLoadBitmap) *LoadBitmap = nullptr;
decltype(::gflMemoryAlloc) *Alloc = nullptr;
decltype(::gflMemoryRealloc) *Realloc = nullptr;
decltype(::gflMemoryFree) *Free = nullptr;
private:

HMODULE hLibgfl = nullptr;
};

Expand Down Expand Up @@ -158,22 +204,160 @@ class GflLibraryInit final
public:
GflLibraryInit(const GflLibrary & lib, bool enableLzw = true) : lib(lib)
{
OutputDebugStr("[%08X] GflLibraryInit: %p\r\n", ::GetCurrentThreadId(), this);

if (lib.isLoaded())
{
auto result = lib.LibraryInit();
//auto result = lib.LibraryInit();
auto result = lib.LibraryInitEx(allocCallBack, reallocCallBack, freeCallback, this);
GlfCheckError(result);
if (enableLzw)
lib.EnableLZW(GFL_TRUE);
}
}
~GflLibraryInit()
{
OutputDebugStr("[%08X] ~GflLibraryInit: %p\r\n", ::GetCurrentThreadId(), this);

if (lib.isLoaded())
lib.LibraryExit();
}
class LargeHeapManager
{
public:
CRITICAL_SECTION cs;
LargeHeapManager()
{
::InitializeCriticalSection(&cs);
};
~LargeHeapManager()
{
::DeleteCriticalSection(&cs);
}

std::map<void*, std::unique_ptr<void, decltype(&::LocalFree)>> listOfHeap;
};

static LargeHeapManager* GetHeapManager()
{
static LargeHeapManager instance;
return &instance;
}

HLOCAL DettachFromHeapManager(void* ptr)
{
CriticalSectionScope cs(&GetHeapManager()->cs);
auto &listOfHeap = GetHeapManager()->listOfHeap;
auto itr = listOfHeap.find(ptr);
if (itr != listOfHeap.end())
{
auto hLocal = itr->second.release();
OutputDebugStr("[%08X] Dettach: %p\r\n", ::GetCurrentThreadId(), ptr);
return hLocal;
}
return nullptr;
}

private:

struct CriticalSectionScope
{
CRITICAL_SECTION *cs;
CriticalSectionScope(CRITICAL_SECTION *cs) : cs(cs)
{
::EnterCriticalSection(cs);
}
~CriticalSectionScope()
{
::LeaveCriticalSection(cs);
}
};

const static size_t HeapThreathold = 1 * 1024 * 1024;
static void* GFLAPI allocCallBack(size_t size, void* user_parms)
{
if (size > HeapThreathold)
{
OutputDebugStr("[%08X] Custom Allocator: %u Bytes ", ::GetCurrentThreadId(), size);
auto this_ = reinterpret_cast<GflLibraryInit*>(user_parms);
CriticalSectionScope cs(&this_->GetHeapManager()->cs);
auto &listOfHeap = this_->GetHeapManager()->listOfHeap;

#ifdef NDEBUG
size += 16;
#endif
auto hLocal = ::LocalAlloc(LMEM_MOVEABLE, size);
if (hLocal)
{
auto p = ::LocalLock(hLocal);
listOfHeap.emplace(
std::piecewise_construct,
std::forward_as_tuple(p),
std::forward_as_tuple(hLocal, &::LocalFree));
OutputDebugStr("->Allocates: %p \r\n", p);
return p;
}
}
#ifndef NDEBUG
return malloc(size);
#else
return malloc(size + 16);
#endif
}
static void* GFLAPI reallocCallBack(void* ptr, size_t new_size, void* user_parms)
{
auto this_ = reinterpret_cast<GflLibraryInit*>(user_parms);
CriticalSectionScope cs(&this_->GetHeapManager()->cs);
auto &listOfHeap = this_->GetHeapManager()->listOfHeap;
auto itr = listOfHeap.find(ptr);
if (itr != listOfHeap.end())
{
HLOCAL hNewLoacl = ::LocalReAlloc(itr->second.get(), new_size, LMEM_MOVEABLE);
if (!hNewLoacl)
return nullptr;

itr->second.release();
listOfHeap.erase(itr);

auto p = ::LocalLock(hNewLoacl);
listOfHeap.emplace(
std::piecewise_construct,
std::forward_as_tuple(p),
std::forward_as_tuple(hNewLoacl, &::LocalFree));
return p;
}
return realloc(ptr, new_size);
}
static void GFLAPI freeCallback(void* ptr, void* user_parms)
{
auto this_ = reinterpret_cast<GflLibraryInit*>(user_parms);
CriticalSectionScope cs(&this_->GetHeapManager()->cs);
auto &listOfHeap = this_->GetHeapManager()->listOfHeap;
if (listOfHeap.size() > 0 && listOfHeap.count(ptr) > 0)
{
OutputDebugStr("[%08X] Custom Deleter: %p\r\n", ::GetCurrentThreadId(), ptr);
auto itr = listOfHeap.find(ptr);
if (itr != listOfHeap.end())
{
if (itr->second)
{
OutputDebugStr("->LocalFree: %p\r\n", itr->second.get());
assert(::LocalFree(itr->second.release()) == NULL);
}
else
{
//nothing
OutputDebugStr("->Already Deleted: %p\r\n", ptr);
}

listOfHeap.erase(itr);
return;
}
}
return free(ptr);
}
const GflLibrary & lib;
};
};

class GflInfomation final : public GFL_FILE_INFORMATION
{
Expand All @@ -185,19 +369,17 @@ class GflInfomation final : public GFL_FILE_INFORMATION
{
std::swap(hadFree, other.hadFree);
}
void free()
void Free()
{
if (!hadFree)
{
lib.FreeFileInformation(this);
hadFree = true;
}

}
~GflInfomation()
{
if (!hadFree)
lib.FreeFileInformation(this);
Free();
}
private:
const GflLibrary & lib;
Expand Down
Loading

0 comments on commit da02330

Please sign in to comment.