flatlaf-natives-windows: reworked memory allocation error handling

This commit is contained in:
Karl Tauber
2022-11-26 19:05:24 +01:00
parent c3adadfe2f
commit c9b5274ccf
5 changed files with 60 additions and 98 deletions

View File

@@ -1,53 +0,0 @@
#ifndef FLATLAF_WIN32_ALLOCROUTINES_H
#define FLATLAF_WIN32_ALLOCROUTINES_H
#include <stddef.h>
#include <windows.h>
struct FlatLafNoThrowT {
};
constexpr FlatLafNoThrowT FlatLafNoThrow{};
#if defined(_MSC_VER)
#define FLATLAF_WIN32_ALLOC_INLINE __forceinline
#elif (defined(__GNUC__) || defined(__clang__))
#define FLATLAF_WIN32_ALLOC_INLINE inline __attribute__((__always_inline__))
#else
#define FLATLAF_WIN32_ALLOC_INLINE inline
#endif
FLATLAF_WIN32_ALLOC_INLINE void* FlatLafWin32ProcessHeapAlloc(size_t cb) noexcept {
#ifdef _WIN32
return ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
#else
return ::calloc(cb, 1);
#endif
}
FLATLAF_WIN32_ALLOC_INLINE void FlatLafWin32ProcessHeapFree(void* pv) noexcept {
#ifdef _WIN32
if(pv)
::HeapFree(::GetProcessHeap(), 0, pv);
#else
if(pv)
::free(pv);
#endif
}
FLATLAF_WIN32_ALLOC_INLINE void* operator new(size_t cb, const FlatLafNoThrowT& tag) noexcept {
return FlatLafWin32ProcessHeapAlloc(cb);
}
FLATLAF_WIN32_ALLOC_INLINE void* operator new[](size_t cb, const FlatLafNoThrowT& tag) noexcept {
return FlatLafWin32ProcessHeapAlloc(cb);
}
FLATLAF_WIN32_ALLOC_INLINE void operator delete(void* pv, const FlatLafNoThrowT& tag) noexcept {
FlatLafWin32ProcessHeapFree(pv);
}
FLATLAF_WIN32_ALLOC_INLINE void operator delete[](void* pv, const FlatLafNoThrowT& tag) noexcept {
FlatLafWin32ProcessHeapFree(pv);
}
#endif

View File

