activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tab...@apache.org
Subject svn commit: r1420260 - in /activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util: Timer.cpp Timer.h concurrent/ThreadPoolExecutor.cpp
Date Tue, 11 Dec 2012 16:30:08 GMT
Author: tabish
Date: Tue Dec 11 16:29:59 2012
New Revision: 1420260

URL: http://svn.apache.org/viewvc?rev=1420260&view=rev
Log:
Better Executor dtor code to prevent possible segfault.

Modified:
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Timer.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Timer.h
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/ThreadPoolExecutor.cpp

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Timer.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Timer.cpp?rev=1420260&r1=1420259&r2=1420260&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Timer.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Timer.cpp Tue Dec 11 16:29:59
2012
@@ -35,10 +35,10 @@ using namespace decaf::lang;
 using namespace decaf::lang::exceptions;
 
 ////////////////////////////////////////////////////////////////////////////////
-namespace decaf{
-namespace util{
+namespace decaf {
+namespace util {
 
-    class TimerImpl : public decaf::lang::Thread, public SynchronizableImpl {
+    class TimerImpl: public decaf::lang::Thread, public SynchronizableImpl {
     public:
 
         TimerTaskHeap heap;
@@ -46,12 +46,12 @@ namespace util{
 
     public:
 
-        TimerImpl() : Thread(), heap(), cancelled( false ) {}
+        TimerImpl() : Thread(), heap(), cancelled(false) {}
 
-        TimerImpl(const std::string& name) : Thread(name), heap(), cancelled( false )
{}
+        TimerImpl(const std::string& name) : Thread(name), heap(), cancelled(false) {}
 
         virtual ~TimerImpl() {
-            try{
+            try {
                 this->cancel();
                 this->join();
             }
@@ -67,7 +67,6 @@ namespace util{
             while (true) {
 
                 Pointer<TimerTask> task;
-
                 synchronized(this) {
 
                     if (cancelled) {
@@ -75,11 +74,10 @@ namespace util{
                     }
 
                     if (heap.isEmpty()) {
-
                         // no tasks scheduled -- sleep until any task appear
                         try {
                             this->wait();
-                        } catch( InterruptedException& e ) {}
+                        } catch (InterruptedException& e) {}
                         continue;
                     }
 
@@ -90,7 +88,7 @@ namespace util{
 
                     synchronized(&(task->lock)) {
                         if (task->cancelled) {
-                            heap.remove( 0 );
+                            heap.remove(0);
                             continue;
                         }
 
@@ -99,10 +97,9 @@ namespace util{
                     }
 
                     if (timeToSleep > 0) {
-
                         task.reset(NULL);
                         try {
-                            this->wait( timeToSleep );
+                            this->wait(timeToSleep);
                         } catch (InterruptedException& e) {
                         }
                         continue;
@@ -111,7 +108,7 @@ namespace util{
                     // Time to run the task, but first we need to check to see if any other
                     // tasks where scheduled and caused this one to be moved someplace new
on
                     // the heap and find it new location.. We also need to check that the
task
-                    // wasn't cancelled while we were sleeping.
+                    // wasn't canceled while we were sleeping.
                     synchronized(&(task->lock)) {
                         std::size_t pos = 0;
 
@@ -145,9 +142,7 @@ namespace util{
                             // insert this task into queue, it will be ordered by the heap
for
                             // its next run time.
                             insertTask(task);
-
                         } else {
-
                             // Task was a one-shot, setting when to zero indicates it
                             // won't run anymore.
                             task->when = 0;
@@ -191,26 +186,36 @@ namespace util{
 
             return (int)result;
         }
-
     };
+
 }}
 
 ////////////////////////////////////////////////////////////////////////////////
 Timer::Timer() : internal(new TimerImpl()) {
-    this->internal->start();
+    try {
+        this->internal->start();
+    } catch(...) {
+        delete this->internal;
+        throw;
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 Timer::Timer(const std::string& name) : internal(new TimerImpl(name)) {
-    this->internal->start();
+    try {
+        this->internal->start();
+    } catch(...) {
+        delete this->internal;
+        throw;
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 Timer::~Timer() {
-    try{
+    try {
         delete this->internal;
     }
-    DECAF_CATCH_NOTHROW( Exception )
+    DECAF_CATCH_NOTHROW(Exception)
     DECAF_CATCHALL_NOTHROW()
 }
 
@@ -220,6 +225,18 @@ void Timer::cancel() {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+bool Timer::awaitTermination(long long timeout, const TimeUnit& unit) {
+
+    if (!this->internal->isAlive()) {
+        return true;
+    }
+
+    this->internal->join(unit.toMillis(timeout));
+
+    return this->internal->isAlive();
+}
+
+////////////////////////////////////////////////////////////////////////////////
 int Timer::purge() {
     return this->internal->purge();
 }
@@ -227,27 +244,19 @@ int Timer::purge() {
 ////////////////////////////////////////////////////////////////////////////////
 void Timer::schedule(TimerTask* task, long long delay) {
 
-    if(delay < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future but delay
was Negative" );
+    if (delay < 0) {
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled to start in the Future but delay was Negative");
     }
 
-    Pointer<TimerTask> wrapper( task );
+    Pointer<TimerTask> wrapper(task);
 
     try {
         scheduleTask(wrapper, delay, -1, false);
-    } catch (NullPointerException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalArgumentException& ex) {
+    } catch (Exception& ex) {
         wrapper.release();
         ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalStateException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
+        throw;
     }
 }
 
@@ -255,8 +264,8 @@ void Timer::schedule(TimerTask* task, lo
 void Timer::schedule(const Pointer<TimerTask>& task, long long delay) {
 
     if (delay < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future but delay
was Negative");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled to start in the Future but delay was Negative");
     }
 
     scheduleTask(task, delay, -1, false);
@@ -266,8 +275,7 @@ void Timer::schedule(const Pointer<Timer
 void Timer::schedule(TimerTask* task, const Date& when) {
 
     if (when.getTime() < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future.");
+        throw IllegalArgumentException(__FILE__, __LINE__, "Task must be scheduled to start
in the Future.");
     }
 
     Pointer<TimerTask> wrapper(task);
@@ -275,18 +283,10 @@ void Timer::schedule(TimerTask* task, co
 
     try {
         scheduleTask(wrapper, delay < 0 ? 0 : delay, -1, false);
-    } catch (NullPointerException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalArgumentException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalStateException& ex) {
+    } catch (Exception& ex) {
         wrapper.release();
         ex.setMark(__FILE__, __LINE__);
-        throw ex;
+        throw;
     }
 }
 
@@ -294,8 +294,7 @@ void Timer::schedule(TimerTask* task, co
 void Timer::schedule(const Pointer<TimerTask>& task, const Date& when) {
 
     if (when.getTime() < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future.");
+        throw IllegalArgumentException(__FILE__, __LINE__, "Task must be scheduled to start
in the Future.");
     }
 
     long long delay = when.getTime() - System::currentTimeMillis();
@@ -306,31 +305,23 @@ void Timer::schedule(const Pointer<Timer
 void Timer::schedule(TimerTask* task, long long delay, long long period) {
 
     if (delay < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future but delay
was Negative");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled to start in the Future but delay was Negative");
     }
 
     if (period <= 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled non-negative or non-zero period.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled non-negative or non-zero period.");
     }
 
     Pointer<TimerTask> wrapper(task);
 
     try {
         scheduleTask(wrapper, delay, period, false);
-    } catch (NullPointerException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalArgumentException& ex) {
+    } catch (Exception& ex) {
         wrapper.release();
         ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalStateException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
+        throw;
     }
 }
 
@@ -338,13 +329,13 @@ void Timer::schedule(TimerTask* task, lo
 void Timer::schedule(const Pointer<TimerTask>& task, long long delay, long long
period) {
 
     if (delay < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future but delay
was Negative");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled to start in the Future but delay was Negative");
     }
 
     if (period <= 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled non-negative or non-zero period.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled non-negative or non-zero period.");
     }
 
     scheduleTask(task, delay, period, false);
@@ -354,13 +345,13 @@ void Timer::schedule(const Pointer<Timer
 void Timer::schedule(TimerTask* task, const Date& when, long long period) {
 
     if (when.getTime() < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled to start in the Future.");
     }
 
     if (period <= 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled non-negative or non-zero period.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled non-negative or non-zero period.");
     }
 
     Pointer<TimerTask> wrapper(task);
@@ -368,18 +359,10 @@ void Timer::schedule(TimerTask* task, co
 
     try {
         scheduleTask(wrapper, delay < 0 ? 0 : delay, period, false);
-    } catch (NullPointerException& ex) {
+    } catch (Exception& ex) {
         wrapper.release();
         ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalArgumentException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalStateException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
+        throw;
     }
 }
 
@@ -387,13 +370,13 @@ void Timer::schedule(TimerTask* task, co
 void Timer::schedule(const Pointer<TimerTask>& task, const Date& when, long
long period) {
 
     if (when.getTime() < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled to start in the Future.");
     }
 
     if (period <= 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled non-negative or non-zero period.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled non-negative or non-zero period.");
     }
 
     long long delay = when.getTime() - System::currentTimeMillis();
@@ -404,31 +387,23 @@ void Timer::schedule(const Pointer<Timer
 void Timer::scheduleAtFixedRate(TimerTask* task, long long delay, long long period) {
 
     if (delay < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future but delay
was Negative");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled to start in the Future but delay was Negative");
     }
 
     if (period <= 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled non-negative or non-zero period.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled non-negative or non-zero period.");
     }
 
     Pointer<TimerTask> wrapper(task);
 
     try {
         scheduleTask(wrapper, delay, period, true);
-    } catch (NullPointerException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalArgumentException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalStateException& ex) {
+    } catch (Exception& ex) {
         wrapper.release();
         ex.setMark(__FILE__, __LINE__);
-        throw ex;
+        throw;
     }
 }
 
@@ -436,13 +411,13 @@ void Timer::scheduleAtFixedRate(TimerTas
 void Timer::scheduleAtFixedRate(const Pointer<TimerTask>& task, long long delay,
long long period) {
 
     if (delay < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future but delay
was Negative");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled to start in the Future but delay was Negative");
     }
 
     if (period <= 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled non-negative or non-zero period.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled non-negative or non-zero period.");
     }
 
     scheduleTask(task, delay, period, true);
@@ -452,13 +427,13 @@ void Timer::scheduleAtFixedRate(const Po
 void Timer::scheduleAtFixedRate(TimerTask* task, const Date& when, long long period)
{
 
     if (when.getTime() < 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled to start in the Future.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled to start in the Future.");
     }
 
     if (period <= 0) {
-        throw IllegalArgumentException(
-            __FILE__, __LINE__, "Task must be scheduled non-negative or non-zero period.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled non-negative or non-zero period.");
     }
 
     Pointer<TimerTask> wrapper(task);
@@ -466,18 +441,10 @@ void Timer::scheduleAtFixedRate(TimerTas
 
     try {
         scheduleTask(wrapper, delay < 0 ? 0 : delay, period, true);
-    } catch (NullPointerException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalArgumentException& ex) {
+    } catch (Exception& ex) {
         wrapper.release();
         ex.setMark(__FILE__, __LINE__);
-        throw ex;
-    } catch (IllegalStateException& ex) {
-        wrapper.release();
-        ex.setMark(__FILE__, __LINE__);
-        throw ex;
+        throw;
     }
 }
 
@@ -485,11 +452,13 @@ void Timer::scheduleAtFixedRate(TimerTas
 void Timer::scheduleAtFixedRate(const Pointer<TimerTask>& task, const Date&
when, long long period) {
 
     if (when.getTime() < 0) {
-        throw IllegalArgumentException(__FILE__, __LINE__, "Task must be scheduled to start
in the Future.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled to start in the Future.");
     }
 
     if (period <= 0) {
-        throw IllegalArgumentException(__FILE__, __LINE__, "Task must be scheduled non-negative
or non-zero period.");
+        throw IllegalArgumentException(__FILE__, __LINE__,
+            "Task must be scheduled non-negative or non-zero period.");
     }
 
     long long delay = when.getTime() - System::currentTimeMillis();
@@ -512,17 +481,20 @@ void Timer::scheduleTask(const Pointer<T
         long long when = delay + System::currentTimeMillis();
 
         if (when < 0) {
-            throw IllegalArgumentException(__FILE__, __LINE__, "Task must be scheduled to
start in the Future but delay was Negative");
+            throw IllegalArgumentException(__FILE__, __LINE__,
+                "Task must be scheduled to start in the Future but delay was Negative");
         }
 
         synchronized(&(task->lock)) {
 
             if (task->isScheduled()) {
-                throw IllegalStateException(__FILE__, __LINE__, "Task is already scheduled
in a Timer, cannot add again.");
+                throw IllegalStateException(__FILE__, __LINE__,
+                    "Task is already scheduled in a Timer, cannot add again.");
             }
 
             if (task->cancelled) {
-                throw IllegalStateException(__FILE__, __LINE__, "Task is already has been
cancelled cannot be restarted.");
+                throw IllegalStateException(__FILE__, __LINE__,
+                    "Task is already has been cancelled cannot be restarted.");
             }
 
             task->when = when;

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Timer.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Timer.h?rev=1420260&r1=1420259&r2=1420260&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Timer.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Timer.h Tue Dec 11 16:29:59
2012
@@ -22,7 +22,7 @@
 
 #include <decaf/util/Config.h>
 #include <decaf/util/Date.h>
-
+#include <decaf/util/concurrent/TimeUnit.h>
 #include <decaf/lang/Pointer.h>
 #include <decaf/lang/exceptions/NullPointerException.h>
 #include <decaf/lang/exceptions/IllegalStateException.h>
@@ -91,6 +91,23 @@ namespace util {
         void cancel();
 
         /**
+         * The caller will block until the Timer has completed termination meaning all tasks
+         * that where scheduled before cancelation have now completed and the executor is
ready for
+         * deletion.  If the timeout period elapses before the Timer reaches the terminated
+         * state then this method return false to indicate it has not terminated.
+         *
+         * @param timeout
+         *      The amount of time to wait before abandoning the wait for termination.
+         * @param unit
+         *      The unit of time that the timeout value represents.
+         *
+         * @return true if the Timer terminated or false if the timeout expired.
+         *
+         * @throws InterruptedException if this call is interrupted while awaiting termination.
+         */
+        bool awaitTermination(long long timeout, const decaf::util::concurrent::TimeUnit&
unit);
+
+        /**
          * Removes all canceled tasks from this timer's task queue. Calling this method has
no effect on the
          * behavior of the timer, but eliminates the canceled tasks from the queue causing
the Timer to destroy
          * the TimerTask pointer it was originally given, the caller should ensure that they
no longer have

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/ThreadPoolExecutor.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/ThreadPoolExecutor.cpp?rev=1420260&r1=1420259&r2=1420260&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/ThreadPoolExecutor.cpp
(original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/ThreadPoolExecutor.cpp
Tue Dec 11 16:29:59 2012
@@ -384,7 +384,7 @@ namespace concurrent{
         }
 
         ~ExecutorKernel() {
-            try{
+            try {
 
                 // Turn off the cleanup timer first so that it doesn't fire while
                 // we transition all the remaining workers into the dead workers
@@ -402,6 +402,10 @@ namespace concurrent{
                 this->shutdown();
                 this->awaitTermination();
 
+                // We need to wait for the worker cleanup timer to shutdown, otherwise
+                // it could segfault if it's still running when the destructor finishes.
+                this->cleanupTimer.awaitTermination(10, TimeUnit::MINUTES);
+
                 // Ensure dead Worker Threads are destroyed, the Timer might not have
                 // run recently.
                 Pointer< Iterator<Worker*> > workers(this->deadWorkers.iterator());



Mime
View raw message