blob: a5da8fd13f0a481568ef998e30a377339087d777 [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"
#ifdef _WIN32
#pragma warning( disable: 4311 )
#endif
#include <decaf/internal/DecafRuntime.h>
#include <decaf/internal/util/concurrent/Threading.h>
#include <decaf/lang/Integer.h>
#include <decaf/lang/Long.h>
#include <decaf/lang/Math.h>
#include <decaf/lang/Exception.h>
#include <decaf/lang/exceptions/RuntimeException.h>
#include <decaf/lang/exceptions/NullPointerException.h>
#include <decaf/lang/exceptions/IllegalThreadStateException.h>
#include <decaf/util/concurrent/TimeUnit.h>
#include <decaf/util/concurrent/Mutex.h>
#include <decaf/util/concurrent/Executors.h>
#include <vector>
using namespace decaf;
using namespace decaf::internal;
using namespace decaf::internal::util;
using namespace decaf::internal::util::concurrent;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
using namespace decaf::util;
using namespace decaf::util::concurrent;
////////////////////////////////////////////////////////////////////////////////
namespace decaf {
namespace lang {
class ThreadProperties {
private:
ThreadProperties( const ThreadProperties& );
ThreadProperties& operator= ( const ThreadProperties& );
public:
Runnable* task;
ThreadHandle* handle;
Thread::UncaughtExceptionHandler* exHandler;
static unsigned int id;
static Thread::UncaughtExceptionHandler* defaultHandler;
public:
ThreadProperties() : task(NULL), handle(NULL), exHandler(NULL) {}
};
}}
////////////////////////////////////////////////////////////////////////////////
unsigned int ThreadProperties::id = 0;
Thread::UncaughtExceptionHandler* ThreadProperties::defaultHandler = NULL;
////////////////////////////////////////////////////////////////////////////////
Thread::Thread(ThreadHandle* handle) : Runnable(), properties(NULL) {
this->properties = new ThreadProperties();
this->properties->handle = handle;
}
////////////////////////////////////////////////////////////////////////////////
Thread::Thread() : Runnable(), properties(NULL) {
this->initializeSelf(NULL, "", -1);
}
////////////////////////////////////////////////////////////////////////////////
Thread::Thread(Runnable* task) : Runnable(), properties(NULL) {
this->initializeSelf(task, "", -1);
}
////////////////////////////////////////////////////////////////////////////////
Thread::Thread(const std::string& name) : Runnable(), properties(NULL) {
this->initializeSelf(NULL, name, -1);
}
////////////////////////////////////////////////////////////////////////////////
Thread::Thread(Runnable* task, const std::string& name) : Runnable(), properties( NULL ) {
this->initializeSelf(task, name, -1);
}
////////////////////////////////////////////////////////////////////////////////
Thread::Thread(Runnable* task, const std::string& name, long long stackSize) : Runnable(), properties( NULL ) {
this->initializeSelf(task, name, stackSize);
}
////////////////////////////////////////////////////////////////////////////////
void Thread::initializeSelf(Runnable* task, const std::string& name, long long stackSize) {
std::string threadName = name;
if (threadName.empty()) {
threadName = std::string("Thread-") + Integer::toString(++ThreadProperties::id);
} else {
threadName = name;
}
this->properties = new ThreadProperties();
this->properties->handle =
Threading::createNewThread(this, threadName.c_str(), stackSize);
this->properties->task = task;
}
////////////////////////////////////////////////////////////////////////////////
Thread::~Thread() {
try {
Threading::destroyThread(this->properties->handle);
delete this->properties;
}
DECAF_CATCH_NOTHROW(Exception)
DECAF_CATCHALL_NOTHROW()
}
////////////////////////////////////////////////////////////////////////////////
void Thread::run() {
if (this->properties->task != NULL) {
this->properties->task->run();
}
}
////////////////////////////////////////////////////////////////////////////////
void Thread::start() {
try {
if (Threading::getThreadState(this->properties->handle) > Thread::NEW) {
throw IllegalThreadStateException(
__FILE__, __LINE__,
"Thread::start - Thread already started");
}
Threading::start(this->properties->handle);
}
DECAF_CATCH_RETHROW(IllegalThreadStateException)
DECAF_CATCH_RETHROW(RuntimeException)
DECAF_CATCH_EXCEPTION_CONVERT(NullPointerException, RuntimeException)
DECAF_CATCHALL_THROW(RuntimeException)
}
////////////////////////////////////////////////////////////////////////////////
void Thread::join() {
Threading::join(this->properties->handle, 0, 0);
}
////////////////////////////////////////////////////////////////////////////////
void Thread::join(long long millisecs) {
if (millisecs < 0) {
throw IllegalArgumentException(
__FILE__, __LINE__,
"Thread::join( millisecs ) - Value given {%d} is less than 0", millisecs );
}
Threading::join(this->properties->handle, millisecs, 0);
}
////////////////////////////////////////////////////////////////////////////////
void Thread::join(long long millisecs, int nanos) {
if (millisecs < 0) {
throw IllegalArgumentException(
__FILE__, __LINE__,
"Thread::join( millisecs, nanos ) - Value given {%d} is less than 0", millisecs );
}
if (nanos < 0 || nanos > 999999) {
throw IllegalArgumentException(
__FILE__, __LINE__,
"Thread::join( millisecs, nanos ) - Nanoseconds must be in range [0...999999]" );
}
Threading::join(this->properties->handle, millisecs, nanos);
}
////////////////////////////////////////////////////////////////////////////////
void Thread::sleep(long long millisecs) {
Threading::sleep(millisecs, 0);
}
////////////////////////////////////////////////////////////////////////////////
void Thread::sleep(long long millisecs, int nanos) {
if (millisecs < 0) {
throw IllegalArgumentException(
__FILE__, __LINE__,
"Thread::sleep( millisecs, nanos ) - Value given {%d} is less than 0", millisecs );
}
if (nanos < 0 || nanos > 999999) {
throw IllegalArgumentException(
__FILE__, __LINE__,
"Thread::sleep( millisecs, nanos ) - Nanoseconds must be in range [0...999999]" );
}
Threading::sleep(millisecs, nanos);
}
////////////////////////////////////////////////////////////////////////////////
void Thread::yield() {
Threading::yeild();
}
////////////////////////////////////////////////////////////////////////////////
long long Thread::getId() const {
return Threading::getThreadId(this->properties->handle);
}
////////////////////////////////////////////////////////////////////////////////
void Thread::setName(const std::string& name) {
Threading::setThreadName(this->properties->handle, name.c_str());
}
////////////////////////////////////////////////////////////////////////////////
std::string Thread::getName() const {
return Threading::getThreadName(this->properties->handle);
}
////////////////////////////////////////////////////////////////////////////////
void Thread::setPriority(int value) {
if (value < Thread::MIN_PRIORITY || value > Thread::MAX_PRIORITY) {
throw IllegalArgumentException(
__FILE__, __LINE__,
"Thread::setPriority - Specified value {%d} is out of range", value );
}
Threading::setThreadPriority(this->properties->handle, value);
}
////////////////////////////////////////////////////////////////////////////////
int Thread::getPriority() const {
return Threading::getThreadPriority(this->properties->handle);
}
////////////////////////////////////////////////////////////////////////////////
void Thread::setUncaughtExceptionHandler(UncaughtExceptionHandler* handler) {
this->properties->exHandler = handler;
}
////////////////////////////////////////////////////////////////////////////////
Thread::UncaughtExceptionHandler* Thread::getUncaughtExceptionHandler() const {
return this->properties->exHandler;
}
////////////////////////////////////////////////////////////////////////////////
Thread::UncaughtExceptionHandler* Thread::getDefaultUncaughtExceptionHandler() {
return ThreadProperties::defaultHandler;
}
////////////////////////////////////////////////////////////////////////////////
void Thread::setDefaultUncaughtExceptionHandler(Thread::UncaughtExceptionHandler* handler) {
ThreadProperties::defaultHandler = handler;
}
////////////////////////////////////////////////////////////////////////////////
std::string Thread::toString() const {
return std::string(Threading::getThreadName(this->properties->handle)) + ": Priority=" +
Integer::toString(Threading::getThreadPriority(this->properties->handle)) +
", ThreadID=" + Long::toString( Threading::getThreadId(this->properties->handle));
}
////////////////////////////////////////////////////////////////////////////////
bool Thread::isAlive() const {
return Threading::isThreadAlive(this->properties->handle);
}
////////////////////////////////////////////////////////////////////////////////
Thread::State Thread::getState() const {
return Threading::getThreadState(this->properties->handle);
}
////////////////////////////////////////////////////////////////////////////////
Thread* Thread::currentThread() {
return Threading::getCurrentThread();
}
////////////////////////////////////////////////////////////////////////////////
void Thread::interrupt() {
Threading::interrupt(this->properties->handle);
}
////////////////////////////////////////////////////////////////////////////////
bool Thread::interrupted() {
return Threading::interrupted();
}
////////////////////////////////////////////////////////////////////////////////
bool Thread::isInterrupted() const {
return Threading::isInterrupted(this->properties->handle, false);
}
////////////////////////////////////////////////////////////////////////////////
ThreadHandle* Thread::getHandle() const {
return this->properties->handle;
}