autoconf/automake/libtool-ized thrift cpp bits:
    Fixed to build on solaris.
    Used clock_gettime() where available
    Fixed rounding of time to ms

			       


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664733 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/concurrency/Util.h b/lib/cpp/src/concurrency/Util.h
index 8467a2c..6e8891d 100644
--- a/lib/cpp/src/concurrency/Util.h
+++ b/lib/cpp/src/concurrency/Util.h
@@ -1,6 +1,8 @@
 #if !defined(_concurrency_Util_h_)
 #define _concurrency_Util_h_ 1
 
+#include <config.h>
+
 #include <assert.h>
 #include <stddef.h>
 #include <sys/time.h>
@@ -18,6 +20,12 @@
 
 class Util {
 
+  static const long long NS_PER_S = 1000000000LL;
+
+  static const long long MS_PER_S = 1000LL;
+
+  static const long long NS_PER_MS = 1000000LL;
+
  public:
 
   /** Converts timespec to milliseconds
@@ -26,28 +34,39 @@
       @param time or duration in milliseconds */
 
   static void toTimespec(struct timespec& result, long long value) {
+
+    result.tv_sec = value / MS_PER_S; // ms to s
     
-    result.tv_sec = value / 1000; // ms to s
-    
-    result.tv_nsec = (value % 1000) * 1000000; // ms to ns
+    result.tv_nsec = (value % MS_PER_S) * NS_PER_MS; // ms to ns
   }
 
   /** Converts timespec to milliseconds */
 
   static const void toMilliseconds(long long& result, const struct timespec& value) {
 
-    result = value.tv_sec * 1000 + value.tv_nsec / 1000000;
+    result = (value.tv_sec * MS_PER_S) + (value.tv_nsec / NS_PER_MS) + (value.tv_nsec % NS_PER_MS >= 500000 ? 1 : 0) ;
   }
 
   /** Get current time as milliseconds from epoch */
 
   static const long long currentTime() {
 
+#if defined(HAVE_CLOCK_GETTIME)
+
+    struct timespec now;
+
+    assert(clock_gettime(&now, NULL) == 0);
+
+    return = (now.tv_sec * MS_PER_S) + (now.tv_nsec / NS_PER_MS) + (now.tv_nsec % NS_PER_MS >= 500000 ? 1 : 0) ;
+
+#elif defined(HAVE_GETTIMEOFDAY)
+
     struct timeval now;
 
     assert(gettimeofday(&now, NULL) == 0);
 
-    return ((long long)now.tv_sec) * 1000LL + now.tv_usec / 1000;
+    return (((long long)now.tv_sec) * MS_PER_S) + (now.tv_usec / MS_PER_S) + (now.tv_usec % MS_PER_S >= 500 ? 1 : 0);
+#endif // defined(HAVE_GETTIMEDAY)
   }
 };
 
diff --git a/lib/cpp/src/concurrency/test/Tests.cc b/lib/cpp/src/concurrency/test/Tests.cc
index 19e1f4a..5c4dd24 100644
--- a/lib/cpp/src/concurrency/test/Tests.cc
+++ b/lib/cpp/src/concurrency/test/Tests.cc
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <vector>
 #include <string>
 
 #include "ThreadFactoryTests.h"
@@ -9,27 +10,22 @@
 
   std::string arg;
 
