wow. that was easy: git mv core nucleus
[feisty_meow.git] / core / library / tests_basis / test_mutex.cpp
diff --git a/core/library/tests_basis/test_mutex.cpp b/core/library/tests_basis/test_mutex.cpp
deleted file mode 100644 (file)
index 743e000..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-/*****************************************************************************\
-*                                                                             *
-*  Name   : test_mutex                                                        *
-*  Author : Chris Koeritz                                                     *
-*                                                                             *
-*******************************************************************************
-* Copyright (c) 1994-$now By Author.  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 is online at:      *
-*     http://www.fsf.org/copyleft/gpl.html                                    *
-* Please send any updates to: fred@gruntose.com                               *
-\*****************************************************************************/
-
-#include <application/hoople_main.h>
-#include <basis/astring.h>
-#include <basis/guards.h>
-#include <basis/mutex.h>
-#include <configuration/application_configuration.h>
-#include <loggers/critical_events.h>
-#include <loggers/program_wide_logger.h>
-#include <mathematics/chaos.h>
-#include <processes/ethread.h>
-#include <processes/safe_roller.h>
-#include <structures/amorph.h>
-#include <structures/static_memory_gremlin.h>
-#include <timely/time_control.h>
-#include <timely/time_stamp.h>
-#include <unit_test/unit_base.h>
-
-#ifdef __WIN32__
-  #include <process.h>
-#endif
-
-using namespace application;
-using namespace basis;
-using namespace loggers;
-using namespace mathematics;
-using namespace timely;
-using namespace processes;
-using namespace structures;
-using namespace unit_test;
-
-//#define DEBUG_MUTEX
-  // uncomment for a verbose test run.
-
-const int MAX_MUTEX_TIMING_TEST = 2000000;
-  // the number of times we'll lock and unlock a mutex.
-
-const int DEFAULT_FISH = 32;
-  // the number of threads, by default.
-
-const int DEFAULT_RUN_TIME = 2 * SECOND_ms;
-  // the length of time to run the program.
-
-const int THREAD_PAUSE_LOWEST = 0;
-const int THREAD_PAUSE_HIGHEST = 48;
-  // this is the range of random sleeps that a thread will take after
-  // performing it's actions.
-
-const int MIN_SAME_THREAD_LOCKING_TESTS = 100;
-const int MAX_SAME_THREAD_LOCKING_TESTS = 1000;
-  // the range of times we'll test recursively locking the mutex.
-
-int concurrent_biters = 0;
-  // the number of threads that are currently active.
-
-int grab_lock = 0;
-  // this is upped whenever a fish obtains access to the mutex.
-
-mutex &guard() { static mutex _muttini; return _muttini; }
-  // the guard ensures that the grab lock isn't molested by two fish at
-  // once... hopefully.
-
-astring protected_string;
-  // this string is protected only by the mutex of guard().
-
-#define LOG(to_print) CLASS_EMERGENCY_LOG(program_wide_logger::get(), to_print)
-  // our macro for logging with a timestamp.
-
-// expects guardian mutex to already be locked once when coming in.
-void test_recursive_locking(chaos &_rando)
-{
-  int test_attempts = _rando.inclusive(MIN_SAME_THREAD_LOCKING_TESTS,
-      MAX_SAME_THREAD_LOCKING_TESTS);
-  int locked = 0;
-  for (int i = 0; i < test_attempts; i++) {
-    bool lock = !!(_rando.inclusive(0, 1));
-    if (lock) {
-      guard().lock();
-      locked++;  // one more lock.
-    } else {
-      if (locked > 0) {
-        // must be sure we are not already locally unlocked completely.
-        guard().unlock();
-        locked--;
-      }
-    }
-  }
-  for (int j = 0; j < locked; j++) {
-    // drop any locks we had left during the test.
-    guard().unlock();
-  }
-}
-
-//hmmm: how are these threads different so far?  they seem to do exactly
-//      the same thing.  maybe one should eat chars from the string.
-
-#undef UNIT_BASE_THIS_OBJECT
-#define UNIT_BASE_THIS_OBJECT c_testing
-
-class piranha : public ethread
-{
-public:
-  chaos _rando;  // our randomizer.
-  unit_base &c_testing;  // provides for test recording.
-
-  piranha(unit_base &testing) : ethread(0), c_testing(testing) {
-    FUNCDEF("constructor");
-    safe_add(concurrent_biters, 1);
-    ASSERT_TRUE(concurrent_biters >= 1, "the piranha is very noticeable");
-//LOG(astring(astring::SPRINTF, "there are %d biters.", concurrent_biters));
-  }
-
-  virtual ~piranha() {
-    FUNCDEF("destructor");
-    safe_add(concurrent_biters, -1); 
-//LOG("reached piranha destructor.");
-  }
-
-  DEFINE_CLASS_NAME("piranha");
-
-  void perform_activity(void *formal(data)) {
-    FUNCDEF("perform_activity");
-    {
-      // we grab the lock.
-      auto_synchronizer locked(guard());
-        // in this case, we make use of auto-synchronizer, handily testing it as well.
-      ASSERT_TRUE(&locked != NIL, "auto_synchronizer should grab the mutex object's lock");
-        // this is not a real test, but indicates that we did actually increase the number of
-        // unit tests by one, since we're using auto_synchronizer now.
-      safe_add(grab_lock, 1);
-      ASSERT_TRUE(grab_lock <= 1, "grab lock should not already be active");
-      protected_string += char(_rando.inclusive('a', 'z'));
-
-      test_recursive_locking(_rando);
-
-      safe_add(grab_lock, -1);
-    }
-    // dropped the lock.  snooze a bit.
-    if (!should_stop())
-      time_control::sleep_ms(_rando.inclusive(THREAD_PAUSE_LOWEST, THREAD_PAUSE_HIGHEST));
-  }
-
-};
-
-class barracuda : public ethread
-{
-public:
-  chaos _rando;  // our randomizer.
-  unit_base &c_testing;  // provides for test recording.
-
-  barracuda(unit_base &testing) : ethread(0), c_testing(testing) {
-    FUNCDEF("constructor");
-    safe_add(concurrent_biters, 1);
-    ASSERT_TRUE(concurrent_biters >= 1, "our presence should have been noticed");
-//LOG(astring(astring::SPRINTF, "there are %d biters.", concurrent_biters));
-  }
-
-  virtual ~barracuda() {
-    FUNCDEF("destructor");
-    safe_add(concurrent_biters, -1);
-//LOG("reached barracuda destructor.");
-  }
-
-  DEFINE_CLASS_NAME("barracuda");
-
-  void perform_activity(void *formal(data)) {
-    FUNCDEF("perform_activity");
-    // we grab the lock.
-    guard().lock();
-    safe_add(grab_lock, 1);
-    ASSERT_TRUE(grab_lock <= 1, "grab lock should not already be active");
-
-    test_recursive_locking(_rando);
-
-    protected_string += char(_rando.inclusive('a', 'z'));
-    safe_add(grab_lock, -1);
-    guard().unlock();
-    // done with the lock.  sleep for a while.
-    if (!should_stop())
-      time_control::sleep_ms(_rando.inclusive(THREAD_PAUSE_LOWEST, THREAD_PAUSE_HIGHEST));
-  }
-};
-
-//////////////
-
-#undef UNIT_BASE_THIS_OBJECT
-#define UNIT_BASE_THIS_OBJECT (*this)
-
-class test_mutex : virtual public unit_base, virtual public application_shell
-{
-public:
-  chaos _rando;  // our randomizer.
-
-  test_mutex() : application_shell() {}
-
-  DEFINE_CLASS_NAME("test_mutex");
-
-  int execute();
-};
-
-int test_mutex::execute()
-{
-  FUNCDEF("execute");
-
-  {
-    // we check how long a lock and unlock of a non-locked mutex will take.
-    // this is important to know so that we aren't spending much of our time
-    // locking mutexes just due to the mechanism.
-    mutex ted;
-    time_stamp mutt_in;
-    for (int qb = 0; qb < MAX_MUTEX_TIMING_TEST; qb++) {
-      ted.lock();
-      ted.unlock();
-    }
-    time_stamp mutt_out;
-    double run_count = MAX_MUTEX_TIMING_TEST;
-    double full_run_time = (mutt_out.value() - mutt_in.value()) / SECOND_ms;
-    double time_per_lock = (mutt_out.value() - mutt_in.value()) / run_count;
-    log(a_sprintf("%.0f mutex lock & unlock pairs took %.3f seconds,",
-        run_count, full_run_time));
-    log(a_sprintf("or %f ms per (lock+unlock).", time_per_lock));
-    ASSERT_TRUE(time_per_lock < 1.0, "mutex lock timing should be super fast");
-  }
-
-  // make sure the guard is initialized before the threads run.
-  guard().lock();
-  guard().unlock();
-
-  amorph<ethread> thread_list;
-
-  for (int i = 0; i < DEFAULT_FISH; i++) {
-    ethread *t = NIL;
-    if (i % 2) t = new piranha(*this);
-    else t = new barracuda(*this);
-    thread_list.append(t);
-    ethread *q = thread_list[thread_list.elements() - 1];
-    ASSERT_EQUAL(q, t, "amorph pointer equivalence is required");
-    // start the thread we added.
-    thread_list[thread_list.elements() - 1]->start(NIL);
-  }
-
-  time_stamp when_to_leave(DEFAULT_RUN_TIME);
-  while (when_to_leave > time_stamp()) {
-    time_control::sleep_ms(100);
-  }
-
-//hmmm: try just resetting the amorph;
-//      that should work fine.
-
-#ifdef DEBUG_MUTEX
-  LOG("now cancelling all threads....");
-#endif
-
-  for (int j = 0; j < thread_list.elements(); j++) thread_list[j]->cancel();
-
-#ifdef DEBUG_MUTEX
-  LOG("now stopping all threads....");
-#endif
-
-  for (int k = 0; k < thread_list.elements(); k++) thread_list[k]->stop();
-
-  int threads_active = 0;
-  for (int k = 0; k < thread_list.elements(); k++) {
-    if (thread_list[k]->thread_active()) threads_active++;
-  }
-  ASSERT_EQUAL(threads_active, 0, "threads should actually have stopped by now");
-
-#ifdef DEBUG_MUTEX
-  LOG("resetting thread list....");
-#endif
-
-  thread_list.reset();  // should whack all threads.
-
-  ASSERT_EQUAL(concurrent_biters, 0, "threads should all be gone by now");
-
-#ifdef DEBUG_MUTEX
-  LOG("done exiting from all threads....");
-
-  LOG(astring(astring::SPRINTF, "the accumulated string had %d characters "
-      "which means\nthere were %d thread activations from %d threads.",
-      protected_string.length(), protected_string.length(),
-      DEFAULT_FISH));
-#endif
-
-  return final_report();
-}
-
-HOOPLE_MAIN(test_mutex, )
-