diff --git a/tests/40components.tests b/tests/40components.tests index 4ff311a4d..c73e24eb1 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -220,6 +220,11 @@ return: 0 END +PLANNED "Multithread Locking by Monitor" MultithreadLocking_test < [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ] out: removed 0 ---> [ 1, 2, 3, 4, 5, 6, 7, 8, 9, ] diff --git a/tests/common/multithread-locking-test.cpp b/tests/common/multithread-locking-test.cpp new file mode 100644 index 000000000..d03fe5c28 --- /dev/null +++ b/tests/common/multithread-locking-test.cpp @@ -0,0 +1,211 @@ +/* + MultithreadLocking(Test) - check the monitor object based locking + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/test/run.hpp" +//#include "common/util.hpp" +#include "common/error.hpp" + +#include "common/multithread.hpp" + +#include + +//#include +//#include +#include + +//using boost::lexical_cast; +//using boost::format; +//using util::isnil; +//using std::string; +using std::cout; +using test::Test; + + +namespace lib { + namespace test { + + namespace { // private test classes and data... + + const uint NUM_COUNTERS = 20; ///< number of independent counters to increment in parallel + const uint NUM_THREADS = 10; ///< number of threads trying to increment these counters + const uint MAX_PAUSE = 10000; ///< maximum delay implemented as empty counting loop + const uint MAX_SUM = 1000; ///< trigger when to finish incrementing + const uint MAX_INC = 10; ///< maximum increment on each step + + + + class Victim + { + long cnt_[NUM_COUNTERS]; + uint step_; ///< @note stored as instance variable + + void + pause () + { + //Lock guard (*this); // note recursive lock + for ( uint i=0, lim=(rand() % MAX_PAUSE); ijoin(); + } + + void + start () + { + thread_ = Glib::Thread::create(sigc::mem_fun(*this, &HavocThread::doIt), true); + ASSERT (thread_); + } + }; + + } // (End) test classes and data.... + + + + + + + + + + + /********************************************************************** + * @test create multiple threads, all concurrently trying to increment + * a number of counters with random steps and random pauses. Without + * locking, the likely result will be differing counters. + * But because the class Victim uses an object level monitor to + * guard the mutations, the state should remain consistent. + * + * @see multithread.hpp + */ + class MultithreadLocking_test : public Test + { + + virtual void run(Arg arg) + { + if (!Glib::thread_supported()) + Glib::thread_init(); + + REQUIRE (ourVictim.checkAllEqual()); + { + HavocThread threads[NUM_THREADS]; + for (uint i=0; i=" << MAX_SUM << "\n"; + ourVictim.report(); + } + } + + }; + + + + /** Register this test class... */ + LAUNCHER (MultithreadLocking_test, "unit common"); + + + + } // namespace test + +} // namespace lumiera