blob: 978f077576cfffdcc1b3f9376c3454443829b991 [file] [log] [blame]
/*
* 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"
#include <apr_time.h>
#include <apr_portable.h>
#include <decaf/lang/Exception.h>
#include <decaf/lang/exceptions/RuntimeException.h>
using namespace decaf;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
////////////////////////////////////////////////////////////////////////////////
Thread::Thread() {
this->task = this;
this->started = false;
this->joined = false;
this->pool = NULL;
this->threadHandle = NULL;
}
////////////////////////////////////////////////////////////////////////////////
Thread::Thread( Runnable* task ) {
this->task = task;
this->started = false;
this->joined = false;
this->pool = NULL;
this->threadHandle = NULL;
}
////////////////////////////////////////////////////////////////////////////////
Thread::~Thread(){
if( pool != NULL ) {
apr_pool_destroy( pool );
}
}
////////////////////////////////////////////////////////////////////////////////
void Thread::start() throw ( Exception )
{
if( this->started ) {
throw Exception(
__FILE__, __LINE__,
"Thread::start - Thread already started");
}
apr_pool_create( &pool, NULL );
apr_status_t err = apr_thread_create(
&this->threadHandle,
NULL,
runCallback,
this,
pool );
if( err != APR_SUCCESS ) {
throw Exception(
__FILE__, __LINE__,
"Thread::start - Coud not start thread");
}
// Mark the thread as started.
started = true;
}
////////////////////////////////////////////////////////////////////////////////
void Thread::join() throw( Exception )
{
if( !this->started ) {
throw Exception( __FILE__, __LINE__,
"Thread::join() called without having called Thread::start()");
}
if( !this->joined ) {
apr_status_t threadReturn;
if( apr_thread_join( &threadReturn, this->threadHandle ) != APR_SUCCESS ) {
throw Exception( __FILE__, __LINE__,
"Thread::join() - Failed to Join the Thread");
}
}
this->joined = true;
}
////////////////////////////////////////////////////////////////////////////////
void Thread::sleep( int millisecs ) {
apr_sleep( (apr_interval_time_t)(millisecs * 1000) );
}
////////////////////////////////////////////////////////////////////////////////
unsigned long Thread::getId() {
return (long)( apr_os_thread_current() );
}
////////////////////////////////////////////////////////////////////////////////
void* APR_THREAD_FUNC Thread::runCallback( apr_thread_t* self, void* param ) {
// Get the instance.
Thread* thread = (Thread*)param;
// Invoke run on the task.
try{
thread->task->run();
} catch( ... ){
RuntimeException ex(
__FILE__, __LINE__,
"unhandled exception bubbled up to Thread::run");
ex.printStackTrace();
}
// Indicate we are done.
apr_thread_exit( self, APR_SUCCESS );
return NULL;
}