diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/glibmm_mainloop/main.cc | 124 |
3 files changed, 134 insertions, 0 deletions
@@ -1,5 +1,13 @@ 2013-06-02 Kjell Ahlstedt <kjell.ahlstedt@bredband.net> + tests: Add the glibmm_mainloop test. + + * tests/glibmm_mainloop/main.cc: New file. Tests MainContext and MainLoop, + including MainContext::invoke(). + * tests/Makefile.am: Add glibmm_mainloop/test. Bug #668184. + +2013-06-02 Kjell Ahlstedt <kjell.ahlstedt@bredband.net> + Glib::MainContext: Add invoke(). * glib/glibmm/main.[h|cc]: Add Glib::MainContext::invoke(). Bug #668184. diff --git a/tests/Makefile.am b/tests/Makefile.am index 7e39e654..36eb067c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -28,6 +28,7 @@ check_PROGRAMS = \ glibmm_date/test \ glibmm_buildfilename/test \ glibmm_interface_implementation/test \ + glibmm_mainloop/test \ glibmm_nodetree/test \ glibmm_ustring_compose/test \ glibmm_ustring_format/test \ @@ -80,6 +81,7 @@ glibmm_date_test_SOURCES = glibmm_date/main.cc glibmm_interface_implementation_test_SOURCES = glibmm_interface_implementation/main.cc glibmm_interface_implementation_test_LDADD = $(giomm_ldadd) +glibmm_mainloop_test_SOURCES = glibmm_mainloop/main.cc glibmm_nodetree_test_SOURCES = glibmm_nodetree/main.cc glibmm_ustring_compose_test_SOURCES = glibmm_ustring_compose/main.cc glibmm_ustring_format_test_SOURCES = glibmm_ustring_format/main.cc diff --git a/tests/glibmm_mainloop/main.cc b/tests/glibmm_mainloop/main.cc new file mode 100644 index 00000000..39c294eb --- /dev/null +++ b/tests/glibmm_mainloop/main.cc @@ -0,0 +1,124 @@ +/* Copyright (C) 2013 The glibmm Development Team + * + * This file is part of glibmm. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <glibmm.h> +#include <iostream> +#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE + +namespace +{ +enum InvokeStatus +{ + NOT_INVOKED, + INVOKED_IN_RIGHT_THREAD, + INVOKED_IN_WRONG_THREAD +}; + +InvokeStatus invoked_in_thread[2] = { NOT_INVOKED, NOT_INVOKED }; + +void quit_loop(const Glib::RefPtr<Glib::MainLoop>& mainloop) +{ + mainloop->quit(); +} + +bool mark_and_quit(const Glib::Threads::Thread* expected_thread, + int thread_nr, const Glib::RefPtr<Glib::MainLoop>& mainloop) +{ + invoked_in_thread[thread_nr] = + (Glib::Threads::Thread::self() == expected_thread) ? + INVOKED_IN_RIGHT_THREAD : INVOKED_IN_WRONG_THREAD; + quit_loop(mainloop); + return false; +} + +void thread_function(const Glib::Threads::Thread* first_thread, + const Glib::RefPtr<Glib::MainLoop>& first_mainloop) +{ + // Create a new MainContext. + Glib::RefPtr<Glib::MainContext> context = Glib::MainContext::create(); + // Create a new MainLoop. + Glib::RefPtr<Glib::MainLoop> second_mainloop = Glib::MainLoop::create(context); + + // Show how Glib::MainContext::invoke() can be used for calling a function, + // possibly executed in another thread. + Glib::MainContext::get_default()->invoke(sigc::bind(sigc::ptr_fun(mark_and_quit), + first_thread, 0, first_mainloop)); + context->invoke(sigc::bind(sigc::ptr_fun(mark_and_quit), + Glib::Threads::Thread::self(), 1, second_mainloop)); + + // Connect a one-shot timer that quits the main loop after a while, + // if mark_and_quit() is not called as expected. + context->signal_timeout().connect_seconds_once( + sigc::bind(sigc::ptr_fun(quit_loop), second_mainloop), 3); + + // Start the second main loop. + second_mainloop->run(); +} + +} // anonymous namespace + +int main(int, char**) +{ + Glib::init(); + + Glib::RefPtr<Glib::MainLoop> first_mainloop = Glib::MainLoop::create(); + + // Connect a one-shot timer that quits the main loop after a while, + // if mark_and_quit() is not called as expected. + Glib::signal_timeout().connect_seconds_once( + sigc::bind(sigc::ptr_fun(quit_loop), first_mainloop), 3); + + // Create a second thread. + Glib::Threads::Thread* second_thread = Glib::Threads::Thread::create( + sigc::bind(sigc::ptr_fun(thread_function), + Glib::Threads::Thread::self(), first_mainloop)); + + // Start the first main loop. + first_mainloop->run(); + + // Wait until the second thread has finished. + second_thread->join(); + + if (invoked_in_thread[0] == INVOKED_IN_RIGHT_THREAD && + invoked_in_thread[1] == INVOKED_IN_RIGHT_THREAD) + return EXIT_SUCCESS; + + const char* N[2] = { "first", "second" }; + for (int i = 0; i < 2; ++i) + { + switch (invoked_in_thread[i]) + { + case INVOKED_IN_RIGHT_THREAD: + break; + case NOT_INVOKED: + std::cout << "Function that should be invoked in " << N[i] + << " thread was not called." << std::endl; + break; + case INVOKED_IN_WRONG_THREAD: + std::cout << "Function that should be invoked in " << N[i] + << " thread was called in another thread." << std::endl; + break; + default: + std::cout << "Unknown value: invoked_in_thread[" << i << "]=" + << invoked_in_thread[i] << std::endl; + break; + } + } + + return EXIT_FAILURE; +} |