-  if(argc < 2) {
+  std::vector<std::string>  args(argc - 1 > 1 ? argc - 1 : 1);
 
-    arg = "all";
+  args[0] = "all";
 
-  } else {
-    
-    arg = std::string(argv[1]);
+  for(int ix = 1; ix < argc; ix++) {
+    args[ix - 1] = std::string(argv[ix]);
   }
 
-  bool runAll = arg.compare("all") == 0;
+  bool runAll = args[0].compare("all") == 0;
 
-  if(runAll || arg.compare("thread-factory") == 0) {
+  if(runAll || args[0].compare("thread-factory") == 0) {
 
     ThreadFactoryTests threadFactoryTests;
     
     std::cout << "ThreadFactory tests..." << std::endl;
     
-    std::cout << "\tThreadFactory hello-world test" << std::endl;
-
-    assert(threadFactoryTests.helloWorldTest());
-
     size_t count =  1000;
 
     std::cout << "\t\tThreadFactory reap N threads test: N = " << count << std::endl;
@@ -39,9 +35,37 @@
     std::cout << "\t\tThreadFactory synchronous start test" << std::endl;
 
     assert(threadFactoryTests.synchStartTest());
+
+    std::cout << "\t\tThreadFactory monitor timeout test" << std::endl;
+
+    assert(threadFactoryTests.monitorTimeoutTest());
   }
 
-  if(runAll || arg.compare("timer-manager") == 0) {
+  if(runAll || args[0].compare("util") == 0) {
+
+    std::cout << "Util tests..." << std::endl;
+
+    std::cout << "\t\tUtil minimum time" << std::endl;
+
+    long long time00 = Util::currentTime();
+    long long time01 = Util::currentTime();
+
+    std::cout << "\t\t\tMinimum time: " << time01 - time00 << "ms" << std::endl;
+
+    time00 = Util::currentTime();
+    time01 = time00;
+    size_t count = 0;
+    
+    while(time01 < time00 + 10) {
+      count++;
+      time01 = Util::currentTime();
+    }
+
+    std::cout << "\t\t\tscall per ms: " << count / (time01 - time00) << std::endl;
+  }
+
+
+  if(runAll || args[0].compare("timer-manager") == 0) {
 
     std::cout << "TimerManager tests..." << std::endl;
 
@@ -52,21 +76,51 @@
     assert(timerManagerTests.test00());
   }
 
-  if(runAll || arg.compare("thread-manager") == 0) {
+  if(runAll || args[0].compare("thread-manager") == 0) {
 
     std::cout << "ThreadManager tests..." << std::endl;
 
-    size_t workerCount = 100;
+    {
 
-    size_t taskCount = 100000;
+      size_t workerCount = 100;
 
-    long long delay = 10LL;
+      size_t taskCount = 100000;
 
-    std::cout << "\t\tThreadManager load test: worker count: " << workerCount << " task count: " << taskCount << " delay: " << delay << std::endl;
+      long long delay = 10LL;
 
-    ThreadManagerTests threadManagerTests;
+      std::cout << "\t\tThreadManager load test: worker count: " << workerCount << " task count: " << taskCount << " delay: " << delay << std::endl;
 
-    assert(threadManagerTests.loadTest(taskCount, delay, workerCount));
+      ThreadManagerTests threadManagerTests;
+
+      assert(threadManagerTests.loadTest(taskCount, delay, workerCount));
+    }
+  }
+
+  if(runAll || args[0].compare("thread-manager-benchmark") == 0) {
+
+    std::cout << "ThreadManager benchmark tests..." << std::endl;
+
+    {
+
+      size_t minWorkerCount = 2;
+
+      size_t maxWorkerCount = 512;
+
+      size_t tasksPerWorker = 1000;
+
+      long long delay = 10LL;
+
+      for(size_t workerCount = minWorkerCount; workerCount < maxWorkerCount; workerCount*= 2) {
+
+	size_t taskCount = workerCount * tasksPerWorker;
+
+	std::cout << "\t\tThreadManager load test: worker count: " << workerCount << " task count: " << taskCount << " delay: " << delay << std::endl;
+
+	ThreadManagerTests threadManagerTests;
+
+	threadManagerTests.loadTest(taskCount, delay, workerCount);
+      }
+    }
   }
 }
 
diff --git a/lib/cpp/src/concurrency/test/ThreadFactoryTests.h b/lib/cpp/src/concurrency/test/ThreadFactoryTests.h
index 1e0b139..d1ec0df 100644
--- a/lib/cpp/src/concurrency/test/ThreadFactoryTests.h
+++ b/lib/cpp/src/concurrency/test/ThreadFactoryTests.h
@@ -1,6 +1,7 @@
 #include <Thread.h>
 #include <PosixThreadFactory.h>
 #include <Monitor.h>
+#include <Util.h>
 
 #include <assert.h>
 #include <iostream>
@@ -216,9 +217,42 @@
 
     assert(state == SynchStartTask::STOPPED);
 
+    bool success = true;
+
+    std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "!" << std::endl;
+
     return true;
   }
 
+  /** See how accurate monitor timeout is. */
+
+  bool monitorTimeoutTest(size_t count=1000, long long timeout=10) {
+
+    Monitor monitor;
+
+    long long startTime = Util::currentTime();
+
+    for(size_t ix = 0; ix < count; ix++) {
+      {Synchronized s(monitor);
+	monitor.wait(timeout);
+      }
+    }
+
+    long long endTime = Util::currentTime();
+
+    double error = ((endTime - startTime) - (count * timeout)) / (double)(count * timeout);
+
+    if(error < 0.0)  {
+
+      error *= 1.0;
+    }
+
+    bool success = error < .10;
+
+    std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "! expected time: " << count * timeout << "ms elapsed time: "<< endTime - startTime << "ms error%: " << error * 100.0 << std::endl;
+
+    return success;
+  }
 };
   
 
diff --git a/lib/cpp/src/concurrency/test/ThreadManagerTests.h b/lib/cpp/src/concurrency/test/ThreadManagerTests.h
index 6132571..8b2dda8 100644
--- a/lib/cpp/src/concurrency/test/ThreadManagerTests.h
+++ b/lib/cpp/src/concurrency/test/ThreadManagerTests.h
@@ -1,3 +1,4 @@
+#include <config.h>
 #include <ThreadManager.h>
 #include <PosixThreadFactory.h>
 #include <Monitor.h>
@@ -6,6 +7,8 @@
 #include <assert.h>
 #include <set>
 #include <iostream>
+#include <set>
+#include <stdint.h>
 
 namespace facebook { namespace thrift { namespace concurrency { namespace test {
 
@@ -32,29 +35,16 @@
 
     void run() {
 
-      Monitor sleep;
+      _startTime = Util::currentTime();
 
-      {Synchronized s(sleep);
+      {Synchronized s(_sleep);
 
-	long long time00 = Util::currentTime();
 
-	sleep.wait(_timeout);
-
-	long long time01 = Util::currentTime();
-
-	double error = ((time01 - time00) - _timeout) / (double)_timeout;
-	
-	if(error < 0.0) {
-	  
-	  error*= -1.0;
-	}
-
-	if(error > .20) {
-	  
-	  assert(false);
-	}
+	_sleep.wait(_timeout);
       }
 
+      _endTime = Util::currentTime();
+
       _done = true;
       
       {Synchronized s(_monitor);
@@ -73,7 +63,10 @@
     Monitor& _monitor;
     size_t& _count;
     long long _timeout;
+    long long _startTime;
+    long long _endTime;
     bool _done;
+    Monitor _sleep;
   };
 
   /** Dispatch count tasks, each of which blocks for timeout milliseconds then completes.
@@ -86,8 +79,12 @@
     size_t activeCount = count;
 
     ThreadManager* threadManager = ThreadManager::newSimpleThreadManager(workerCount);
+
+    PosixThreadFactory* threadFactory = new PosixThreadFactory();
+
+    threadFactory->priority(PosixThreadFactory::HIGHEST);
       
-    threadManager->threadFactory(new PosixThreadFactory());
+    threadManager->threadFactory(threadFactory);
 
     threadManager->start();
       
@@ -115,11 +112,45 @@
 
     long long time01 = Util::currentTime();
 
+    long long firstTime = 9223372036854775807LL;
+    long long lastTime = 0;
+
+    double averageTime = 0;
+    long long minTime = 9223372036854775807LL;
+    long long maxTime = 0;
+
     for(std::set<ThreadManagerTests::Task*>::iterator ix = tasks.begin(); ix != tasks.end(); ix++) {
+      
+      ThreadManagerTests::Task* task = *ix;
+
+      long long delta = task->_endTime - task->_startTime;
+
+      assert(delta > 0);
+
+      if(task->_startTime < firstTime) {
+	firstTime = task->_startTime;
+      }
+
+      if(task->_endTime > lastTime) {
+	lastTime = task->_endTime;
+      }
+
+      if(delta < minTime) {
+	minTime = delta;
+      }
+
+      if(delta > maxTime) {
+	maxTime = delta;
+      }
+
+      averageTime+= delta;
 
       delete *ix;
-      
     }
+    
+    averageTime /= count;
+
+    std::cout << "\t\t\tfirst start: " << firstTime << "ms Last end: " << lastTime << "ms min: " << minTime << "ms max: " << maxTime << "ms average: " << averageTime << "ms" << std::endl;
 
     double expectedTime = ((count + (workerCount - 1)) / workerCount) * timeout;
 
@@ -133,9 +164,11 @@
 
     delete threadManager;
 
+    delete threadFactory;
+
     std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "! expected time: " << expectedTime << "ms elapsed time: "<< time01 - time00 << "ms error%: " << error * 100.0 << std::endl;
 
-    return true;
+    return success;
   }
 };