SharedControl class is now synchronized shared class.

Fixed working of SharedControl.invoke/delayInvoke methods when a given-function has multiple arguments.
This commit is contained in:
haru-s 2024-09-01 00:01:21 +09:00
parent bf168783ef
commit e26ea5fe78
2 changed files with 86 additions and 97 deletions

View file

@ -2043,7 +2043,7 @@ else
enum LRESULT LRESULT_DFL_INVOKE = 0x95FADF; // Magic number. enum LRESULT LRESULT_DFL_INVOKE = 0x95FADF; // Magic number.
UINT wmDfl; UINT wmDfl; // TODO: shared?
enum: WPARAM enum: WPARAM
{ {

View file

@ -1,7 +1,3 @@
// Written by Christopher E. Miller
// See the included license.txt for copyright and license details.
/// ///
module dfl.sharedcontrol; module dfl.sharedcontrol;
@ -13,26 +9,31 @@ private import dfl.internal.winapi;
private import dfl.internal.dlib; private import dfl.internal.dlib;
private import dfl.internal.clib : malloc, free; private import dfl.internal.clib : malloc, free;
private import core.atomic;
/// ///
shared class SharedControl synchronized shared class SharedControl
{ {
private: private:
Control _ctrl; Control _ctrl;
void makeParam(ARGS...)(void function(Control, ARGS) func, ARGS args, DflInvokeParam* dflInvokeParam) void makeParam(ARGS...)(ref void function(Control, ARGS) func, ref ARGS args, ref DflInvokeParam* dflInvokeParam)
if (ARGS.length) if (ARGS.length)
{ {
static struct FunctionInvokeParam static struct FunctionInvokeParam
{ {
void function(Control, ARGS) func;
ARGS args; ARGS args;
void function(Control, ARGS) func; // NOTE: This function pointer must be after "args", why?
} }
auto invokeParam = cast(FunctionInvokeParam*)malloc(FunctionInvokeParam.sizeof); auto invokeParam = cast(FunctionInvokeParam*)malloc(FunctionInvokeParam.sizeof);
if (!invokeParam) if (!invokeParam)
throw new OomException(); throw new OomException();
invokeParam.func = func; invokeParam.func.atomicStore(func.atomicLoad());
invokeParam.args = args; static foreach (i, e; args)
{
invokeParam.args[i].atomicStore(e.atomicLoad());
}
static void funcEntry(Control c, size_t[] p) static void funcEntry(Control c, size_t[] p)
{ {
@ -41,13 +42,13 @@ private:
free(param); free(param);
} }
dflInvokeParam.fp = &funcEntry; dflInvokeParam.fp.atomicStore(&funcEntry);
dflInvokeParam.exception = null; dflInvokeParam.exception.atomicStore(null);
dflInvokeParam.nparams = 1; dflInvokeParam.nparams.atomicStore(1);
dflInvokeParam.params[0] = cast(size_t)invokeParam; dflInvokeParam.params[0].atomicStore(cast(size_t)invokeParam);
} }
void makeParamNoneArgs(void function(Control) func, DflInvokeParam* dflInvokeParam) void makeParamNoneArgs(ref void function(Control) func, ref DflInvokeParam* dflInvokeParam)
{ {
static void funcEntry(Control c, size_t[] p) static void funcEntry(Control c, size_t[] p)
{ {
@ -74,110 +75,98 @@ public:
void invoke(ARGS...)(void function(Control, ARGS) func, ARGS args) void invoke(ARGS...)(void function(Control, ARGS) func, ARGS args)
if (ARGS.length && !hasLocalAliasing!(ARGS)) if (ARGS.length && !hasLocalAliasing!(ARGS))
{ {
synchronized auto ctrl = cast(Control)_ctrl;
auto hwnd = ctrl.handle;
if(!hwnd)
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle();
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof);
if (!dflInvokeParam)
throw new OomException();
makeParam(func, args, dflInvokeParam);
scope(exit)
{ {
auto ctrl = cast(Control)_ctrl; free(dflInvokeParam);
auto hwnd = ctrl.handle;
if(!hwnd)
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle();
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof);
if (!dflInvokeParam)
throw new OomException();
makeParam(func, args, dflInvokeParam);
scope(exit)
{
free(dflInvokeParam);
}
if (LRESULT_DFL_INVOKE != SendMessageA(hwnd, wmDfl, WPARAM_DFL_INVOKE_PARAMS, cast(LPARAM)dflInvokeParam))
throw new DflException("Invoke failure");
if (dflInvokeParam.exception)
throw dflInvokeParam.exception;
} }
if (LRESULT_DFL_INVOKE != SendMessageA(hwnd.atomicLoad(), wmDfl.atomicLoad(), WPARAM_DFL_INVOKE_PARAMS.atomicLoad(), cast(LPARAM)dflInvokeParam))
throw new DflException("Invoke failure");
if (dflInvokeParam.exception)
throw dflInvokeParam.exception;
} }
/// ///
void invoke(ARGS...)(void function(Control, ARGS) func, ARGS args) void invoke(ARGS...)(void function(Control, ARGS) func, ARGS args)
if (!ARGS.length) if (!ARGS.length)
{ {
synchronized auto ctrl = cast(Control)_ctrl;
auto hwnd = ctrl.handle;
if(!hwnd)
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle();
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof);
if (!dflInvokeParam)
throw new OomException();
makeParamNoneArgs(func, dflInvokeParam);
scope(exit)
{ {
auto ctrl = cast(Control)_ctrl; free(dflInvokeParam);
auto hwnd = ctrl.handle;
if(!hwnd)
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle();
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof);
if (!dflInvokeParam)
throw new OomException();
makeParamNoneArgs(func, dflInvokeParam);
scope(exit)
{
free(dflInvokeParam);
}
if (LRESULT_DFL_INVOKE != SendMessageA(hwnd, wmDfl, WPARAM_DFL_INVOKE_NOPARAMS, cast(LPARAM)dflInvokeParam))
throw new DflException("Invoke failure");
if (dflInvokeParam.exception)
throw dflInvokeParam.exception;
} }
if (LRESULT_DFL_INVOKE != SendMessageA(hwnd.atomicLoad(), wmDfl.atomicLoad(), WPARAM_DFL_INVOKE_NOPARAMS.atomicLoad(), cast(LPARAM)dflInvokeParam))
throw new DflException("Invoke failure");
if (dflInvokeParam.exception)
throw dflInvokeParam.exception;
} }
/// ///
void delayInvoke(ARGS...)(void function(Control, ARGS) func, ARGS args) void delayInvoke(ARGS...)(void function(Control, ARGS) func, ARGS args)
if (ARGS.length && !hasLocalAliasing!(ARGS)) if (ARGS.length && !hasLocalAliasing!(ARGS))
{ {
synchronized auto ctrl = cast(Control)_ctrl;
{ auto hwnd = ctrl.handle;
auto ctrl = cast(Control)_ctrl;
auto hwnd = ctrl.handle; if(!hwnd)
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle();
if(!hwnd)
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle(); static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof); auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof); // NOTE: You must free memory in window procedure.
if (!dflInvokeParam)
auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof); // NOTE: You must free memory in window procedure. throw new OomException();
if (!dflInvokeParam)
throw new OomException(); makeParam(func, args, dflInvokeParam);
PostMessageA(hwnd.atomicLoad(), wmDfl.atomicLoad(), WPARAM_DFL_DELAY_INVOKE_PARAMS.atomicLoad(), cast(LPARAM)dflInvokeParam);
makeParam(func, args, dflInvokeParam);
PostMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_PARAMS, cast(LPARAM)dflInvokeParam);
}
} }
/// ///
void delayInvoke(ARGS...)(void function(Control, ARGS) func, ARGS args) void delayInvoke(ARGS...)(void function(Control, ARGS) func, ARGS args)
if (!ARGS.length) if (!ARGS.length)
{ {
synchronized auto ctrl = cast(Control)_ctrl;
{ auto hwnd = ctrl.handle;
auto ctrl = cast(Control)_ctrl;
auto hwnd = ctrl.handle; if(!hwnd)
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle();
if(!hwnd)
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle(); static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof); auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof); // NOTE: You must free memory in window procedure.
if (!dflInvokeParam)
auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof); // NOTE: You must free memory in window procedure. throw new OomException();
if (!dflInvokeParam)
throw new OomException(); makeParamNoneArgs(func, dflInvokeParam);
PostMessageA(hwnd.atomicLoad(), wmDfl.atomicLoad(), WPARAM_DFL_DELAY_INVOKE_NOPARAMS.atomicLoad(), cast(LPARAM)dflInvokeParam);
makeParamNoneArgs(func, dflInvokeParam);
PostMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_NOPARAMS, cast(LPARAM)dflInvokeParam);
}
} }
} }