| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "Thread.h" |
| |
| #ifdef HAVE_PTHREAD_H |
| #include <errno.h> |
| #else |
| #include <process.h> // _endthreadex |
| #endif |
| |
| #include <activemq/exceptions/ActiveMQException.h> |
| #include <activemq/exceptions/RuntimeException.h> |
| |
| using namespace activemq; |
| using namespace activemq::concurrent; |
| |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Thread::Thread() |
| { |
| task = this; |
| started = false; |
| joined = false; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Thread::Thread( Runnable* task ) |
| { |
| this->task = task; |
| started = false; |
| joined = false; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Thread::~Thread() |
| { |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void Thread::start() throw ( exceptions::ActiveMQException ) |
| { |
| if (this->started) { |
| throw exceptions::ActiveMQException( __FILE__, __LINE__, |
| "Thread already started"); |
| } |
| |
| #ifdef HAVE_PTHREAD_H |
| |
| ::pthread_attr_init (&attributes); |
| ::pthread_attr_setdetachstate (&attributes, PTHREAD_CREATE_JOINABLE); |
| int err = ::pthread_create ( |
| &this->threadHandle, |
| &attributes, |
| runCallback, |
| this); |
| if (err != 0) { |
| throw exceptions::ActiveMQException( __FILE__, __LINE__, |
| "Coud not start thread"); |
| } |
| |
| #else |
| |
| unsigned int threadId = 0; |
| this->threadHandle = |
| (HANDLE)::_beginthreadex(NULL, 0, runCallback, this, 0, &threadId); |
| if (this->threadHandle == NULL) { |
| throw exceptions::ActiveMQException( __FILE__, __LINE__, |
| "Coud not start thread"); |
| } |
| |
| #endif |
| |
| // Mark the thread as started. |
| started = true; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void Thread::join() throw( exceptions::ActiveMQException ) |
| { |
| if (!this->started) { |
| throw exceptions::ActiveMQException( __FILE__, __LINE__, |
| "Thread::join() called without having called Thread::start()"); |
| } |
| if (!this->joined) { |
| |
| #ifdef HAVE_PTHREAD_H |
| ::pthread_join(this->threadHandle, NULL); |
| #else |
| ::WaitForSingleObject (this->threadHandle, INFINITE); |
| #endif |
| |
| } |
| this->joined = true; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void Thread::sleep( int millisecs ) |
| { |
| #ifdef HAVE_PTHREAD_H |
| struct timespec rec, rem; |
| rec.tv_sec = millisecs / 1000; |
| rec.tv_nsec = (millisecs % 1000) * 1000000; |
| while( nanosleep( &rec, &rem ) == -1 ){ |
| if( errno != EINTR ){ |
| break; |
| } |
| } |
| |
| #else |
| ::Sleep (millisecs); |
| #endif |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| unsigned long Thread::getId(void) |
| { |
| #ifdef HAVE_PTHREAD_H |
| return (long)(pthread_self()); |
| #else |
| return GetCurrentThreadId(); |
| #endif |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| #ifdef HAVE_PTHREAD_H |
| void* |
| #else |
| unsigned int WINAPI |
| #endif |
| Thread::runCallback( void* param ) |
| { |
| // Get the instance. |
| Thread* thread = (Thread*)param; |
| |
| // Invoke run on the task. |
| try{ |
| thread->task->run(); |
| } catch( ... ){ |
| exceptions::RuntimeException ex(__FILE__, __LINE__, "unhandled exception bubbled up to Thread::run"); |
| ex.printStackTrace(); |
| } |
| |
| #ifdef HAVE_PTHREAD_H |
| ::pthread_attr_destroy( &thread->attributes ); |
| return NULL; |
| #else |
| |
| // Needed when using threads and CRT in Windows. Otherwise memleak can appear. |
| ::_endthreadex(0); |
| |
| // _endthreadex (unlike _endthread) does not automatically close the thread handle |
| // so we need to do this manually. |
| ::CloseHandle(thread->threadHandle); |
| |
| return 0; |
| #endif |
| } |
| |