@@ -23,7 +23,6 @@
#include <jawt.h> #include <jawt.h>
#include <jawt_md.h> #include <jawt_md.h>
#include "FlatWndProc.h" #include "FlatWndProc.h"
#include "AllocRoutines.h"
#include "com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc.h" #include "com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc.h"
/** /**
@@ -101,15 +100,9 @@ HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) {
// create HWND map // create HWND map
if( hwndMap == NULL ) { if( hwndMap == NULL ) {
HWNDMap* newHwndMap = new (FlatLafNoThrow) HWNDMap(); hwndMap = new HWNDMap();
if(newHwndMap == NULL) { if( hwndMap == NULL )
return 0; return 0;
} else if(!newHwndMap->isTableAllocated()) {
FlatLafWin32ProcessHeapFree(newHwndMap);
return 0;
}
hwndMap = newHwndMap;
} }
// get window handle // get window handle
@@ -117,15 +110,18 @@ HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) {
if( hwnd == NULL || hwndMap->get( hwnd ) != NULL ) if( hwnd == NULL || hwndMap->get( hwnd ) != NULL )
return 0; return 0;
FlatWndProc* fwp = new (FlatLafNoThrow) FlatWndProc(); FlatWndProc* fwp = new FlatWndProc();
if(fwp == NULL) if( fwp == NULL )
return 0; return 0;
if( !hwndMap->put( hwnd, fwp ) ) {
delete fwp;
return 0;
}
env->GetJavaVM( &fwp->jvm ); env->GetJavaVM( &fwp->jvm );
fwp->obj = env->NewGlobalRef( obj ); fwp->obj = env->NewGlobalRef( obj );
fwp->hwnd = hwnd; fwp->hwnd = hwnd;
if(!hwndMap->put( hwnd, fwp ))
return 0;
// replace window procedure // replace window procedure
fwp->defaultWndProc = reinterpret_cast<WNDPROC>( fwp->defaultWndProc = reinterpret_cast<WNDPROC>(
@@ -154,7 +150,7 @@ void FlatWndProc::uninstall( JNIEnv *env, jobject obj, HWND hwnd ) {
env->DeleteGlobalRef( fwp->obj ); env->DeleteGlobalRef( fwp->obj );
if( fwp->background != NULL ) if( fwp->background != NULL )
::DeleteObject( fwp->background ); ::DeleteObject( fwp->background );
FlatLafWin32ProcessHeapFree(fwp); delete fwp;
} }
void FlatWndProc::initIDs( JNIEnv *env, jobject obj ) { void FlatWndProc::initIDs( JNIEnv *env, jobject obj ) {
@@ -312,7 +308,7 @@ LRESULT FlatWndProc::WmDestroy( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lPara
if( background != NULL ) if( background != NULL )
::DeleteObject( background ); ::DeleteObject( background );
hwndMap->remove( hwnd ); hwndMap->remove( hwnd );
FlatLafWin32ProcessHeapFree(this); delete this;
// call original AWT window procedure because it may fire window closed event in AwtWindow::WmDestroy() // call original AWT window procedure because it may fire window closed event in AwtWindow::WmDestroy()
return ::CallWindowProc( defaultWndProc2, hwnd, uMsg, wParam, lParam ); return ::CallWindowProc( defaultWndProc2, hwnd, uMsg, wParam, lParam );

View File

@@ -18,10 +18,7 @@
#define _NO_CRT_STDIO_INLINE #define _NO_CRT_STDIO_INLINE
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include "HWNDMap.h" #include "HWNDMap.h"
#include "AllocRoutines.h"
#define DEFAULT_CAPACITY 20 #define DEFAULT_CAPACITY 20
#define INCREASE_CAPACITY 10 #define INCREASE_CAPACITY 10
@@ -46,8 +43,8 @@ public:
HWNDMap::HWNDMap() { HWNDMap::HWNDMap() {
size = 0; size = 0;
capacity = DEFAULT_CAPACITY; capacity = 0;
table = new (FlatLafNoThrow) Entry[capacity]; table = NULL;
::InitializeCriticalSection( &criticalSection ); ::InitializeCriticalSection( &criticalSection );
@@ -69,13 +66,12 @@ bool HWNDMap::put( HWND key, LPVOID value ) {
if( index >= 0 ) { if( index >= 0 ) {
// key already in map --> replace // key already in map --> replace
table[index].value = value; table[index].value = value;
return true;
} else { } else {
// insert new key // insert new key
if(size == INT_MAX || !ensureCapacity( size + 1 )) if( !ensureCapacity() )
return false; return false;
// make roor for new entry // make room for new entry
index = -(index + 1); index = -(index + 1);
for( int i = size - 1; i >= index; i-- ) for( int i = size - 1; i >= index; i-- )
table[i + 1] = table[i]; table[i + 1] = table[i];
@@ -84,10 +80,10 @@ bool HWNDMap::put( HWND key, LPVOID value ) {
// insert entry // insert entry
table[index].key = key; table[index].key = key;
table[index].value = value; table[index].value = value;
return true;
} }
// dump( "put" ); // dump( "put" );
return true;
} }
void HWNDMap::remove( HWND key ) { void HWNDMap::remove( HWND key ) {
@@ -108,6 +104,9 @@ void HWNDMap::remove( HWND key ) {
} }
int HWNDMap::binarySearch( HWND key ) { int HWNDMap::binarySearch( HWND key ) {
if( table == NULL )
return -1;
__int64 ikey = reinterpret_cast<__int64>( key ); __int64 ikey = reinterpret_cast<__int64>( key );
int low = 0; int low = 0;
int high = size - 1; int high = size - 1;
@@ -127,26 +126,25 @@ int HWNDMap::binarySearch( HWND key ) {
return -(low + 1); return -(low + 1);
} }
static constexpr size_t MaxEntryArrayLength = (SIZE_MAX >> 1) / sizeof(Entry); bool HWNDMap::ensureCapacity() {
static_assert(MaxEntryArrayLength > 0, "MaxEntryArrayLength > 0 must be true"); if( table == NULL ) {
table = new Entry[DEFAULT_CAPACITY];
if( table == NULL )
return false;
static constexpr int MaxEntryArrayIntCapacity = capacity = DEFAULT_CAPACITY;
(MaxEntryArrayLength <= INT_MAX) ? static_cast<int>(MaxEntryArrayLength) : INT_MAX; return true;
static_assert(MaxEntryArrayIntCapacity > 0, "MaxEntryArrayIntCapacity > 0 must be true"); }
bool HWNDMap::ensureCapacity( int minCapacity ) { // check capacity
if(minCapacity <= capacity) int minCapacity = size + 1;
if( minCapacity <= capacity )
return true; return true;
if(minCapacity > MaxEntryArrayIntCapacity)
return false;
// allocate new table // allocate new table
unsigned newCapacity = static_cast<unsigned>(minCapacity) + INCREASE_CAPACITY; int newCapacity = minCapacity + INCREASE_CAPACITY;
if(newCapacity > MaxEntryArrayIntCapacity) Entry* newTable = new Entry[newCapacity];
newCapacity = MaxEntryArrayIntCapacity; if( newTable == NULL )
Entry* newTable = new (FlatLafNoThrow) Entry[newCapacity];
if(newTable == NULL)
return false; return false;
// copy old table to new table // copy old table to new table
@@ -154,10 +152,10 @@ bool HWNDMap::ensureCapacity( int minCapacity ) {
newTable[i] = table[i]; newTable[i] = table[i];
// delete old table // delete old table
FlatLafWin32ProcessHeapFree(table); delete[] table;
table = newTable; table = newTable;
capacity = static_cast<int>(newCapacity); capacity = newCapacity;
return true; return true;
} }

View File

@@ -44,11 +44,10 @@ public:
LPVOID get( HWND key ); LPVOID get( HWND key );
bool put( HWND key, LPVOID value ); bool put( HWND key, LPVOID value );
void remove( HWND key ); void remove( HWND key );
bool isTableAllocated() noexcept { return static_cast<bool>(table); }
private: private:
int binarySearch( HWND key ); int binarySearch( HWND key );
bool ensureCapacity( int newCapacity ); bool ensureCapacity();
// void dump( char* msg ); // void dump( char* msg );
}; };

View File

@@ -41,6 +41,28 @@ BOOL WINAPI _DllMainCRTStartup( HINSTANCE instance, DWORD reason, LPVOID reserve
return TRUE; return TRUE;
} }
void* __cdecl operator new( size_t cb ) {
// printf( "new %d\n", cb );
return ::HeapAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, cb );
}
void* __cdecl operator new[]( size_t cb ) {
// printf( "new[] %d\n", cb );
return ::HeapAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, cb );
}
void __cdecl operator delete( void* pv, size_t cb ) {
// printf( "delete %p %d\n", pv, cb );
if( pv != NULL )
::HeapFree( ::GetProcessHeap(), 0, pv );
}
void __cdecl operator delete[]( void* pv ) {
// printf( "delete[] %p\n", pv );
if( pv != NULL )
::HeapFree( ::GetProcessHeap(), 0, pv );
}
/* /*
extern "C" extern "C"
int __cdecl printf( const char* format, ... ) { int __cdecl printf( const char* format, ... ) {