diff options
author | Dan Gudmundsson <[email protected]> | 2015-07-07 10:38:38 +0200 |
---|---|---|
committer | Dan Gudmundsson <[email protected]> | 2015-07-07 10:38:38 +0200 |
commit | fcbc24440945a13b379b2b6135599c982bf8bdf0 (patch) | |
tree | 5c04db3494dfe5c196ab291da7bb2dcddadcf101 | |
parent | 70cb9432dc03ac9435b2c8c5fe2e8fd0608015dc (diff) | |
download | otp-fcbc24440945a13b379b2b6135599c982bf8bdf0.tar.gz otp-fcbc24440945a13b379b2b6135599c982bf8bdf0.tar.bz2 otp-fcbc24440945a13b379b2b6135599c982bf8bdf0.zip |
wx: Add event callback fastpath
Avoids spawn but can deadlock
-rw-r--r-- | lib/wx/api_gen/wx_extra/wxEvtHandler.erl | 2 | ||||
-rw-r--r-- | lib/wx/src/gen/wxEvtHandler.erl | 2 | ||||
-rw-r--r-- | lib/wx/src/wxe_server.erl | 35 | ||||
-rw-r--r-- | lib/wx/test/wx_event_SUITE.erl | 11 |
4 files changed, 32 insertions, 18 deletions
diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl index c9726fd475..85ebc093f5 100644 --- a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl +++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl @@ -70,6 +70,8 @@ connect(This=#wx_ref{type=ThisT}, EventType, Options) -> parse_opts([{callback,Fun}|R], Opts) when is_function(Fun) -> %% Check Fun Arity? parse_opts(R, Opts#evh{cb=Fun}); +parse_opts([{callback,CB={nospawn, Fun}}|R], Opts) when is_function(Fun) -> + parse_opts(R, Opts#evh{cb=CB}); parse_opts([callback|R], Opts) -> parse_opts(R, Opts#evh{cb=self()}); parse_opts([{userData, UserData}|R],Opts) -> diff --git a/lib/wx/src/gen/wxEvtHandler.erl b/lib/wx/src/gen/wxEvtHandler.erl index 6e9770bbb6..2d0a87f4dd 100644 --- a/lib/wx/src/gen/wxEvtHandler.erl +++ b/lib/wx/src/gen/wxEvtHandler.erl @@ -90,6 +90,8 @@ connect(This=#wx_ref{type=ThisT}, EventType, Options) -> parse_opts([{callback,Fun}|R], Opts) when is_function(Fun) -> %% Check Fun Arity? parse_opts(R, Opts#evh{cb=Fun}); +parse_opts([{callback,CB={nospawn, Fun}}|R], Opts) when is_function(Fun) -> + parse_opts(R, Opts#evh{cb=CB}); parse_opts([callback|R], Opts) -> parse_opts(R, Opts#evh{cb=self()}); parse_opts([{userData, UserData}|R],Opts) -> diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl index 6679fcfbe1..cc253b1143 100644 --- a/lib/wx/src/wxe_server.erl +++ b/lib/wx/src/wxe_server.erl @@ -240,6 +240,8 @@ handle_connect(Object, EvData=#evh{handler=Handler}, invoke_cb({{Ev=#wx{}, Ref=#wx_ref{}}, FunId,_}, _S) -> %% Event callbacks case get(FunId) of + {{nospawn, Fun}, _} when is_function(Fun) -> + invoke_callback_fun(fun() -> Fun(Ev, Ref), <<>> end); {Fun,_} when is_function(Fun) -> invoke_callback(fun() -> Fun(Ev, Ref), <<>> end); {Pid,_} when is_pid(Pid) -> %% wx_object sync event @@ -258,21 +260,10 @@ invoke_cb({FunId, Args, _}, _S) when is_list(Args), is_integer(FunId) -> invoke_callback(Fun) -> Env = get(?WXE_IDENTIFIER), - CB = fun() -> - wx:set_env(Env), - wxe_util:cast(?WXE_CB_START, <<>>), - Res = try - Return = Fun(), - true = is_binary(Return), - Return - catch _:Reason -> - ?log("Callback fun crashed with {'EXIT, ~p, ~p}~n", - [Reason, erlang:get_stacktrace()]), - <<>> - end, - wxe_util:cast(?WXE_CB_RETURN, Res) - end, - spawn(CB), + spawn(fun() -> + wx:set_env(Env), + invoke_callback_fun(Fun) + end), ok. invoke_callback(Pid, Ev, Ref) -> @@ -302,6 +293,20 @@ invoke_callback(Pid, Ev, Ref) -> spawn(CB), ok. +invoke_callback_fun(Fun) -> + wxe_util:cast(?WXE_CB_START, <<>>), + Res = try + Return = Fun(), + true = is_binary(Return), + Return + catch _:Reason -> + ?log("Callback fun crashed with {'EXIT, ~p, ~p}~n", + [Reason, erlang:get_stacktrace()]), + <<>> + end, + wxe_util:cast(?WXE_CB_RETURN, Res). + + get_wx_object_state(Pid) -> case process_info(Pid, dictionary) of {dictionary, Dict} -> diff --git a/lib/wx/test/wx_event_SUITE.erl b/lib/wx/test/wx_event_SUITE.erl index 2d6f7b6aaa..7e71d6ca69 100644 --- a/lib/wx/test/wx_event_SUITE.erl +++ b/lib/wx/test/wx_event_SUITE.erl @@ -78,7 +78,6 @@ connect(Config) -> Tester ! {got_size, UserD} end, - ?m(ok, wxFrame:connect(Frame, size)), ?m(ok, wxEvtHandler:connect(Panel, size,[{skip, true},{userData, panel}])), ?m(ok, wxEvtHandler:connect(Panel, size,[{callback,CB},{userData, panel}])), @@ -91,12 +90,16 @@ connect(Config) -> ?m(ok, wxWindow:connect(Window, size,[{callback,CB},{userData, window}])), ?m(ok, wxWindow:connect(Window, size,[{skip,true},{userData, window}])), + %% For trivial side effect free callbacks, can deadlock easily otherwise + CB1 = fun(_,_) -> Tester ! {got_size, nospawn_cb} end, + ?m(ok, wxWindow:connect(Frame, size, [{callback,{nospawn, CB1}}])), + ?m(ok, wxFrame:connect(Frame, size, [{skip, true}])), ?m(true, wxFrame:show(Frame)), wxWindow:setSize(Panel, {200,100}), wxWindow:setSize(Window, {200,100}), - get_size_messages(Frame, [frame, panel_cb, window_cb, window]), + get_size_messages(Frame, [frame, panel_cb, window_cb, window, nospawn_cb]), wx_test_lib:wx_destroy(Frame, Config). @@ -115,7 +118,9 @@ get_size_messages(Frame, Msgs) -> ?m(false, lists:member(window, Msgs)), get_size_messages(Frame, lists:delete(window_cb, Msgs)); {got_size,panel} -> - get_size_messages(Frame, lists:delete(panel_cb, Msgs)); + get_size_messages(Frame, lists:delete(panel_cb, Msgs)); + {got_size,nospawn_cb} -> + get_size_messages(Frame, lists:delete(nospawn_cb, Msgs)); Other -> ?error("Got unexpected msg ~p ~p~n", [Other,Msgs]) after 1000 -> |