summaryrefslogtreecommitdiff
path: root/tests/glibmm_mainloop
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjell.ahlstedt@bredband.net>2013-06-02 15:13:23 +0200
committerKjell Ahlstedt <kjell.ahlstedt@bredband.net>2013-06-02 15:13:23 +0200
commit592f582cd86b52b6b731e3a56d32291ad8fde6c7 (patch)
treec5b251b792101473944e536cefd2c8535f475dde /tests/glibmm_mainloop
parent47f1dedf040506b4aa7d131311866d8121bdbd8b (diff)
downloadglibmm-592f582cd86b52b6b731e3a56d32291ad8fde6c7.tar.gz
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.
Diffstat (limited to 'tests/glibmm_mainloop')
-rw-r--r--tests/glibmm_mainloop/main.cc124
1 files changed, 124 insertions, 0 deletions
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;
+}