Modified PosixThreadFactory::PThread:
        Pay attention to detached flags.  If thread is create non-detached and has not been joined when all references are given up,
        (ie boost::share_ptr calls ~PThread) do the join in the destructor to prevent thread ids from being leaked.

Modified ThreadFactoryTests.reapNThreads:
        Loop M times for M threads where M x N is bigger than 32K to verify that thread ids aren't leaked

Modified TimerManager.cpp:
        Removed debug messages.

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@665129 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/concurrency/PosixThreadFactory.cpp b/lib/cpp/src/concurrency/PosixThreadFactory.cpp
index 5f86ea2..2e8ed47 100644
--- a/lib/cpp/src/concurrency/PosixThreadFactory.cpp
+++ b/lib/cpp/src/concurrency/PosixThreadFactory.cpp
@@ -46,35 +46,49 @@
   int priority_;
   int stackSize_;
   weak_ptr<PthreadThread> self_;
+  bool detached_;
 
  public:
 
-  PthreadThread(int policy, int priority, int stackSize, shared_ptr<Runnable> runnable) :
+  PthreadThread(int policy, int priority, int stackSize, bool detached, shared_ptr<Runnable> runnable) :
     pthread_(0),
     state_(uninitialized),
     policy_(policy),
     priority_(priority),
-    stackSize_(stackSize) {
+    stackSize_(stackSize),
+    detached_(detached) {
 
     this->Thread::runnable(runnable);
   }
 
-  ~PthreadThread() {}
+  ~PthreadThread() {
+    /* Nothing references this thread, if is is not detached, do a join
+       now, otherwise the thread-id and, possibly, other resources will 
+       be leaked. */
+    if(!detached_) {
+      try {
+        join();
+      } catch(...) {
+        // We're really hosed. 
+      }
+    }
+  }
 
   void start() {
     if (state_ != uninitialized) {
       return;
     }
 
-    state_ = starting;
-
     pthread_attr_t thread_attr;
     if (pthread_attr_init(&thread_attr) != 0) {
         throw SystemResourceException("pthread_attr_init failed");
     }
 
-    if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE) != 0) {
-      throw SystemResourceException("pthread_attr_setdetachstate failed");
+    if(pthread_attr_setdetachstate(&thread_attr, 
+                                   detached_ ? 
+                                   PTHREAD_CREATE_DETACHED : 
+                                   PTHREAD_CREATE_JOINABLE) != 0) {
+        throw SystemResourceException("pthread_attr_setdetachstate failed");
     }
 
     // Set thread stack size
@@ -99,20 +113,23 @@
     shared_ptr<PthreadThread>* selfRef = new shared_ptr<PthreadThread>();
     *selfRef = self_.lock();
 
+    state_ = starting;
+
     if (pthread_create(&pthread_, &thread_attr, threadMain, (void*)selfRef) != 0) {
       throw SystemResourceException("pthread_create failed");
     }
   }
 
   void join() {
-    if (state_ != stopped) {
+    if (!detached_ && state_ != uninitialized) {
       void* ignore;
       pthread_join(pthread_, &ignore);
+      detached_ = true;
     }
   }
 
   id_t id() {
-    return pthread_;
+    return static_cast<id_t>(pthread_);
   }
 
   shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
@@ -211,7 +228,7 @@
    * @param runnable A runnable object
    */
   shared_ptr<Thread> newThread(shared_ptr<Runnable> runnable) const {
-    shared_ptr<PthreadThread> result = shared_ptr<PthreadThread>(new PthreadThread(toPthreadPolicy(policy_), toPthreadPriority(policy_, priority_), stackSize_, runnable));
+    shared_ptr<PthreadThread> result = shared_ptr<PthreadThread>(new PthreadThread(toPthreadPolicy(policy_), toPthreadPriority(policy_, priority_), stackSize_, detached_, runnable));
     result->weakRef(result);
     runnable->thread(result);
     return result;
@@ -223,7 +240,7 @@
 
   PRIORITY priority() const { return priority_; }
 
-  Thread::id_t currentThreadId() const { return pthread_self(); }
+  Thread::id_t currentThreadId() const {return static_cast<id_t>(pthread_self());}
 
   /**
    * Sets priority.