Mercurial > godwindows
changeset 90:b90ce8ec9c44
Fixed a bug in go_event_close() and added thread/event pages to the test programs, ported from the C version.
author | Brian Smith <brian@dbsoft.org> |
---|---|
date | Thu, 26 Sep 2013 03:55:04 -0500 |
parents | 90e3c9c7ac73 |
children | d982501fe83d |
files | src/dw/dwglue.c src/dwootest/dwootest.go src/dwtest/dwtest.go |
diffstat | 3 files changed, 302 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dw/dwglue.c Thu Sep 26 01:50:58 2013 -0500 +++ b/src/dw/dwglue.c Thu Sep 26 03:55:04 2013 -0500 @@ -1133,22 +1133,23 @@ static int go_event_close(void *event) { - return dw_event_close((HMTX)event); + HEV thisevent = (HEV)event; + return dw_event_close(&thisevent); } static int go_event_post(void *event) { - return dw_event_post((HMTX)event); + return dw_event_post((HEV)event); } static int go_event_reset(void *event) { - return dw_event_reset((HMTX)event); + return dw_event_reset((HEV)event); } static int go_event_wait(void *event, unsigned long timeout) { - return dw_event_wait((HMTX)event, timeout); + return dw_event_wait((HEV)event, timeout); } extern int go_int_callback_basic(void *pfunc, void* window, void *data, unsigned int flags);
--- a/src/dwootest/dwootest.go Thu Sep 26 01:50:58 2013 -0500 +++ b/src/dwootest/dwootest.go Thu Sep 26 03:55:04 2013 -0500 @@ -46,6 +46,15 @@ // Page 8 var MAX_WIDGETS = 20 +// Page 9 +var threadmle dw.HMLE +var startbutton dw.HBUTTON +var mutex dw.HMTX; +var workevent, controlevent dw.HEV +var finished = 0 +var ready = 0 +var mlepos = 0 + // Miscellaneous var fileicon, foldericon dw.HICN var current_file string @@ -1082,6 +1091,138 @@ } } +// Page 9 +func update_mle(text string, lock int) { + /* Protect pos from being changed by different threads */ + if(lock != 0) { + mutex.Lock(); + } + mlepos = threadmle.Import(text, mlepos); + threadmle.SetCursor(mlepos); + if(lock != 0) { + mutex.Unlock(); + } +} + +func thread_add(notebookbox9 dw.HBOX) { + /* create a box to pack into the notebook page */ + tmpbox := dw.BoxNew(dw.VERT, 0); + notebookbox9.PackStart(tmpbox, 0, 0, dw.TRUE, dw.TRUE, 1); + + startbutton := dw.ButtonNew("Start Threads", 0); + tmpbox.PackStart(startbutton, -1, 30, dw.FALSE, dw.FALSE, 0); + /* Create the base threading components */ + threadmle = dw.MLENew(0); + tmpbox.PackStart(threadmle, 1, 1, dw.TRUE, dw.TRUE, 0); + mutex = dw.MutexNew(); + workevent = dw.EventNew(); + /* Connect signal handlers */ + startbutton.ConnectClicked(func(window dw.HBUTTON) int { + startbutton.Disable(); + mutex.Lock(); + controlevent = dw.EventNew(); + workevent.Reset(); + finished = dw.FALSE; + ready = 0; + update_mle("Starting thread 1\r\n", dw.FALSE); + go run_thread(1); + update_mle("Starting thread 2\r\n", dw.FALSE); + go run_thread(2); + update_mle("Starting thread 3\r\n", dw.FALSE); + go run_thread(3); + update_mle("Starting thread 4\r\n", dw.FALSE); + go run_thread(4); + update_mle("Starting control thread\r\n", dw.FALSE); + go control_thread(); + mutex.Unlock(); + return dw.FALSE; + }); + +} + +func run_thread(threadnum int) { + dw.InitThread(); + update_mle(fmt.Sprintf("Thread %d started.\r\n", threadnum), dw.TRUE); + + /* Increment the ready count while protected by mutex */ + mutex.Lock(); + ready++; + /* If all 4 threads have incrememted the ready count... + * Post the control event semaphore so things will get started. + */ + if(ready == 4) { + controlevent.Post(); + } + mutex.Unlock(); + + for finished == 0 { + result := workevent.Wait(2000); + + if(result == dw.ERROR_TIMEOUT) { + update_mle(fmt.Sprintf("Thread %d timeout waiting for event.\r\n", threadnum), dw.TRUE); + } else if(result == dw.ERROR_NONE) { + update_mle(fmt.Sprintf("Thread %d doing some work.\r\n", threadnum), dw.TRUE); + /* Pretend to do some work */ + dw.MainSleep(1000 * threadnum); + + /* Increment the ready count while protected by mutex */ + mutex.Lock(); + ready++; + buf := fmt.Sprintf("Thread %d work done. ready=%d", threadnum, ready); + /* If all 4 threads have incrememted the ready count... + * Post the control event semaphore so things will get started. + */ + if(ready == 4) { + controlevent.Post(); + buf = fmt.Sprintf("%s%s", buf, " Control posted."); + } + mutex.Unlock(); + update_mle(fmt.Sprintf("%s\r\n", buf), dw.TRUE); + } else { + update_mle(fmt.Sprintf("Thread %d error %d.\r\n", threadnum), dw.TRUE); + dw.MainSleep(10000); + } + } + update_mle(fmt.Sprintf("Thread %d finished.\r\n", threadnum), dw.TRUE); + dw.DeinitThread(); +} + +func control_thread() { + dw.InitThread(); + + inprogress := 5; + + for inprogress != 0 { + result := controlevent.Wait(2000); + + if(result == dw.ERROR_TIMEOUT) { + update_mle("Control thread timeout waiting for event.\r\n", dw.TRUE); + } else if(result == dw.ERROR_NONE) { + /* Reset the control event */ + controlevent.Reset(); + ready = 0; + update_mle(fmt.Sprintf("Control thread starting worker threads. Inprogress=%d\r\n", inprogress), dw.TRUE); + /* Start the work threads */ + workevent.Post(); + dw.MainSleep(100); + /* Reset the work event */ + workevent.Reset(); + inprogress--; + } else { + update_mle(fmt.Sprintf("Control thread error %d.\r\n", result), dw.TRUE); + dw.MainSleep(10000); + } + } + /* Tell the other threads we are done */ + finished = dw.TRUE; + workevent.Post(); + /* Close the control event */ + controlevent.Close(); + update_mle("Control thread finished.\r\n", dw.TRUE); + startbutton.Enable(); + dw.DeinitThread(); +} + func main() { /* Pick an approriate font for our platform */ if runtime.GOOS == "windows" { @@ -1183,6 +1324,12 @@ notebookpage8.SetText("scrollbox"); scrollbox_add(notebookbox8); + notebookbox9 := dw.BoxNew(dw.VERT, 8); + notebookpage9 := notebook.PageNew(1, dw.FALSE); + notebookpage9.Pack(notebookbox9); + notebookpage9.SetText("thread/event"); + thread_add(notebookbox9); + mainwindow.ConnectDelete(func(window dw.HWND) int { return exit_handler(); }); /* * The following is a special case handler for the Mac and other platforms which contain
--- a/src/dwtest/dwtest.go Thu Sep 26 01:50:58 2013 -0500 +++ b/src/dwtest/dwtest.go Thu Sep 26 03:55:04 2013 -0500 @@ -81,6 +81,15 @@ var iteration = 0; +// Page 9 +var notebookbox9 dw.HBOX +var threadmle dw.HMLE +var startbutton dw.HBUTTON +var mutex dw.HMTX; +var workevent, controlevent dw.HEV +var finished = 0 +var ready = 0 +var mlepos = 0 // Miscellaneous var fileicon, foldericon dw.HICN @@ -790,6 +799,111 @@ return FALSE; } +// Page 9 Callbacks +func run_thread(threadnum int) { + dw.InitThread(); + update_mle(fmt.Sprintf("Thread %d started.\r\n", threadnum), TRUE); + + /* Increment the ready count while protected by mutex */ + dw.Mutex_lock(mutex); + ready++; + /* If all 4 threads have incrememted the ready count... + * Post the control event semaphore so things will get started. + */ + if(ready == 4) { + dw.Event_post(controlevent); + } + dw.Mutex_unlock(mutex); + + for finished == 0 { + result := dw.Event_wait(workevent, 2000); + + if(result == dw.ERROR_TIMEOUT) { + update_mle(fmt.Sprintf("Thread %d timeout waiting for event.\r\n", threadnum), dw.TRUE); + } else if(result == dw.ERROR_NONE) { + update_mle(fmt.Sprintf("Thread %d doing some work.\r\n", threadnum), dw.TRUE); + /* Pretend to do some work */ + dw.Main_sleep(1000 * threadnum); + + /* Increment the ready count while protected by mutex */ + dw.Mutex_lock(mutex); + ready++; + buf := fmt.Sprintf("Thread %d work done. ready=%d", threadnum, ready); + /* If all 4 threads have incrememted the ready count... + * Post the control event semaphore so things will get started. + */ + if(ready == 4) { + dw.Event_post(controlevent); + buf = fmt.Sprintf("%s%s", buf, " Control posted."); + } + dw.Mutex_unlock(mutex); + update_mle(fmt.Sprintf("%s\r\n", buf), dw.TRUE); + } else { + update_mle(fmt.Sprintf("Thread %d error %d.\r\n", threadnum), dw.TRUE); + dw.Main_sleep(10000); + } + } + update_mle(fmt.Sprintf("Thread %d finished.\r\n", threadnum), dw.TRUE); + dw.DeinitThread(); +} + +func control_thread() { + dw.InitThread(); + + inprogress := 5; + + for inprogress != 0 { + result := dw.Event_wait(controlevent, 2000); + + if(result == dw.ERROR_TIMEOUT) { + update_mle("Control thread timeout waiting for event.\r\n", dw.TRUE); + } else if(result == dw.ERROR_NONE) { + /* Reset the control event */ + dw.Event_reset(controlevent); + ready = 0; + update_mle(fmt.Sprintf("Control thread starting worker threads. Inprogress=%d\r\n", inprogress), dw.TRUE); + /* Start the work threads */ + dw.Event_post(workevent); + dw.Main_sleep(100); + /* Reset the work event */ + dw.Event_reset(workevent); + inprogress--; + } else { + update_mle(fmt.Sprintf("Control thread error %d.\r\n", result), dw.TRUE); + dw.Main_sleep(10000); + } + } + /* Tell the other threads we are done */ + finished = dw.TRUE; + dw.Event_post(workevent); + /* Close the control event */ + dw.Event_close(controlevent); + update_mle("Control thread finished.\r\n", dw.TRUE); + dw.Window_enable(startbutton); + dw.DeinitThread(); +} + +func start_threads_button_callback(window dw.HWND, data dw.POINTER) int { + dw.Window_disable(startbutton); + dw.Mutex_lock(mutex); + controlevent = dw.Event_new(); + dw.Event_reset(workevent); + finished = FALSE; + ready = 0; + update_mle("Starting thread 1\r\n", FALSE); + go run_thread(1); + update_mle("Starting thread 2\r\n", FALSE); + go run_thread(2); + update_mle("Starting thread 3\r\n", FALSE); + go run_thread(3); + update_mle("Starting thread 4\r\n", FALSE); + go run_thread(4); + update_mle("Starting control thread\r\n", FALSE); + go control_thread(); + dw.Mutex_unlock(mutex); + return FALSE; +} + var exit_callback_func = exit_callback; var copy_clicked_callback_func = copy_clicked_callback; var paste_clicked_callback_func = paste_clicked_callback; @@ -829,6 +943,7 @@ var slider_valuechanged_callback_func = slider_valuechanged_callback; var print_callback_func = print_callback; var draw_page_func = draw_page; +var start_threads_button_callback_func = start_threads_button_callback; var checkable_string = "checkable"; var noncheckable_string = "non-checkable"; @@ -1312,6 +1427,35 @@ } } +// Page 9 +func update_mle(text string, lock int) { + /* Protect pos from being changed by different threads */ + if(lock != 0) { + dw.Mutex_lock(mutex); + } + mlepos = dw.Mle_import(threadmle, text, mlepos); + dw.Mle_set_cursor(threadmle, mlepos); + if(lock != 0) { + dw.Mutex_unlock(mutex); + } +} + +func thread_add() { + /* create a box to pack into the notebook page */ + tmpbox := dw.Box_new(dw.VERT, 0); + dw.Box_pack_start(notebookbox9, tmpbox, 0, 0, dw.TRUE, dw.TRUE, 1); + + startbutton = dw.Button_new("Start Threads", 0); + dw.Box_pack_start(tmpbox, startbutton, -1, 30, dw.FALSE, dw.FALSE, 0); + dw.Signal_connect(startbutton, dw.SIGNAL_CLICKED, dw.SIGNAL_FUNC(&start_threads_button_callback_func), nil); + + /* Create the base threading components */ + threadmle = dw.Mle_new(0); + dw.Box_pack_start(tmpbox, threadmle, 1, 1, TRUE, TRUE, 0); + mutex = dw.Mutex_new(); + workevent = dw.Event_new(); +} + func main() { /* Pick an approriate font for our platform */ if runtime.GOOS == "windows" { @@ -1410,6 +1554,12 @@ dw.Notebook_page_set_text(notebook, notebookpage8, "scrollbox"); scrollbox_add(); + notebookbox9 = dw.Box_new(dw.VERT, 8); + notebookpage9 := dw.Notebook_page_new(notebook, 1, FALSE); + dw.Notebook_pack(notebook, notebookpage9, notebookbox9); + dw.Notebook_page_set_text(notebook, notebookpage9, "thread/event"); + thread_add(); + /* Set the default field */ dw.Window_default(mainwindow, copypastefield);