aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Gudmundsson <[email protected]>2015-07-07 10:38:38 +0200
committerDan Gudmundsson <[email protected]>2015-07-07 10:38:38 +0200
commitfcbc24440945a13b379b2b6135599c982bf8bdf0 (patch)
tree5c04db3494dfe5c196ab291da7bb2dcddadcf101
parent70cb9432dc03ac9435b2c8c5fe2e8fd0608015dc (diff)
downloadotp-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.erl2
-rw-r--r--lib/wx/src/gen/wxEvtHandler.erl2
-rw-r--r--lib/wx/src/wxe_server.erl35
-rw-r--r--lib/wx/test/wx_event_SUITE.erl11
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 ->