aboutsummaryrefslogtreecommitdiffstats
path: root/lib/wx/c_src/wxe_impl.cpp
diff options
context:
space:
mode:
authorDan Gudmundsson <[email protected]>2014-01-17 16:57:29 +0100
committerDan Gudmundsson <[email protected]>2014-01-22 16:33:01 +0100
commitfb767602c08159daa2190129622ebf185606fd35 (patch)
treead89eb12ac2f554a2151f3605c9122882b7eb386 /lib/wx/c_src/wxe_impl.cpp
parent6459bb3e5c82cdd5474bdd77d8aff3a12ce88910 (diff)
downloadotp-fb767602c08159daa2190129622ebf185606fd35.tar.gz
otp-fb767602c08159daa2190129622ebf185606fd35.tar.bz2
otp-fb767602c08159daa2190129622ebf185606fd35.zip
wx: Delay memory cleanup until safe
Previously we could do a cleanup while we where recursed down and thus delete the objects we where invoking.
Diffstat (limited to 'lib/wx/c_src/wxe_impl.cpp')
-rw-r--r--lib/wx/c_src/wxe_impl.cpp59
1 files changed, 44 insertions, 15 deletions
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index 5205e4a2c1..5c10881eda 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -123,6 +123,8 @@ bool WxeApp::OnInit()
wxe_batch = new wxList;
wxe_batch_cb_saved = new wxList;
cb_buff = NULL;
+ recurse_level = 0;
+ delayed_cleanup = new wxList;
wxe_ps_init2();
// wxIdleEvent::SetMode(wxIDLE_PROCESS_SPECIFIED); // Hmm printpreview doesn't work in 2.9 with this
@@ -186,23 +188,40 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process)
{
WxeApp * app = (WxeApp *) wxTheApp;
ErlDrvMonitor monitor;
+ // Is thread safe if pdl have been incremented
driver_monitor_process(port, process, &monitor);
// Should we be able to handle commands when recursing? probably
erl_drv_mutex_lock(wxe_batch_locker_m);
//fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr);
+ app->recurse_level++;
app->dispatch_cb(wxe_batch, wxe_batch_cb_saved, process);
+ app->recurse_level--;
//fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr);
wxe_batch_caller = 0;
erl_drv_mutex_unlock(wxe_batch_locker_m);
driver_demonitor_process(port, &monitor);
}
-void WxeApp::dispatch_cmds() {
+void WxeApp::dispatch_cmds()
+{
erl_drv_mutex_lock(wxe_batch_locker_m);
+ recurse_level++;
int level = dispatch(wxe_batch_cb_saved, 0, WXE_STORED);
dispatch(wxe_batch, level, WXE_NORMAL);
+ recurse_level--;
wxe_batch_caller = 0;
erl_drv_mutex_unlock(wxe_batch_locker_m);
+ // Cleanup old memenv's
+ if(recurse_level == 0 && delayed_cleanup->size() > 0) {
+ for( wxList::compatibility_iterator node = delayed_cleanup->GetFirst();
+ node;
+ node = delayed_cleanup->GetFirst()) {
+ wxeMetaCommand *event = (wxeMetaCommand *)node->GetData();
+ delayed_cleanup->Erase(node);
+ destroyMemEnv(*event);
+ delete event;
+ }
+ }
}
// Should have erl_drv_mutex_lock(wxe_batch_locker_m);
@@ -370,9 +389,11 @@ void WxeApp::newMemEnv(wxeMetaCommand& Ecmd) {
erl_drv_send_term(WXE_DRV_PORT,Ecmd.caller,rt,2);
}
-void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) {
+void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd)
+{
// Clear incoming cmd queue first
// dispatch_cmds();
+ int delay = false;
wxWindow *parent = NULL;
wxeMemEnv * memenv = refmap[Ecmd.port];
@@ -389,26 +410,34 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) {
ptrMap::iterator it = ptr2ref.find(ptr);
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
- if(refd->alloc_in_erl) {
- if(refd->type == 2) {
- wxDialog *win = (wxDialog *) ptr;
- if(win->IsModal()) {
- win->EndModal(-1);
- }
- parent = win->GetParent();
- if(parent) {
- ptrMap::iterator parentRef = ptr2ref.find(parent);
- if(parentRef == ptr2ref.end()) {
- // The parent is already dead delete the parent ref
- win->SetParent(NULL);
- }
+ if(refd->alloc_in_erl && refd->type == 2) {
+ wxDialog *win = (wxDialog *) ptr;
+ if(win->IsModal()) {
+ win->EndModal(-1);
+ }
+ parent = win->GetParent();
+ if(parent) {
+ ptrMap::iterator parentRef = ptr2ref.find(parent);
+ if(parentRef == ptr2ref.end()) {
+ // The parent is already dead delete the parent ref
+ win->SetParent(NULL);
}
+ }
+ if(recurse_level > 0) {
+ // Delay delete until we are out of dispatch*
+ delayed_cleanup->Append(Ecmd.Clone());
+ delay = true;
+ } else {
delete win;
}
}
}
}
}
+
+ if(delay)
+ return;
+
// First pass, delete all top parents/windows of all linked objects
// fprintf(stderr, "close port %x\r\n", Ecmd.port);fflush(stderr);