Modified PosixThreadFactory
        Added explicit detached getter and setter
Modified PosixThreadFactory::~PThread:
        Check for join failing and don't transition to detached_ state if it does.  Potential thread-handle leak for
        threads created joinable who aren't referenced by any external thread.  Solution for now has to be
        "DONT DO THAT", the clever approach doesn't always work.

Added ThreadFactoryTests.floodNThreads:
        Loop M times for N threads where M x N is bigger than 32K to verify that detached threads can be created
        ad infinitum.

Reviewed By: mcslee

Revert Plan: revertible

Test Plan: concurrency_test thread-factory passes


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665130 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/concurrency/test/Tests.cpp b/lib/cpp/src/concurrency/test/Tests.cpp
index 5fe4651..a160472 100644
--- a/lib/cpp/src/concurrency/test/Tests.cpp
+++ b/lib/cpp/src/concurrency/test/Tests.cpp
@@ -33,11 +33,17 @@
     std::cout << "ThreadFactory tests..." << std::endl;
 
     size_t count =  1000;
+    size_t floodLoops =  1;
+    size_t floodCount =  100000;
 
     std::cout << "\t\tThreadFactory reap N threads test: N = " << count << std::endl;
 
     assert(threadFactoryTests.reapNThreads(count));
 
+    std::cout << "\t\tThreadFactory floodN threads test: N = " << floodCount << std::endl;
+
+    assert(threadFactoryTests.floodNTest(floodLoops, floodCount));
+
     std::cout << "\t\tThreadFactory synchronous start test" << std::endl;
 
     assert(threadFactoryTests.synchStartTest());
@@ -134,4 +140,3 @@
     }
   }
 }
-
diff --git a/lib/cpp/src/concurrency/test/ThreadFactoryTests.h b/lib/cpp/src/concurrency/test/ThreadFactoryTests.h
index 4cd6bd5..99bc94e 100644
--- a/lib/cpp/src/concurrency/test/ThreadFactoryTests.h
+++ b/lib/cpp/src/concurrency/test/ThreadFactoryTests.h
@@ -112,7 +112,7 @@
           throw e;
         }
       }
-      
+
       tix = 0;
       for (std::set<shared_ptr<Thread> >::const_iterator thread = threads.begin(); thread != threads.end(); tix++, ++thread) {
 
@@ -123,14 +123,14 @@
           throw e;
         }
       }
-      
+
       {
         Synchronized s(*monitor);
         while (*activeCount > 0) {
           monitor->wait(1000);
         }
       }
-      
+
       for (std::set<shared_ptr<Thread> >::const_iterator thread = threads.begin(); thread != threads.end(); thread++) {
         threads.erase(*thread);
       }
@@ -276,6 +276,67 @@
 
     return success;
   }
+
+
+  class FloodTask : public Runnable {
+  public:
+
+    FloodTask(const size_t id) :_id(id) {}
+    ~FloodTask(){
+      if(_id % 1000 == 0) {
+        std::cout << "\t\tthread " << _id << " done" << std::endl;
+      }
+    }
+
+    void run(){
+      if(_id % 1000 == 0) {
+        std::cout << "\t\tthread " << _id << " started" << std::endl;
+      }
+
+      usleep(1);
+    }
+    const size_t _id;
+  };
+
+  void foo(PosixThreadFactory *tf) {
+  }
+
+  bool floodNTest(size_t loop=1, size_t count=100000) {
+
+    bool success = false;
+
+    for(size_t lix = 0; lix < loop; lix++) {
+
+      PosixThreadFactory threadFactory = PosixThreadFactory();
+      threadFactory.setDetached(true);
+
+        for(size_t tix = 0; tix < count; tix++) {
+
+          try {
+
+            shared_ptr<FloodTask> task(new FloodTask(lix * count + tix ));
+
+            shared_ptr<Thread> thread = threadFactory.newThread(task);
+
+            thread->start();
+
+            usleep(1);
+
+          } catch (TException& e) {
+
+            std::cout << "\t\t\tfailed to start  " << lix * count + tix << " thread " << e.what() << std::endl;
+
+            return success;
+          }
+        }
+
+        std::cout << "\t\t\tflooded " << (lix + 1) * count << " threads" << std::endl;
+
+        success = true;
+    }
+
+    return success;
+  }
 };
 
 const double ThreadFactoryTests::ERROR = .20;
diff --git a/lib/cpp/src/concurrency/test/ThreadManagerTests.h b/lib/cpp/src/concurrency/test/ThreadManagerTests.h
index 5f518ca..a8fdcda 100644
--- a/lib/cpp/src/concurrency/test/ThreadManagerTests.h
+++ b/lib/cpp/src/concurrency/test/ThreadManagerTests.h
@@ -100,7 +100,7 @@
 
     shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
 
-    threadFactory->priority(PosixThreadFactory::HIGHEST);
+    threadFactory->setPriority(PosixThreadFactory::HIGHEST);
 
     threadManager->threadFactory(threadFactory);
 
@@ -239,7 +239,7 @@
 
       shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
 
-      threadFactory->priority(PosixThreadFactory::HIGHEST);
+      threadFactory->setPriority(PosixThreadFactory::HIGHEST);
 
       threadManager->threadFactory(threadFactory);