From 4b070250f7965d41f150ee7a31ef3f8326e7662b Mon Sep 17 00:00:00 2001 From: Truong Hoang Minh Date: Sat, 19 Aug 2017 09:41:49 +0700 Subject: [PATCH 01/41] #231 Defined private, public variable. Clean unuse code --- java/lang/Double/DoubleTest.cpp | 8 +- java/lang/Thread/Thread.cpp | 159 ++++++------------------------ java/lang/Thread/Thread.hpp | 168 ++++++++++++++++++++++++++------ java/lang/Thread/ThreadTest.cpp | 154 ++++++++++------------------- 4 files changed, 223 insertions(+), 266 deletions(-) diff --git a/java/lang/Double/DoubleTest.cpp b/java/lang/Double/DoubleTest.cpp index 7a75fb1f..44cdd2e1 100644 --- a/java/lang/Double/DoubleTest.cpp +++ b/java/lang/Double/DoubleTest.cpp @@ -523,25 +523,25 @@ TEST(JavaLang, DoubleLongValue) { // Test POSITIVE_INFINITY_DOUBLE variableTestLongValue = POSITIVE_INFINITY_DOUBLE; - expectedResultLongValue = -9223372036854775808l; + expectedResultLongValue = -9223372036854775808u; actualResultLongValue = variableTestLongValue.longValue(); ASSERT_EQUAL(expectedResultLongValue , actualResultLongValue); // Test NEGATIVE_INFINITY_DOUBLE variableTestLongValue = NEGATIVE_INFINITY_DOUBLE; - expectedResultLongValue = -9223372036854775808l; + expectedResultLongValue = -9223372036854775808u; actualResultLongValue = variableTestLongValue.longValue(); ASSERT_EQUAL(expectedResultLongValue , actualResultLongValue); // Test NaN_NUMBER_DOUBLE variableTestLongValue = NaN_NUMBER_DOUBLE; - expectedResultLongValue = -9223372036854775808l; + expectedResultLongValue = -9223372036854775808u; actualResultLongValue = variableTestLongValue.longValue(); ASSERT_EQUAL(expectedResultLongValue , actualResultLongValue); // Test MAX_VALUE_DOUBLE variableTestLongValue = MAX_VALUE_DOUBLE; - expectedResultLongValue = -9223372036854775808l; + expectedResultLongValue = -9223372036854775808u; actualResultLongValue = variableTestLongValue.longValue(); ASSERT_EQUAL(expectedResultLongValue , actualResultLongValue); diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index 0d4aa2b6..a0bc0e06 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -1,129 +1,30 @@ -///** -// * Copyright (c) 2016 Food Tiny Project. All rights reserved. -// * -// * Redistribution and use in source and binary forms, with or without -// * modification, are permitted provided that the following conditions are met: -// * -// * Redistributions of source code must retain the above copyright -// * notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// * copyright notice, this list of conditions and the following disclaimer -// * in the documentation and/or other materials provided with the -// * distribution. -// * -// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// */ -// -//#include "Thread.hpp" -// -//using namespace Java::Lang; -// -//Thread::Thread() { -// this->target = NULL; -// this->threadName = strdup(""); -//} -// -//Thread::Thread(Runnable &target2) { -// this->target = &target2; -// this->threadName = strdup(""); -//} -// -//Thread::Thread(Runnable &target2, String name) { -// this->target = &target2; -// this->threadName = strdup(name.toString()); -//} -// -//Thread::Thread(String name) { -// this->target = NULL; -// this->threadName = strdup(name.toString()); -//} -// -//Thread::~Thread() { -// //TODO: reduce Thread::Thread.numberThread -// if (this->threadName != NULL) { -// free(this->threadName); -// } -//} -// -///** -// * Call Runnable target's run() method -// */ -//void Thread::run() const { -// if (this->target != NULL) { -// this->target->run(); -// } -//} -// -///** -// * Force thread and call Runnable target's run() method -// */ -//void Thread::start() { -// this->isThreadRunning = TRUE; -// pthread_create(&this->original, NULL, &Thread::pthread_helper, (void *) this); -//} -// -///** -// * Stop a thread if it's running -// */ -//void Thread::stop() { -// if (!this->isThreadRunning) { -// return; -// } -// -// //pthread_cancel(this->original); -// this->isThreadRunning = FALSE; -//} -// -///** -// * Waits for this thread to die if it's running -// */ -//void Thread::join() { -// if (!this->isThreadRunning) { -// return; -// } -// -// pthread_join(this->original, NULL); -//} -// -///** -// * Waits at most millis milliseconds for this thread to die if it's running -// */ -//void Thread::join(unsigned int millis) { -// if (!this->isThreadRunning) { -// return; -// } -// -// usleep(millis * 1000); -// pthread_join(this->original, NULL); -//} -// -///** -// * Return this thread's name -// */ -//string Thread::getName() { -// return this->threadName; -//} -// -///** -// * Set this thread's name -// */ -//void Thread::setName(string target) { -// this->threadName = strdup(target); -//} -// -///** -// * Returns a string representation of this thread, including the thread's name, priority, and thread group. -// */ -//string Thread::toString() const { -// return this->threadName; -//} +/** + * Copyright (c) 2016 Food Tiny Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Thread.hpp" + +using namespace Java::Lang; + diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index 7048ad32..15fbabd4 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -24,8 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JAVA_LANG_THREAD_HPP_ -#define JAVA_LANG_THREAD_HPP_ +#ifndef JAVA_LANG_THREAD_THREAD_HPP_ +#define JAVA_LANG_THREAD_THREAD_HPP_ #include #include "../Object/Object.hpp" @@ -35,46 +35,154 @@ namespace Java { namespace Lang { class Thread : public Object, public virtual Runnable { - private: + private: pthread_t original; - string threadName; - Runnable *target; - boolean isThreadRunning; - ///Adds-on function to adapt pthread_create of C style - public: + + volatile string name; + int priority; + Thread threadQ(); + long eetop; + + /** + * Whether or not to single_step this thread. + */ + boolean single_step; + + /** + * Whether or not the thread is a daemon thread. + */ + boolean daemon = false; + + /** + * JVM state + */ + boolean stillborn = false; + + /** + * What will be run. + */ + Runnable *target; + + // TODO(thoangminh): Need Class ThreadGroup + /** + * The group of this thread + */ +// ThreadGroup group; + + // TODO(thoangminh): Need Class ClassLoader + /** + * The context ClassLoader for this thread + */ +// ClassLoader contextClassLoader; + + // TODO(thoangminh): Need Class AccessControlContext + /** + * The inherited AccessControlContext of this thread + */ +// AccessControlContext inheritedAccessControlContext; + + /** + * For autonumbering anonymous threads. + */ + static int threadInitNumber; + + // TODO(thoangminh): Need Class ThreadLocal + /** + * ThreadLocal values pertaining to this thread. + * This map is maintained + * by the ThreadLocal class. + */ +// ThreadLocal.ThreadLocalMap threadLocals = null; + + // TODO(thoangminh): Need Class ThreadLocal + /** + * InheritableThreadLocal values pertaining to this thread. + * This map is maintained by + * the InheritableThreadLocal class. + */ +// ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; + + /** + * The requested stack size for this thread, or 0 if the creator did + * not specify a stack size. It is up to the VM to do + * whatever it likes with this number; some VMs will ignore it. * + */ + long stackSize; + + /** + * JVM-private state that persists after native thread termination. + */ + long nativeParkEventPointer; + + /** + * Thread ID + */ + long tid; + + /** + * For generating thread ID + */ + static long threadSeqNumber; + + /** + * Java thread status for tools, + * initialized to indicate thread 'not yet started' + */ + volatile int threadStatus = 0; + + // TODO(thoangminh): Need Class Interruptible + /** + * The object in which this thread is blocked in an interruptible I/O + * operation, if any. The blocker's interrupt method should be invoked + * after setting this thread's interrupt status. + */ +// volatile Interruptible blocker; +// const Object blockerLock = new Object(); + + + public: + /** + * The minimum priority that a thread can have. + */ + static int const MIN_PRIORITY = 1; + + /** + * The default priority that is assigned to a thread. + */ + static int const NORM_PRIORITY = 5; + + /** + * The maximum priority that a thread can have. + */ + static int const MAX_PRIORITY = 10; + + public: void *pthread_run(void *context) { - ((Thread *) context )->target->run(); + ((Thread *) (context))->target->run(); } static void *pthread_helper(void *context) { - return ((Thread *) context )->pthread_run(context); + return ((Thread *) (context))->pthread_run(context); } - public: + public: Thread(); - Thread(Runnable &target2); - Thread(Runnable &target2, String name); - Thread(String name); - //Thread(ThreadGroup group, Runnable &target); - //Thread(ThreadGroup group, Runnable &target, String &name); - //Thread(ThreadGroup group, Runnable &target, String &name, long stackSize); - //Thread(ThreadGroup group, String &name); + Thread(Runnable &target); + Thread(String name); +// Thread(Runnable target, AccessControlContext acc); +// Thread(ThreadGroup group, Runnable target); +// Thread(ThreadGroup group, String name); + Thread(Runnable &target, String name); +// Thread(ThreadGroup group, Runnable target +// , String name, long stackSize); +// Thread(ThreadGroup group, Runnable target, String name); ~Thread(); - public: + public: void run() const; - void start(); - void stop(); - void join(); - void join(unsigned int millis); - - string getName(); - void setName(string target); - string toString() const; - }; - } -} + } // namespace Lang +} // namespace Java #endif // JAVA_LANG_THREAD_THREAD_HPP_ \ No newline at end of file diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 10686f1f..73dad5b6 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -1,103 +1,51 @@ -///** -// * Copyright (c) 2016 Food Tiny Project. All rights reserved. -// * -// * Redistribution and use in source and binary forms, with or without -// * modification, are permitted provided that the following conditions are met: -// * -// * Redistributions of source code must retain the above copyright -// * notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// * copyright notice, this list of conditions and the following disclaimer -// * in the documentation and/or other materials provided with the -// * distribution. -// * -// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// */ -// -//extern "C" { -//#include "../../../kernel/test.h" -//}; -// -//#include "Thread.hpp" -// -//using namespace Java::Lang; -// -//class RunnableTarget : public virtual Runnable { -//public: -// void run() const { -// } -//}; -// -//class RunnableTarget2 : public virtual Runnable { -//public: -// void run() const { -// int index = 0; -// int limit = 51; -// for (; index <= limit; index++) { -// // printf("Index [%d] must not equal to %d to test Thread.stop()\n", index, limit); -// usleep(1); -// } -// } -//}; -// -//TEST (JavaLang, ThreadConstructor) { -// return; -// // Given valid Thread with default constructor -// Thread thread; -// -// // Test empty threadName -// ASSERT_STR("", thread.getName()); -// -// // Given valid Thread & valid Target to test constructor with target and threadName -// RunnableTarget target; -// Thread thread2 = Thread(target, String("sample thread")); -// -// // Test true after call constructor -// ASSERT_STR("sample thread", thread2.getName()); -//} -// -//TEST (JavaLang, ThreadName) { -// return; -// // Given valid Thread to test get/set thread name -// Thread thread; -// -// // Test true after set new name for threadName -// thread.setName((string) "Some valid name"); -// ASSERT_STR("Some valid name", thread.getName()); -//} -// -//TEST (JavaLang, ThreadStart) { -// return; -// // Given valid Target and valid Thread to test start(), join(), join(millis) functions -// RunnableTarget validTarget; -// Thread thread = Thread(validTarget); -// -// thread.start(); -// thread.join(); /// Make sure that thread has join() because if not -// /// there will be crashed because it's finished this test case before this thread's completed -// -// ///Please help to check this output <"Hello world"> is appeared at test case 74 or not -//} -// -//TEST (JavaLang, ThreadStop) { -// return; -// // Given valid RunnableTarget2's instance, valid Thread's instance, start success a Thread to test Thread.stop() -// RunnableTarget2 target; -// Thread thread = Thread(target); -// -// thread.start(); -// usleep(10); -// thread.stop(); -// -// ///Please check: <"Index [%index] must not equal to %limit to test Thread.stop()"> is appeared at test case 75 or not -//} +/** + * Copyright (c) 2016 Food Tiny Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +extern "C" { +#include "../../../kernel/test.h" +}; + +#include "Thread.hpp" + +using namespace Java::Lang; + +class RunnableTarget : public virtual Runnable { +public: + void run() const { + } +}; + +class RunnableTarget2 : public virtual Runnable { +public: + void run() const { + int index = 0; + int limit = 51; + for (; index <= limit; index++) { + // printf("Index [%d] must not equal to %d to test Thread.stop()\n", index, limit); + usleep(1); + } + } +}; From 8c5b2507664a4d48c23aa54329638ec4f410cf0c Mon Sep 17 00:00:00 2001 From: Truong Hoang Minh Date: Sat, 19 Aug 2017 17:13:02 +0700 Subject: [PATCH 02/41] #231 Added test + Built Constructor, Getter + Setter of name, priority, daemon. Thread::run(), ASSERT_NOT_STR --- java/lang/Double/Double.cpp | 2 +- java/lang/Float/FloatTest.cpp | 8 +- java/lang/Thread/Thread.cpp | 56 +++++ java/lang/Thread/Thread.hpp | 365 +++++++++++++++++++++----------- java/lang/Thread/ThreadTest.cpp | 87 ++++++++ kernel/test.h | 11 + 6 files changed, 397 insertions(+), 132 deletions(-) diff --git a/java/lang/Double/Double.cpp b/java/lang/Double/Double.cpp index 35be1e73..bc6e9bb7 100755 --- a/java/lang/Double/Double.cpp +++ b/java/lang/Double/Double.cpp @@ -47,7 +47,7 @@ Double::Double(const Double &doubleNumber) { } Double::~Double() { - if (this->originalString != NULL) { + if (this->originalString != nullptr) { free(this->originalString); } } diff --git a/java/lang/Float/FloatTest.cpp b/java/lang/Float/FloatTest.cpp index 48f9f6a9..6aa5eab7 100755 --- a/java/lang/Float/FloatTest.cpp +++ b/java/lang/Float/FloatTest.cpp @@ -517,25 +517,25 @@ TEST(JavaLang, FloatLongValue) { // Test POSITIVE_INFINITY variableTestLongValue = POSITIVE_INFINITY; - expectedResultLongValue = -9223372036854775808l; + expectedResultLongValue = -9223372036854775808u; actualResultLongValue = variableTestLongValue.longValue(); ASSERT_EQUAL(expectedResultLongValue , actualResultLongValue); // Test NEGATIVE_INFINITY variableTestLongValue = NEGATIVE_INFINITY; - expectedResultLongValue = -9223372036854775808l; + expectedResultLongValue = -9223372036854775808u; actualResultLongValue = variableTestLongValue.longValue(); ASSERT_EQUAL(expectedResultLongValue , actualResultLongValue); // Test NaN_NUMBER variableTestLongValue = NaN_NUMBER; - expectedResultLongValue = -9223372036854775808l; + expectedResultLongValue = -9223372036854775808u; actualResultLongValue = variableTestLongValue.longValue(); ASSERT_EQUAL(expectedResultLongValue , actualResultLongValue); // Test MAX_VALUE variableTestLongValue = MAX_VALUE; - expectedResultLongValue = -9223372036854775808l; + expectedResultLongValue = -9223372036854775808u; actualResultLongValue = variableTestLongValue.longValue(); ASSERT_EQUAL(expectedResultLongValue , actualResultLongValue); diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index a0bc0e06..9cdcbd95 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -28,3 +28,59 @@ using namespace Java::Lang; + +Thread::Thread() { + this->name = strdup(""); + this->target = nullptr; +} + +Thread::~Thread() { + if (this->name != nullptr) { + free(this->name); + } +} + +void Thread::run() const { + int index = 1; + int limit = 1; + for (; index <= limit; index++) { + std::cout<<"run #"<name = strdup(name); +} + +string Thread::getName() { + return this->name; +} + +// TODO(thoangminh): Need IllegalThreadStateException, method checkAccess, isAlive +void Thread::setDaemon(boolean on) { + this->daemon = on; +} + +boolean Thread::isDaemon() { + return this->daemon; +} + +// TODO(thoangminh): Need class ThreadGroup, IllegalThreadStateException, method checkAccess +void Thread::setPriority(int newPriority) { + if (newPriority > Thread::MAX_PRIORITY) { + newPriority = Thread::MAX_PRIORITY; + } + + if (newPriority < Thread::MIN_PRIORITY) { + newPriority = Thread::MIN_PRIORITY; + } + + this->priority = newPriority; +} + +int Thread::getPriority() { + return this->priority; +} + diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index 15fbabd4..33175e5f 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -36,153 +36,264 @@ namespace Java { namespace Lang { class Thread : public Object, public virtual Runnable { private: - pthread_t original; - boolean isThreadRunning; - - volatile string name; - int priority; - Thread threadQ(); - long eetop; - - /** - * Whether or not to single_step this thread. - */ - boolean single_step; - - /** - * Whether or not the thread is a daemon thread. - */ - boolean daemon = false; - - /** - * JVM state - */ - boolean stillborn = false; - - /** - * What will be run. - */ - Runnable *target; - - // TODO(thoangminh): Need Class ThreadGroup - /** - * The group of this thread - */ + pthread_t original; + boolean isAlive; + + string name; + int priority; + long eetop; + + /** + * Whether or not to single_step this thread. + */ + boolean single_step; + + /** + * Whether or not the thread is a daemon thread. + */ + boolean daemon = false; + + /** + * JVM state + */ + boolean stillborn = false; + + /** + * What will be run. + */ + Runnable *target; + + // TODO(thoangminh): Need Class ThreadGroup + /** + * The group of this thread + */ // ThreadGroup group; - // TODO(thoangminh): Need Class ClassLoader - /** - * The context ClassLoader for this thread - */ + // TODO(thoangminh): Need Class ClassLoader + /** + * The context ClassLoader for this thread + */ // ClassLoader contextClassLoader; - // TODO(thoangminh): Need Class AccessControlContext - /** - * The inherited AccessControlContext of this thread - */ + // TODO(thoangminh): Need Class AccessControlContext + /** + * The inherited AccessControlContext of this thread + */ // AccessControlContext inheritedAccessControlContext; - /** - * For autonumbering anonymous threads. - */ - static int threadInitNumber; - - // TODO(thoangminh): Need Class ThreadLocal - /** - * ThreadLocal values pertaining to this thread. - * This map is maintained - * by the ThreadLocal class. - */ + /** + * For autonumbering anonymous threads. + */ + static int threadInitNumber; + + // TODO(thoangminh): Need Class ThreadLocal + /** + * ThreadLocal values pertaining to this thread. + * This map is maintained + * by the ThreadLocal class. + */ // ThreadLocal.ThreadLocalMap threadLocals = null; - // TODO(thoangminh): Need Class ThreadLocal - /** - * InheritableThreadLocal values pertaining to this thread. - * This map is maintained by - * the InheritableThreadLocal class. - */ + // TODO(thoangminh): Need Class ThreadLocal + /** + * InheritableThreadLocal values pertaining to this thread. + * This map is maintained by + * the InheritableThreadLocal class. + */ // ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; - /** - * The requested stack size for this thread, or 0 if the creator did - * not specify a stack size. It is up to the VM to do - * whatever it likes with this number; some VMs will ignore it. * - */ - long stackSize; - - /** - * JVM-private state that persists after native thread termination. - */ - long nativeParkEventPointer; - - /** - * Thread ID - */ - long tid; - - /** - * For generating thread ID - */ - static long threadSeqNumber; - - /** - * Java thread status for tools, - * initialized to indicate thread 'not yet started' - */ - volatile int threadStatus = 0; - - // TODO(thoangminh): Need Class Interruptible - /** - * The object in which this thread is blocked in an interruptible I/O - * operation, if any. The blocker's interrupt method should be invoked - * after setting this thread's interrupt status. - */ -// volatile Interruptible blocker; -// const Object blockerLock = new Object(); + /** + * The requested stack size for this thread, or 0 if the creator did + * not specify a stack size. It is up to the VM to do + * whatever it likes with this number; some VMs will ignore it. * + */ + long stackSize; + + /** + * JVM-private state that persists after native thread termination. + */ + long nativeParkEventPointer; + + /** + * Thread ID + */ + long tid; + + /** + * For generating thread ID + */ + static long threadSeqNumber; + + /** + * Java thread status for tools, + * initialized to indicate thread 'not yet started' + */ + volatile int threadStatus = 0; + + // TODO(thoangminh): Need Class Interruptible + /** + * The object in which this thread is blocked in an interruptible I/O + * operation, if any. The blocker's interrupt method should be invoked + * after setting this thread's interrupt status. + */ +// volatile Interruptible blocker; +// const Object blockerLock = new Object(); + private: + /** + * Initializes a Thread. + * + * @param g the Thread group + * @param target the object whose run() method gets called + * @param name the name of the new Thread + * @param stackSize the desired stack size for the new thread, or + * zero to indicate that this parameter is to be ignored. + * @param acc the AccessControlContext to inherit, or + * AccessController.getContext() if null + */ + // void init(ThreadGroup g, Runnable target, String name, + // long stackSize, AccessControlContext acc); + + /** + * Initializes a Thread. + * + * @param target the object whose run() method gets called + * @param name the name of the new Thread + * @param stackSize the desired stack size for the new thread, or + * zero to indicate that this parameter is to be ignored. + */ + void init(Runnable &target, String name, long stackSize); public: - /** - * The minimum priority that a thread can have. - */ - static int const MIN_PRIORITY = 1; + /** + * The minimum priority that a thread can have. + */ + static int const MIN_PRIORITY = 1; - /** - * The default priority that is assigned to a thread. - */ - static int const NORM_PRIORITY = 5; + /** + * The default priority that is assigned to a thread. + */ + static int const NORM_PRIORITY = 5; - /** - * The maximum priority that a thread can have. - */ - static int const MAX_PRIORITY = 10; + /** + * The maximum priority that a thread can have. + */ + static int const MAX_PRIORITY = 10; public: - void *pthread_run(void *context) { - ((Thread *) (context))->target->run(); - } - - static void *pthread_helper(void *context) { - return ((Thread *) (context))->pthread_run(context); - } - + void *pthread_run(void *context) { + ((Thread *) (context))->target->run(); + } + + static void *pthread_helper(void *context) { + return ((Thread *) (context))->pthread_run(context); + } + public: - Thread(); - Thread(Runnable &target); - Thread(String name); -// Thread(Runnable target, AccessControlContext acc); -// Thread(ThreadGroup group, Runnable target); -// Thread(ThreadGroup group, String name); - Thread(Runnable &target, String name); -// Thread(ThreadGroup group, Runnable target -// , String name, long stackSize); -// Thread(ThreadGroup group, Runnable target, String name); - ~Thread(); + Thread(); +// Thread(Runnable &target); +// Thread(String name); +// Thread(Runnable target, AccessControlContext acc); +// Thread(ThreadGroup group, Runnable target); +// Thread(ThreadGroup group, String name); +// Thread(Runnable &target, String name); +// Thread(ThreadGroup group, Runnable target +// , String name, long stackSize); +// Thread(ThreadGroup group, Runnable target, String name); + ~Thread(); public: - void run() const; - }; - } // namespace Lang + void run() const; + + // TODO(thoangminh): Set synchronized for this method + /** + * Changes the name of this thread to be equal to the argument + * name. + * + * First the checkAccess method of this thread is called + * with no arguments. This may result in throwing a + * SecurityException. + * + * @param name the new name for this thread. + * @exception SecurityException if the current thread cannot modify this + * thread. + * @see #getName + * @see #checkAccess() + */ + void setName(string name); + + /** + * Returns this thread's name. + * + * @return this thread's name. + * @see #setName(String) + */ + string getName(); + + /** + * Tests if this thread is a daemon thread. + * + * @return true if this thread is a daemon thread; + * false otherwise. + * @see #setDaemon(boolean) + */ + boolean isDaemon() ; + + /** + * Marks this thread as either a {#isDaemon daemon} thread + * or a user thread. The Java Virtual Machine exits when the only + * threads running are all daemon threads. + * + * This method must be invoked before the thread is started. + * + * @param on + * if {true}, marks this thread as a daemon thread + * + * @throws IllegalThreadStateException + * if this thread is {#isAlive alive} + * + * @throws SecurityException + * if {#checkAccess} determines that the current + * thread cannot modify this thread + */ + void setDaemon(boolean on); + + /** + * Changes the priority of this thread. + * + * First the checkAccess method of this thread is called + * with no arguments. This may result in throwing a + * SecurityException. + * + * Otherwise, the priority of this thread is set to the smaller of + * the specified newPriority and the maximum permitted + * priority of the thread's thread group. + * + * @param newPriority priority to set this thread to + * @exception IllegalArgumentException If the priority is not in the + * range MIN_PRIORITY to + * MAX_PRIORITY. + * @exception SecurityException if the current thread cannot modify + * this thread. + * @see #getPriority + * @see #checkAccess() + * @see #getThreadGroup() + * @see #MAX_PRIORITY + * @see #MIN_PRIORITY + * @see ThreadGroup#getMaxPriority() + */ + void setPriority(int newPriority); + + /** + * Returns this thread's priority. + * + * @return this thread's priority. + * @see #setPriority + */ + int getPriority(); + + }; + } // namespace Lang } // namespace Java #endif // JAVA_LANG_THREAD_THREAD_HPP_ \ No newline at end of file diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 73dad5b6..09cf7091 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -49,3 +49,90 @@ class RunnableTarget2 : public virtual Runnable { } } }; + +TEST(JavaLang, ThreadConstructor) { + Thread thread; +} + +TEST(JavaLang, ThreadRun) { + Thread thread; + + thread.run(); +} + +TEST(JavaLang, ThreadSetDaemon) { + Thread thread; + + thread.setDaemon(true); + ASSERT_TRUE(thread.isDaemon()); + + thread.setDaemon(false); + ASSERT_FALSE(thread.isDaemon()); +} + +TEST(JavaLang, ThreadIsDaemon) { + Thread thread; + + thread.setDaemon(true); + ASSERT_TRUE(thread.isDaemon()); + + thread.setDaemon(false); + ASSERT_FALSE(thread.isDaemon()); +} + +TEST(JavaLang, ThreadSetPriority) { + Thread thread; + + thread.setPriority(-1); + ASSERT_EQUAL(1, thread.getPriority()); + + thread.setPriority(0); + ASSERT_EQUAL(1, thread.getPriority()); + + thread.setPriority(3); + ASSERT_EQUAL(3, thread.getPriority()); + + thread.setPriority(Thread::MIN_PRIORITY); + ASSERT_EQUAL(1, thread.getPriority()); + + thread.setPriority(Thread::NORM_PRIORITY); + ASSERT_EQUAL(5, thread.getPriority()); + + thread.setPriority(Thread::MAX_PRIORITY); + ASSERT_EQUAL(10, thread.getPriority()); +} + +TEST(JavaLang, ThreadGetPriority) { + Thread thread; + + thread.setPriority(-1); + ASSERT_EQUAL(1, thread.getPriority()); + + thread.setPriority(0); + ASSERT_EQUAL(1, thread.getPriority()); + + thread.setPriority(3); + ASSERT_EQUAL(3, thread.getPriority()); + + thread.setPriority(Thread::MIN_PRIORITY); + ASSERT_EQUAL(1, thread.getPriority()); + + thread.setPriority(Thread::NORM_PRIORITY); + ASSERT_EQUAL(5, thread.getPriority()); + + thread.setPriority(Thread::MAX_PRIORITY); + ASSERT_EQUAL(10, thread.getPriority()); +} + +TEST(JavaLang, ThreadSetName) { + Thread thread; + + thread.setName(static_cast ("Thread 1")); + ASSERT_STR(static_cast ("Thread 1"), thread.getName()); + + thread.setName(static_cast ("Thread 2")); + ASSERT_STR(static_cast ("Thread 2"), thread.getName()); + + thread.setName(static_cast ("Thread 5")); + ASSERT_NOT_STR(static_cast ("Thread 1"), thread.getName()); +} \ No newline at end of file diff --git a/kernel/test.h b/kernel/test.h index 09219560..4f3923bd 100755 --- a/kernel/test.h +++ b/kernel/test.h @@ -116,6 +116,9 @@ void CTEST_ERR(const char *fmt, ...); // doesn't return void assert_str(const char *exp, const char *real, const char *caller, int line); #define ASSERT_STR(exp, real) assert_str(exp, real, __FILE__, __LINE__) +void assert_not_str(const char *exp, const char *real, const char *caller, int line); +#define ASSERT_NOT_STR(exp, real) assert_not_str(exp, real, __FILE__, __LINE__) + void assert_data(const unsigned char *exp, size_t expsize, const unsigned char *real, size_t realsize, const char *caller, int line); @@ -283,6 +286,14 @@ void assert_str(const char* exp, const char* real, const char* caller, int line } } +void assert_not_str(const char* exp, const char* real, const char* caller, int line) { + if ((exp == NULL && real != NULL) || + (exp != NULL && real == NULL) || + (exp && real && strcmp(exp, real) == 0)) { + CTEST_ERR("%s:%d\nEXPECTED\n'%s'\nACTUAL \n'%s'\n", caller, line, exp, real); + } +} + void assert_data(const unsigned char* exp, size_t expsize, const unsigned char* real, size_t realsize, const char* caller, int line) { From 677eb3ee204283bcce535de7cde9b1dc63bdaa78 Mon Sep 17 00:00:00 2001 From: Truong Hoang Minh Date: Sat, 19 Aug 2017 20:10:43 +0700 Subject: [PATCH 03/41] #231 Edited constructor. Added test + Built Init(), setName(), getName(). --- java/lang/Thread/Thread.cpp | 32 ++++++++++++++++++++++---------- java/lang/Thread/Thread.hpp | 22 ++++++++++++++++------ java/lang/Thread/ThreadTest.cpp | 31 ++++++++++++++++++++++++------- 3 files changed, 62 insertions(+), 23 deletions(-) diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index 9cdcbd95..eb79caee 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -28,17 +28,14 @@ using namespace Java::Lang; +int Thread::threadInitNumber = 0; +long Thread::threadSeqNumber = 0; Thread::Thread() { - this->name = strdup(""); - this->target = nullptr; + init(nullptr, "Thread - " + Thread::nextThreadNum(), 0); } -Thread::~Thread() { - if (this->name != nullptr) { - free(this->name); - } -} +Thread::~Thread() = default; void Thread::run() const { int index = 1; @@ -50,11 +47,19 @@ void Thread::run() const { } // TODO(thoangminh): Need method checkAccess, threadStatus, setNativeName -void Thread::setName(string name) { - this->name = strdup(name); +void Thread::setName(String name) { + this->name = name; } -string Thread::getName() { +void Thread::init(Runnable *target, String name, long stackSize) { + this->target = target; + this->name = name; + this->stackSize = stackSize; + + this->tid = nextThreadID(); +} + +String Thread::getName() { return this->name; } @@ -84,3 +89,10 @@ int Thread::getPriority() { return this->priority; } +int Thread::nextThreadNum() { + return threadInitNumber++; +} + +long Thread::nextThreadID() { + ++threadSeqNumber; +}; \ No newline at end of file diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index 33175e5f..2dfde912 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -31,6 +31,8 @@ #include "../Object/Object.hpp" #include "../String/String.hpp" #include "../Runnable/Runnable.hpp" +#include +#define synchronized(m) for(std::unique_lock lk(m); lk; lk.unlock()); namespace Java { namespace Lang { @@ -39,7 +41,7 @@ namespace Java { pthread_t original; boolean isAlive; - string name; + String name; int priority; long eetop; @@ -154,6 +156,7 @@ namespace Java { // void init(ThreadGroup g, Runnable target, String name, // long stackSize, AccessControlContext acc); + // TODO(thoangminh): Need to improve this medthod /** * Initializes a Thread. * @@ -162,7 +165,13 @@ namespace Java { * @param stackSize the desired stack size for the new thread, or * zero to indicate that this parameter is to be ignored. */ - void init(Runnable &target, String name, long stackSize); + void init(Runnable *target, String name, long stackSize); + + // TODO(thoangminh): Set synchronized for this method + static int nextThreadNum(); + + // TODO(thoangminh): Set synchronized for this method + static long nextThreadID(); public: /** @@ -203,7 +212,7 @@ namespace Java { ~Thread(); public: - void run() const; + void run() const override ; // TODO(thoangminh): Set synchronized for this method /** @@ -220,7 +229,7 @@ namespace Java { * @see #getName * @see #checkAccess() */ - void setName(string name); + void setName(String name); /** * Returns this thread's name. @@ -228,7 +237,7 @@ namespace Java { * @return this thread's name. * @see #setName(String) */ - string getName(); + String getName(); /** * Tests if this thread is a daemon thread. @@ -296,4 +305,5 @@ namespace Java { } // namespace Lang } // namespace Java -#endif // JAVA_LANG_THREAD_THREAD_HPP_ \ No newline at end of file +#endif // JAVA_LANG_THREAD_THREAD_HPP_ + diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 09cf7091..a9384dd3 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -50,6 +50,7 @@ class RunnableTarget2 : public virtual Runnable { } }; +// TODO(thoangminh): Need to improve it TEST(JavaLang, ThreadConstructor) { Thread thread; } @@ -127,12 +128,28 @@ TEST(JavaLang, ThreadGetPriority) { TEST(JavaLang, ThreadSetName) { Thread thread; - thread.setName(static_cast ("Thread 1")); - ASSERT_STR(static_cast ("Thread 1"), thread.getName()); + String name = "Thread 1"; + thread.setName(name); + ASSERT_STR((string) "Thread 1", thread.getName().toString()); - thread.setName(static_cast ("Thread 2")); - ASSERT_STR(static_cast ("Thread 2"), thread.getName()); + thread.setName((string) "Thread 2"); + ASSERT_STR((string) "Thread 2", thread.getName().toString()); + + thread.setName((string) "Thread 5"); + ASSERT_NOT_STR((string) "Thread 1", thread.getName().toString()); +} + +TEST(JavaLang, ThreadGetName) { + Thread thread; + + String name = "Thread 1"; + thread.setName(name); + ASSERT_STR((string) "Thread 1", thread.getName().toString()); + + thread.setName((string) "Thread 2"); + ASSERT_STR((string) "Thread 2", thread.getName().toString()); + + thread.setName((string) "Thread 5"); + ASSERT_NOT_STR((string) "Thread 1", thread.getName().toString()); +} - thread.setName(static_cast ("Thread 5")); - ASSERT_NOT_STR(static_cast ("Thread 1"), thread.getName()); -} \ No newline at end of file From 0071038785e52353fdf0870becaf2099522276f9 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Mon, 28 Aug 2017 23:49:04 +0700 Subject: [PATCH 04/41] #231 Implement Semaphore, Thread::join() --- CMakeLists.txt | 1 + java/lang/Runnable/Runnable.hpp | 2 +- java/lang/Thread/Thread.cpp | 98 ++++++++++++++++++++++++++---- java/lang/Thread/Thread.hpp | 44 +++++++++++--- java/lang/Thread/ThreadTest.cpp | 102 ++++++++++++++++++++++++++------ 5 files changed, 211 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e9a9d929..65f4ffcb 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ include(GNUInstallDirs) # Force Linux and Darwin use GCC set(CMAKE_C_COMPILER "gcc") set(CMAKE_CXX_COMPILER "g++") +set(CMAKE_CXX_FLAGS "-pthread") # Check C++ compiler version include(CheckCXXCompilerFlag) diff --git a/java/lang/Runnable/Runnable.hpp b/java/lang/Runnable/Runnable.hpp index aca6347a..afe55180 100755 --- a/java/lang/Runnable/Runnable.hpp +++ b/java/lang/Runnable/Runnable.hpp @@ -31,7 +31,7 @@ namespace Java { namespace Lang { class Runnable { public: - virtual void run() const = 0; + virtual void run() = 0; }; } } diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index eb79caee..1f091928 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -35,15 +35,35 @@ Thread::Thread() { init(nullptr, "Thread - " + Thread::nextThreadNum(), 0); } -Thread::~Thread() = default; - -void Thread::run() const { - int index = 1; - int limit = 1; - for (; index <= limit; index++) { - std::cout<<"run #"<joinable()) + threadObject->join(); + delete threadObject; } + + if(this->semaphoreObject) { + delete this->semaphoreObject; + } +} + +void Thread::run() { + mutexObject.lock(); + alive = true; + mutexObject.unlock(); + + target->run(); + if(semaphoreObject) { + semaphoreObject->release(1, NULL); + } + + mutexObject.lock(); + alive = false; + mutexObject.unlock(); } // TODO(thoangminh): Need method checkAccess, threadStatus, setNativeName @@ -55,8 +75,9 @@ void Thread::init(Runnable *target, String name, long stackSize) { this->target = target; this->name = name; this->stackSize = stackSize; - this->tid = nextThreadID(); + this->threadObject = NULL; + this->semaphoreObject = new Semaphore(0, 1); } String Thread::getName() { @@ -68,6 +89,11 @@ void Thread::setDaemon(boolean on) { this->daemon = on; } +boolean Thread::isAlive() { + std::unique_lock locker(mutexObject); + return alive; +} + boolean Thread::isDaemon() { return this->daemon; } @@ -95,4 +121,56 @@ int Thread::nextThreadNum() { long Thread::nextThreadID() { ++threadSeqNumber; -}; \ No newline at end of file +} + +void Thread::start() { + if(target && !isAlive()) { + threadObject = new std::thread(&Thread::run, this); + } +} + +void Thread::join() { + join(0); +} + +void Thread::join(long millis) { + if(millis > 0) { + semaphoreObject->wait(millis); + } else { + semaphoreObject->wait(); + } +} + +Semaphore::Semaphore(long initCount, long maxCount) { + this->count = initCount; + this->maxCount = maxCount; +} + +Semaphore::~Semaphore() { + +} + +void Semaphore::release(long releaseCount, long* previousCount) { + std::unique_lock locker(mutexObject); + if(previousCount) + *previousCount = count; + count += releaseCount; + count = std::max(count, maxCount); + conditionObject.notify_one(); +} + +void Semaphore::wait() { + wait(-1); +} + +void Semaphore::wait(long millis) { + std::unique_lock locker(mutexObject); + if(millis < 0) { + if(count == 0) + conditionObject.wait(locker); + --count; + } else { + if(count == 0 && conditionObject.wait_for(locker, std::chrono::milliseconds(millis)) != std::cv_status::timeout) + --count; + } +} diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index 2dfde912..c41f57bf 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -27,19 +27,37 @@ #ifndef JAVA_LANG_THREAD_THREAD_HPP_ #define JAVA_LANG_THREAD_THREAD_HPP_ -#include #include "../Object/Object.hpp" #include "../String/String.hpp" #include "../Runnable/Runnable.hpp" #include +#include +#include +#include + #define synchronized(m) for(std::unique_lock lk(m); lk; lk.unlock()); namespace Java { namespace Lang { - class Thread : public Object, public virtual Runnable { + class Semaphore { + public: + Semaphore(long initCount, long maxCount); + ~Semaphore(); + + void release(long releaseCount, long* previousCount); + void wait(); + void wait(long millis); + private: + std::mutex mutexObject; + std::condition_variable conditionObject; + long maxCount; + long count; + }; + + class Thread : public Object, public virtual Runnable { private: pthread_t original; - boolean isAlive; + boolean alive; String name; int priority; @@ -141,6 +159,10 @@ namespace Java { // volatile Interruptible blocker; // const Object blockerLock = new Object(); + std::thread* threadObject; + std::mutex mutexObject; + Semaphore* semaphoreObject; + private: /** * Initializes a Thread. @@ -153,8 +175,7 @@ namespace Java { * @param acc the AccessControlContext to inherit, or * AccessController.getContext() if null */ - // void init(ThreadGroup g, Runnable target, String name, - // long stackSize, AccessControlContext acc); +// void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc); // TODO(thoangminh): Need to improve this medthod /** @@ -200,19 +221,19 @@ namespace Java { public: Thread(); + Thread(Runnable* target); // Thread(Runnable &target); // Thread(String name); // Thread(Runnable target, AccessControlContext acc); // Thread(ThreadGroup group, Runnable target); // Thread(ThreadGroup group, String name); // Thread(Runnable &target, String name); -// Thread(ThreadGroup group, Runnable target -// , String name, long stackSize); +// Thread(ThreadGroup group, Runnable target, String name, long stackSize); // Thread(ThreadGroup group, Runnable target, String name); ~Thread(); public: - void run() const override ; + void run() override ; // TODO(thoangminh): Set synchronized for this method /** @@ -239,6 +260,8 @@ namespace Java { */ String getName(); + boolean isAlive(); + /** * Tests if this thread is a daemon thread. * @@ -301,6 +324,11 @@ namespace Java { */ int getPriority(); + void start(); + + void join(); + + void join(long millis); }; } // namespace Lang } // namespace Java diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index a9384dd3..2719442c 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -32,33 +32,41 @@ extern "C" { using namespace Java::Lang; -class RunnableTarget : public virtual Runnable { +class RunnableTarget1 : public virtual Runnable { public: - void run() const { - } -}; + long value; -class RunnableTarget2 : public virtual Runnable { -public: - void run() const { - int index = 0; - int limit = 51; - for (; index <= limit; index++) { - // printf("Index [%d] must not equal to %d to test Thread.stop()\n", index, limit); - usleep(1); - } + RunnableTarget1() { + value = 0; + } + + ~RunnableTarget1() { + + } + + void run() override { + value = 0xb00b; + std::this_thread::sleep_for(std::chrono::seconds(1)); } }; // TODO(thoangminh): Need to improve it TEST(JavaLang, ThreadConstructor) { - Thread thread; } TEST(JavaLang, ThreadRun) { - Thread thread; - - thread.run(); + long expect = 0xb00b; + long result = 0; + + { + RunnableTarget1 target; + Thread thread(&target); + thread.start(); + thread.join(); + result = target.value; + } + + ASSERT_EQUAL(expect, result); } TEST(JavaLang, ThreadSetDaemon) { @@ -153,3 +161,63 @@ TEST(JavaLang, ThreadGetName) { ASSERT_NOT_STR((string) "Thread 1", thread.getName().toString()); } +TEST(JavaLang, ThreadJoinWithTimeout) { + std::chrono::time_point start; + std::chrono::time_point end; + std::chrono::duration elapsed; + + long expect1 = 0xb00b; + long result1 = 0; + double expect2 = 1.0; + double result2 = 0; + + { + RunnableTarget1 target; + Thread thread(&target); + thread.start(); + + start = std::chrono::system_clock::now(); + thread.join(1000); + end = std::chrono::system_clock::now(); + elapsed = end - start; + + thread.join(); + + result1 = target.value; + result2 = elapsed.count(); + } + + ASSERT_EQUAL(expect1, result1); + ASSERT_DBL_NEAR_PRE(expect2, result2, 1); +} + +TEST(JavaLang, Semaphore) { + + Semaphore semObject(0, 1); + + { + long expect = 0; + long result = 0; + semObject.release(1, &result); + semObject.wait(); + ASSERT_EQUAL(expect, result); + } + + { + double expect = 1.0; + double result = 0; + + std::chrono::time_point start; + std::chrono::time_point end; + std::chrono::duration elapsed; + + start = std::chrono::system_clock::now(); + semObject.wait(1000); + end = std::chrono::system_clock::now(); + elapsed = end-start; + result = elapsed.count(); + + ASSERT_DBL_NEAR_PRE(expect, result, 1); + } + +} From 5bfec5bf230d5c470598e8094aef6f4935669dad Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Wed, 30 Aug 2017 21:27:48 +0700 Subject: [PATCH 05/41] #231 Fix test case --- java/lang/Thread/ThreadTest.cpp | 45 +++++---------------------------- 1 file changed, 6 insertions(+), 39 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 2719442c..16c1c1a1 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -46,7 +46,7 @@ class RunnableTarget1 : public virtual Runnable { void run() override { value = 0xb00b; - std::this_thread::sleep_for(std::chrono::seconds(1)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }; @@ -168,56 +168,23 @@ TEST(JavaLang, ThreadJoinWithTimeout) { long expect1 = 0xb00b; long result1 = 0; - double expect2 = 1.0; - double result2 = 0; { RunnableTarget1 target; Thread thread(&target); thread.start(); - - start = std::chrono::system_clock::now(); thread.join(1000); - end = std::chrono::system_clock::now(); - elapsed = end - start; - - thread.join(); - result1 = target.value; - result2 = elapsed.count(); } ASSERT_EQUAL(expect1, result1); - ASSERT_DBL_NEAR_PRE(expect2, result2, 1); } TEST(JavaLang, Semaphore) { - Semaphore semObject(0, 1); - - { - long expect = 0; - long result = 0; - semObject.release(1, &result); - semObject.wait(); - ASSERT_EQUAL(expect, result); - } - - { - double expect = 1.0; - double result = 0; - - std::chrono::time_point start; - std::chrono::time_point end; - std::chrono::duration elapsed; - - start = std::chrono::system_clock::now(); - semObject.wait(1000); - end = std::chrono::system_clock::now(); - elapsed = end-start; - result = elapsed.count(); - - ASSERT_DBL_NEAR_PRE(expect, result, 1); - } - + long expect = 0; + long result = 0; + semObject.release(1, &result); + semObject.wait(); + ASSERT_EQUAL(expect, result); } From 57fcc877891d08bf45ca02cb2d8b70aa26516ca8 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Wed, 30 Aug 2017 21:36:42 +0700 Subject: [PATCH 06/41] #231 Test std::thread --- java/lang/Thread/ThreadTest.cpp | 65 +++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 16c1c1a1..a9a6f3e2 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -50,23 +50,32 @@ class RunnableTarget1 : public virtual Runnable { } }; +void DummyThread() +{ + std::this_thread::sleep_for(std::chrono::milliseconds(100)); +} + // TODO(thoangminh): Need to improve it TEST(JavaLang, ThreadConstructor) { } TEST(JavaLang, ThreadRun) { - long expect = 0xb00b; - long result = 0; - - { - RunnableTarget1 target; - Thread thread(&target); - thread.start(); - thread.join(); - result = target.value; - } - - ASSERT_EQUAL(expect, result); +// long expect = 0xb00b; +// long result = 0; +// +// { +// RunnableTarget1 target; +// Thread thread(&target); +// thread.start(); +// thread.join(); +// result = target.value; +// } +// +// ASSERT_EQUAL(expect, result); + + std::thread dummyThread(DummyThread); + if(dummyThread.joinable()) + dummyThread.join(); } TEST(JavaLang, ThreadSetDaemon) { @@ -162,22 +171,22 @@ TEST(JavaLang, ThreadGetName) { } TEST(JavaLang, ThreadJoinWithTimeout) { - std::chrono::time_point start; - std::chrono::time_point end; - std::chrono::duration elapsed; - - long expect1 = 0xb00b; - long result1 = 0; - - { - RunnableTarget1 target; - Thread thread(&target); - thread.start(); - thread.join(1000); - result1 = target.value; - } - - ASSERT_EQUAL(expect1, result1); +// std::chrono::time_point start; +// std::chrono::time_point end; +// std::chrono::duration elapsed; +// +// long expect1 = 0xb00b; +// long result1 = 0; +// +// { +// RunnableTarget1 target; +// Thread thread(&target); +// thread.start(); +// thread.join(1000); +// result1 = target.value; +// } +// +// ASSERT_EQUAL(expect1, result1); } TEST(JavaLang, Semaphore) { From 88d4bb7df990d12335602372b97a04102f2bf4aa Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Wed, 30 Aug 2017 22:01:35 +0700 Subject: [PATCH 07/41] #231 Remove semaphore --- java/lang/Thread/Thread.cpp | 49 ++++----------------------------- java/lang/Thread/Thread.hpp | 16 ----------- java/lang/Thread/ThreadTest.cpp | 18 ------------ 3 files changed, 5 insertions(+), 78 deletions(-) diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index 1f091928..94834f97 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -45,10 +45,6 @@ Thread::~Thread() { threadObject->join(); delete threadObject; } - - if(this->semaphoreObject) { - delete this->semaphoreObject; - } } void Thread::run() { @@ -57,9 +53,9 @@ void Thread::run() { mutexObject.unlock(); target->run(); - if(semaphoreObject) { - semaphoreObject->release(1, NULL); - } +// if(semaphoreObject) { +// semaphoreObject->release(1, NULL); +// } mutexObject.lock(); alive = false; @@ -77,7 +73,6 @@ void Thread::init(Runnable *target, String name, long stackSize) { this->stackSize = stackSize; this->tid = nextThreadID(); this->threadObject = NULL; - this->semaphoreObject = new Semaphore(0, 1); } String Thread::getName() { @@ -135,42 +130,8 @@ void Thread::join() { void Thread::join(long millis) { if(millis > 0) { - semaphoreObject->wait(millis); - } else { - semaphoreObject->wait(); - } -} - -Semaphore::Semaphore(long initCount, long maxCount) { - this->count = initCount; - this->maxCount = maxCount; -} - -Semaphore::~Semaphore() { - -} - -void Semaphore::release(long releaseCount, long* previousCount) { - std::unique_lock locker(mutexObject); - if(previousCount) - *previousCount = count; - count += releaseCount; - count = std::max(count, maxCount); - conditionObject.notify_one(); -} - -void Semaphore::wait() { - wait(-1); -} - -void Semaphore::wait(long millis) { - std::unique_lock locker(mutexObject); - if(millis < 0) { - if(count == 0) - conditionObject.wait(locker); - --count; + //semaphoreObject->wait(millis); } else { - if(count == 0 && conditionObject.wait_for(locker, std::chrono::milliseconds(millis)) != std::cv_status::timeout) - --count; + //semaphoreObject->wait(); } } diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index c41f57bf..cd1c8979 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -39,21 +39,6 @@ namespace Java { namespace Lang { - class Semaphore { - public: - Semaphore(long initCount, long maxCount); - ~Semaphore(); - - void release(long releaseCount, long* previousCount); - void wait(); - void wait(long millis); - private: - std::mutex mutexObject; - std::condition_variable conditionObject; - long maxCount; - long count; - }; - class Thread : public Object, public virtual Runnable { private: pthread_t original; @@ -161,7 +146,6 @@ namespace Java { std::thread* threadObject; std::mutex mutexObject; - Semaphore* semaphoreObject; private: /** diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index a9a6f3e2..50a67057 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -50,11 +50,6 @@ class RunnableTarget1 : public virtual Runnable { } }; -void DummyThread() -{ - std::this_thread::sleep_for(std::chrono::milliseconds(100)); -} - // TODO(thoangminh): Need to improve it TEST(JavaLang, ThreadConstructor) { } @@ -72,10 +67,6 @@ TEST(JavaLang, ThreadRun) { // } // // ASSERT_EQUAL(expect, result); - - std::thread dummyThread(DummyThread); - if(dummyThread.joinable()) - dummyThread.join(); } TEST(JavaLang, ThreadSetDaemon) { @@ -188,12 +179,3 @@ TEST(JavaLang, ThreadJoinWithTimeout) { // // ASSERT_EQUAL(expect1, result1); } - -TEST(JavaLang, Semaphore) { - Semaphore semObject(0, 1); - long expect = 0; - long result = 0; - semObject.release(1, &result); - semObject.wait(); - ASSERT_EQUAL(expect, result); -} From b56cf71bd2685e1508cc0ffae314c5c6e93e2283 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 17 Sep 2017 21:24:11 +0700 Subject: [PATCH 08/41] #231 Add new Semaphore --- java/lang/Thread/Thread.cpp | 11 +-- java/lang/Thread/Thread.hpp | 13 ++-- java/lang/Thread/ThreadTest.cpp | 82 +++++++++++++------- java/util/Concurrent/Semaphore/Semaphore.cpp | 1 + java/util/Concurrent/Semaphore/Semaphore.hpp | 3 +- 5 files changed, 67 insertions(+), 43 deletions(-) diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index 94834f97..6a10c36b 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -44,6 +44,9 @@ Thread::~Thread() { if (threadObject->joinable()) threadObject->join(); delete threadObject; + + if (semahoreObject.availablePermits() > 0) + semahoreObject.release(semahoreObject.availablePermits()); } } @@ -53,9 +56,7 @@ void Thread::run() { mutexObject.unlock(); target->run(); -// if(semaphoreObject) { -// semaphoreObject->release(1, NULL); -// } + semahoreObject.release(1); mutexObject.lock(); alive = false; @@ -130,8 +131,8 @@ void Thread::join() { void Thread::join(long millis) { if(millis > 0) { - //semaphoreObject->wait(millis); + semahoreObject.tryAcquire(1, millis); } else { - //semaphoreObject->wait(); + semahoreObject.acquire(); } } diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index cd1c8979..7b06fc3c 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -27,20 +27,18 @@ #ifndef JAVA_LANG_THREAD_THREAD_HPP_ #define JAVA_LANG_THREAD_THREAD_HPP_ -#include "../Object/Object.hpp" -#include "../String/String.hpp" -#include "../Runnable/Runnable.hpp" #include #include -#include -#include -#define synchronized(m) for(std::unique_lock lk(m); lk; lk.unlock()); +#include "../Object/Object.hpp" +#include "../String/String.hpp" +#include "../Runnable/Runnable.hpp" +#include "../../util/Concurrent/Semaphore/Semaphore.hpp" namespace Java { namespace Lang { class Thread : public Object, public virtual Runnable { - private: + private: pthread_t original; boolean alive; @@ -146,6 +144,7 @@ namespace Java { std::thread* threadObject; std::mutex mutexObject; + Java::Util::Concurrent::Semaphore semahoreObject; private: /** diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 50a67057..cf2d7f39 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -46,27 +46,46 @@ class RunnableTarget1 : public virtual Runnable { void run() override { value = 0xb00b; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } }; +class RunnableTarget2 : public virtual Runnable { +public: + long value; + + RunnableTarget2() { + value = 0; + } + + ~RunnableTarget2() { + + } + + void run() override { + value = 0xb00b; + std::this_thread::sleep_for(std::chrono::milliseconds(5000)); + value = 0xbeef; + } +}; + // TODO(thoangminh): Need to improve it TEST(JavaLang, ThreadConstructor) { } TEST(JavaLang, ThreadRun) { -// long expect = 0xb00b; -// long result = 0; -// -// { -// RunnableTarget1 target; -// Thread thread(&target); -// thread.start(); -// thread.join(); -// result = target.value; -// } -// -// ASSERT_EQUAL(expect, result); + long expect = 0xb00b; + long result = 0; + + { + RunnableTarget1 target; + Thread thread(&target); + thread.start(); + thread.join(); + result = target.value; + } + + ASSERT_EQUAL(expect, result); } TEST(JavaLang, ThreadSetDaemon) { @@ -162,20 +181,25 @@ TEST(JavaLang, ThreadGetName) { } TEST(JavaLang, ThreadJoinWithTimeout) { -// std::chrono::time_point start; -// std::chrono::time_point end; -// std::chrono::duration elapsed; -// -// long expect1 = 0xb00b; -// long result1 = 0; -// -// { -// RunnableTarget1 target; -// Thread thread(&target); -// thread.start(); -// thread.join(1000); -// result1 = target.value; -// } -// -// ASSERT_EQUAL(expect1, result1); + long expect1 = 0xb00b; + long result1 = 0; + long expect2 = 0xbeef; + long result2 = 0; + + { + RunnableTarget2 target; + Thread thread(&target); + thread.start(); + + // + thread.join(1000); + result1 = target.value; + + // + thread.join(); + result2 = target.value; + } + + ASSERT_EQUAL(expect1, result1); + ASSERT_EQUAL(expect2, result2); } diff --git a/java/util/Concurrent/Semaphore/Semaphore.cpp b/java/util/Concurrent/Semaphore/Semaphore.cpp index 433bb6e2..c38bb361 100644 --- a/java/util/Concurrent/Semaphore/Semaphore.cpp +++ b/java/util/Concurrent/Semaphore/Semaphore.cpp @@ -25,6 +25,7 @@ */ #include "Semaphore.hpp" +#include "../../../lang/IllegalArgumentException/IllegalArgumentException.hpp" using namespace std::chrono; diff --git a/java/util/Concurrent/Semaphore/Semaphore.hpp b/java/util/Concurrent/Semaphore/Semaphore.hpp index 9379497e..56aa55b3 100644 --- a/java/util/Concurrent/Semaphore/Semaphore.hpp +++ b/java/util/Concurrent/Semaphore/Semaphore.hpp @@ -27,8 +27,7 @@ #ifndef JAVA_UTIL_CONCURRENT_SEMAPHORE_SEMAPHORE_HPP_ #define JAVA_UTIL_CONCURRENT_SEMAPHORE_SEMAPHORE_HPP_ -#include "../../../Lang.hpp" -#include "../../../lang/IllegalArgumentException/IllegalArgumentException.hpp" +#include "../../../lang/String/String.hpp" #include #include From 358a395e50784d91c5239515f060f550c5e3e1bc Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 17 Sep 2017 21:37:55 +0700 Subject: [PATCH 09/41] #231 Try decreasing sleep time --- java/lang/Thread/ThreadTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index cf2d7f39..0616b02e 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -64,7 +64,7 @@ class RunnableTarget2 : public virtual Runnable { void run() override { value = 0xb00b; - std::this_thread::sleep_for(std::chrono::milliseconds(5000)); + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); value = 0xbeef; } }; @@ -192,7 +192,7 @@ TEST(JavaLang, ThreadJoinWithTimeout) { thread.start(); // - thread.join(1000); + thread.join(100); result1 = target.value; // From 1f584a9582eb2811a9d72b4faaac88ff23491da6 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 17 Sep 2017 21:54:47 +0700 Subject: [PATCH 10/41] #231 Comment join testcase --- java/lang/Thread/ThreadTest.cpp | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 0616b02e..36d0177d 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -181,25 +181,25 @@ TEST(JavaLang, ThreadGetName) { } TEST(JavaLang, ThreadJoinWithTimeout) { - long expect1 = 0xb00b; - long result1 = 0; - long expect2 = 0xbeef; - long result2 = 0; - - { - RunnableTarget2 target; - Thread thread(&target); - thread.start(); - - // - thread.join(100); - result1 = target.value; - - // - thread.join(); - result2 = target.value; - } - - ASSERT_EQUAL(expect1, result1); - ASSERT_EQUAL(expect2, result2); +// long expect1 = 0xb00b; +// long result1 = 0; +// long expect2 = 0xbeef; +// long result2 = 0; +// +// { +// RunnableTarget2 target; +// Thread thread(&target); +// thread.start(); +// +// // +// thread.join(100); +// result1 = target.value; +// +// // +// thread.join(); +// result2 = target.value; +// } +// +// ASSERT_EQUAL(expect1, result1); +// ASSERT_EQUAL(expect2, result2); } From c51c8d4a2b36f9dd8e1ac0681b8bf4926621edfe Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 17 Sep 2017 22:09:03 +0700 Subject: [PATCH 11/41] #231 Uncomment testcase, comment destructor --- java/lang/Thread/Thread.cpp | 4 ++-- java/lang/Thread/ThreadTest.cpp | 42 ++++++++++++++++----------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index 6a10c36b..d0b5e59e 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -45,8 +45,8 @@ Thread::~Thread() { threadObject->join(); delete threadObject; - if (semahoreObject.availablePermits() > 0) - semahoreObject.release(semahoreObject.availablePermits()); +// if (semahoreObject.availablePermits() > 0) +// semahoreObject.release(semahoreObject.availablePermits()); } } diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 36d0177d..0616b02e 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -181,25 +181,25 @@ TEST(JavaLang, ThreadGetName) { } TEST(JavaLang, ThreadJoinWithTimeout) { -// long expect1 = 0xb00b; -// long result1 = 0; -// long expect2 = 0xbeef; -// long result2 = 0; -// -// { -// RunnableTarget2 target; -// Thread thread(&target); -// thread.start(); -// -// // -// thread.join(100); -// result1 = target.value; -// -// // -// thread.join(); -// result2 = target.value; -// } -// -// ASSERT_EQUAL(expect1, result1); -// ASSERT_EQUAL(expect2, result2); + long expect1 = 0xb00b; + long result1 = 0; + long expect2 = 0xbeef; + long result2 = 0; + + { + RunnableTarget2 target; + Thread thread(&target); + thread.start(); + + // + thread.join(100); + result1 = target.value; + + // + thread.join(); + result2 = target.value; + } + + ASSERT_EQUAL(expect1, result1); + ASSERT_EQUAL(expect2, result2); } From ad7f32a3288fbcd027187b157372b7cd8757b326 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 17 Sep 2017 22:26:36 +0700 Subject: [PATCH 12/41] #231 Comment testcase & destructor --- java/lang/Thread/ThreadTest.cpp | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 0616b02e..36d0177d 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -181,25 +181,25 @@ TEST(JavaLang, ThreadGetName) { } TEST(JavaLang, ThreadJoinWithTimeout) { - long expect1 = 0xb00b; - long result1 = 0; - long expect2 = 0xbeef; - long result2 = 0; - - { - RunnableTarget2 target; - Thread thread(&target); - thread.start(); - - // - thread.join(100); - result1 = target.value; - - // - thread.join(); - result2 = target.value; - } - - ASSERT_EQUAL(expect1, result1); - ASSERT_EQUAL(expect2, result2); +// long expect1 = 0xb00b; +// long result1 = 0; +// long expect2 = 0xbeef; +// long result2 = 0; +// +// { +// RunnableTarget2 target; +// Thread thread(&target); +// thread.start(); +// +// // +// thread.join(100); +// result1 = target.value; +// +// // +// thread.join(); +// result2 = target.value; +// } +// +// ASSERT_EQUAL(expect1, result1); +// ASSERT_EQUAL(expect2, result2); } From 134302a09e137990741b27e7785d3127846d65fa Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 17 Sep 2017 22:35:08 +0700 Subject: [PATCH 13/41] #231 Comment testcase --- java/lang/Thread/ThreadTest.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 36d0177d..576f12eb 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -74,18 +74,18 @@ TEST(JavaLang, ThreadConstructor) { } TEST(JavaLang, ThreadRun) { - long expect = 0xb00b; - long result = 0; - - { - RunnableTarget1 target; - Thread thread(&target); - thread.start(); - thread.join(); - result = target.value; - } - - ASSERT_EQUAL(expect, result); +// long expect = 0xb00b; +// long result = 0; +// +// { +// RunnableTarget1 target; +// Thread thread(&target); +// thread.start(); +// thread.join(); +// result = target.value; +// } +// +// ASSERT_EQUAL(expect, result); } TEST(JavaLang, ThreadSetDaemon) { From 44d93e4be17babfcd64b7a6afa8f1d2e1ed5d534 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Mon, 18 Sep 2017 21:02:57 +0700 Subject: [PATCH 14/41] #231 Try fixing crash --- java/lang/Thread/Thread.cpp | 15 +++++---------- java/lang/Thread/Thread.hpp | 2 +- java/lang/Thread/ThreadTest.cpp | 24 ++++++++++++------------ 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index d0b5e59e..c5056063 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -40,14 +40,10 @@ Thread::Thread(Runnable *target) { } Thread::~Thread() { - if(threadObject) { - if (threadObject->joinable()) - threadObject->join(); - delete threadObject; - -// if (semahoreObject.availablePermits() > 0) -// semahoreObject.release(semahoreObject.availablePermits()); - } + if (threadObject.joinable()) + threadObject.join(); + if (semahoreObject.availablePermits() > 0) + semahoreObject.release(semahoreObject.availablePermits()); } void Thread::run() { @@ -73,7 +69,6 @@ void Thread::init(Runnable *target, String name, long stackSize) { this->name = name; this->stackSize = stackSize; this->tid = nextThreadID(); - this->threadObject = NULL; } String Thread::getName() { @@ -121,7 +116,7 @@ long Thread::nextThreadID() { void Thread::start() { if(target && !isAlive()) { - threadObject = new std::thread(&Thread::run, this); + threadObject = std::move(std::thread(&Thread::run, this)); } } diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index 7b06fc3c..fb448a72 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -142,7 +142,7 @@ namespace Java { // volatile Interruptible blocker; // const Object blockerLock = new Object(); - std::thread* threadObject; + std::thread threadObject; std::mutex mutexObject; Java::Util::Concurrent::Semaphore semahoreObject; diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 576f12eb..36d0177d 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -74,18 +74,18 @@ TEST(JavaLang, ThreadConstructor) { } TEST(JavaLang, ThreadRun) { -// long expect = 0xb00b; -// long result = 0; -// -// { -// RunnableTarget1 target; -// Thread thread(&target); -// thread.start(); -// thread.join(); -// result = target.value; -// } -// -// ASSERT_EQUAL(expect, result); + long expect = 0xb00b; + long result = 0; + + { + RunnableTarget1 target; + Thread thread(&target); + thread.start(); + thread.join(); + result = target.value; + } + + ASSERT_EQUAL(expect, result); } TEST(JavaLang, ThreadSetDaemon) { From dc38f7817b143bd399eaa703592c62dcce50cb9a Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Mon, 18 Sep 2017 22:08:40 +0700 Subject: [PATCH 15/41] #231 Try fixing crash --- java/lang/Thread/ThreadTest.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 36d0177d..cabde2d9 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -76,15 +76,16 @@ TEST(JavaLang, ThreadConstructor) { TEST(JavaLang, ThreadRun) { long expect = 0xb00b; long result = 0; + RunnableTarget1* target = new RunnableTarget1(); { - RunnableTarget1 target; - Thread thread(&target); + Thread thread(target); thread.start(); thread.join(); - result = target.value; + result = target->value; } + delete target; ASSERT_EQUAL(expect, result); } From 60e84c19bff4ca1dbc9947753277d906e244aa50 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Mon, 18 Sep 2017 23:14:32 +0700 Subject: [PATCH 16/41] #231 Add class field init --- java/lang/Thread/Thread.cpp | 5 +++-- java/lang/Thread/Thread.hpp | 6 ++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index c5056063..d15e2ae2 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -25,6 +25,7 @@ */ #include "Thread.hpp" +#include using namespace Java::Lang; @@ -115,7 +116,7 @@ long Thread::nextThreadID() { } void Thread::start() { - if(target && !isAlive()) { + if (target && !isAlive()) { threadObject = std::move(std::thread(&Thread::run, this)); } } @@ -125,7 +126,7 @@ void Thread::join() { } void Thread::join(long millis) { - if(millis > 0) { + if (millis > 0) { semahoreObject.tryAcquire(1, millis); } else { semahoreObject.acquire(); diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index fb448a72..5b00423a 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -39,12 +39,10 @@ namespace Java { namespace Lang { class Thread : public Object, public virtual Runnable { private: - pthread_t original; - boolean alive; + boolean alive = false; String name; int priority; - long eetop; /** * Whether or not to single_step this thread. @@ -64,7 +62,7 @@ namespace Java { /** * What will be run. */ - Runnable *target; + Runnable *target = NULL; // TODO(thoangminh): Need Class ThreadGroup /** From 53f89ce68199debd9cf0f46299a7d914561a94ab Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Mon, 18 Sep 2017 23:40:04 +0700 Subject: [PATCH 17/41] #231 Uncomment thread::join() testcase --- java/lang/Thread/ThreadTest.cpp | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index cabde2d9..84b3cfcb 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -182,25 +182,25 @@ TEST(JavaLang, ThreadGetName) { } TEST(JavaLang, ThreadJoinWithTimeout) { -// long expect1 = 0xb00b; -// long result1 = 0; -// long expect2 = 0xbeef; -// long result2 = 0; -// -// { -// RunnableTarget2 target; -// Thread thread(&target); -// thread.start(); -// -// // -// thread.join(100); -// result1 = target.value; -// -// // -// thread.join(); -// result2 = target.value; -// } -// -// ASSERT_EQUAL(expect1, result1); -// ASSERT_EQUAL(expect2, result2); + long expect1 = 0xb00b; + long result1 = 0; + long expect2 = 0xbeef; + long result2 = 0; + + { + RunnableTarget2 target; + Thread thread(&target); + thread.start(); + + // + thread.join(100); + result1 = target.value; + + // + thread.join(); + result2 = target.value; + } + + ASSERT_EQUAL(expect1, result1); + ASSERT_EQUAL(expect2, result2); } From 3063d6b227ca7dedba91da1b9066988679fb1cd2 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Mon, 25 Sep 2017 21:19:20 +0700 Subject: [PATCH 18/41] #231 Add Thread::sleep() --- java/lang/Thread/Thread.cpp | 7 ++++++- java/lang/Thread/Thread.hpp | 2 ++ java/lang/Thread/ThreadTest.cpp | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index d15e2ae2..01408f11 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -24,9 +24,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "Thread.hpp" -#include +using namespace std; using namespace Java::Lang; int Thread::threadInitNumber = 0; @@ -132,3 +133,7 @@ void Thread::join(long millis) { semahoreObject.acquire(); } } + +void Thread::sleep(long millis) { + this_thread::sleep_for(chrono::milliseconds(millis)); +} diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index 5b00423a..3b62d2ce 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -310,6 +310,8 @@ namespace Java { void join(); void join(long millis); + + static void sleep(long millis); }; } // namespace Lang } // namespace Java diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 84b3cfcb..b22d5d46 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -46,7 +46,7 @@ class RunnableTarget1 : public virtual Runnable { void run() override { value = 0xb00b; - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + Thread::sleep(1000); } }; @@ -64,7 +64,7 @@ class RunnableTarget2 : public virtual Runnable { void run() override { value = 0xb00b; - std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + Thread::sleep(1000); value = 0xbeef; } }; From 7e2998be5f9ee11c6ff4abcaed7bedf40f5aa95b Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Wed, 27 Sep 2017 00:08:35 +0700 Subject: [PATCH 19/41] #231 Implement Thread::getId(), Thread::currentThread(), InterruptedException --- .../InterruptedException.cpp | 24 ++ .../InterruptedException.hpp | 45 ++++ .../InterruptedExceptionTest.cpp | 79 ++++++ java/lang/String/String.hpp | 4 +- java/lang/Thread/Thread.cpp | 72 +++--- java/lang/Thread/Thread.hpp | 234 +----------------- java/lang/Thread/ThreadTest.cpp | 165 ++++++------ 7 files changed, 280 insertions(+), 343 deletions(-) create mode 100644 java/lang/InterruptedException/InterruptedException.cpp create mode 100644 java/lang/InterruptedException/InterruptedException.hpp create mode 100644 java/lang/InterruptedException/InterruptedExceptionTest.cpp diff --git a/java/lang/InterruptedException/InterruptedException.cpp b/java/lang/InterruptedException/InterruptedException.cpp new file mode 100644 index 00000000..5f280bac --- /dev/null +++ b/java/lang/InterruptedException/InterruptedException.cpp @@ -0,0 +1,24 @@ +// +// Created by home on 9/26/17. +// + +#include "InterruptedException.hpp" + +InterruptedException::InterruptedException() : Exception() { + +} + +InterruptedException::InterruptedException(String message) : + Exception(message) { + +} + +InterruptedException::InterruptedException(Throwable *cause) : + Exception(cause){ + +} + +InterruptedException::InterruptedException(String message, Throwable *cause) + : Exception(message, cause) { + +} diff --git a/java/lang/InterruptedException/InterruptedException.hpp b/java/lang/InterruptedException/InterruptedException.hpp new file mode 100644 index 00000000..30690a69 --- /dev/null +++ b/java/lang/InterruptedException/InterruptedException.hpp @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2016 Food Tiny Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NATIVE_JAVA_LANG_INTERRUPTEDEXCEPTION_HPP +#define NATIVE_JAVA_LANG_INTERRUPTEDEXCEPTION_HPP + +#include "../Exception/Exception.hpp" +#include "../../Lang.hpp" + +namespace Java { + namespace Lang { + class InterruptedException : public Exception { + public: + InterruptedException(); + InterruptedException(String message); + InterruptedException(Throwable *cause); + InterruptedException(String message, Throwable *cause); + }; + } // namespace Lang +} // namespace Java + +#endif //NATIVE_JAVA_LANG_INTERRUPTEDEXCEPTION_HPP diff --git a/java/lang/InterruptedException/InterruptedExceptionTest.cpp b/java/lang/InterruptedException/InterruptedExceptionTest.cpp new file mode 100644 index 00000000..1510cc20 --- /dev/null +++ b/java/lang/InterruptedException/InterruptedExceptionTest.cpp @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2016 Food Tiny Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +extern "C" { +#include "../../../kernel/test.h" +}; + +#include "../InterruptedException/InterruptedException.hpp" + +using namespace Java::Lang; + +TEST(JavaLang, InterruptedExceptionConstructor) { + + InterruptedException interruptedExceptionWithNullMessage; + ASSERT_STR( + "", + interruptedExceptionWithNullMessage.getMessage().toString()); + + InterruptedException interruptedExceptionWithMessage = + InterruptedException( + "InterruptedException with the specified message"); + + ASSERT_STR( + "InterruptedException with the specified message", + interruptedExceptionWithMessage.getMessage().toString()); + + InterruptedException interruptedExceptionWithMessageAndCause = + InterruptedException( + "InterruptedException with the specified message and cause", + &interruptedExceptionWithMessage); + ASSERT_STR( + "InterruptedException with the specified message and cause", + interruptedExceptionWithMessageAndCause.getMessage().toString()); + ASSERT_STR( + "InterruptedException with the specified message", + interruptedExceptionWithMessageAndCause.getCause() + ->getMessage().toString()); + + InterruptedException interruptedExceptionWithCause = + InterruptedException(&interruptedExceptionWithMessageAndCause); + ASSERT_STR("InterruptedException with the specified message and cause", + interruptedExceptionWithCause.getCause() + ->getMessage().toString()); + ASSERT_STR("InterruptedException with the specified message", + interruptedExceptionWithCause.getCause() + ->getCause() + ->getMessage().toString()); +} + +TEST(JavaLang, InterruptedExceptionTryCatch) { + try { + throw InterruptedException("Throw InterruptedException"); + } catch (Exception e) { + ASSERT_STR("Throw InterruptedException", e.getMessage().toString()); + } +} diff --git a/java/lang/String/String.hpp b/java/lang/String/String.hpp index 114bc577..078bfe27 100644 --- a/java/lang/String/String.hpp +++ b/java/lang/String/String.hpp @@ -1030,9 +1030,9 @@ namespace Java { String remainString(inputStringPtr + matchedResult[0].rm_eo, inputStringLength - matchedResult[0].rm_eo); try { result += String::format(remainString, args...); - } catch (IllegalArgumentException& e) { + } catch (...) { regfree(®ex); - throw e; + throw; } break; } diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index 01408f11..95e3123a 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -25,20 +25,21 @@ */ #include +#include #include "Thread.hpp" +#include "../InterruptedException/InterruptedException.hpp" using namespace std; using namespace Java::Lang; -int Thread::threadInitNumber = 0; -long Thread::threadSeqNumber = 0; +thread_local Thread* currentThreadPtr = NULL; Thread::Thread() { - init(nullptr, "Thread - " + Thread::nextThreadNum(), 0); + init(nullptr, ""); } Thread::Thread(Runnable *target) { - init(target, "Thread - " + Thread::nextThreadNum(), 0); + init(target, ""); } Thread::~Thread() { @@ -49,6 +50,19 @@ Thread::~Thread() { } void Thread::run() { + // set thread id + { + stringstream out; + out << this_thread::get_id(); + stringstream in(out.str()); + in >> this->tid; + } + + // set tls + if (currentThreadPtr == NULL) { + currentThreadPtr = this; + } + mutexObject.lock(); alive = true; mutexObject.unlock(); @@ -61,59 +75,26 @@ void Thread::run() { mutexObject.unlock(); } -// TODO(thoangminh): Need method checkAccess, threadStatus, setNativeName void Thread::setName(String name) { this->name = name; } -void Thread::init(Runnable *target, String name, long stackSize) { +void Thread::init(Runnable *target, String name) { this->target = target; this->name = name; - this->stackSize = stackSize; - this->tid = nextThreadID(); } String Thread::getName() { return this->name; } -// TODO(thoangminh): Need IllegalThreadStateException, method checkAccess, isAlive -void Thread::setDaemon(boolean on) { - this->daemon = on; -} - boolean Thread::isAlive() { std::unique_lock locker(mutexObject); return alive; } -boolean Thread::isDaemon() { - return this->daemon; -} - -// TODO(thoangminh): Need class ThreadGroup, IllegalThreadStateException, method checkAccess -void Thread::setPriority(int newPriority) { - if (newPriority > Thread::MAX_PRIORITY) { - newPriority = Thread::MAX_PRIORITY; - } - - if (newPriority < Thread::MIN_PRIORITY) { - newPriority = Thread::MIN_PRIORITY; - } - - this->priority = newPriority; -} - -int Thread::getPriority() { - return this->priority; -} - -int Thread::nextThreadNum() { - return threadInitNumber++; -} - -long Thread::nextThreadID() { - ++threadSeqNumber; +long long Thread::getId() { + return this->tid; } void Thread::start() { @@ -135,5 +116,14 @@ void Thread::join(long millis) { } void Thread::sleep(long millis) { - this_thread::sleep_for(chrono::milliseconds(millis)); + if (currentThreadPtr) { + if (currentThreadPtr->semahoreObject.tryAcquire(1, millis)) + throw InterruptedException("interrupted"); + } else { + this_thread::sleep_for(chrono::milliseconds(millis)); + } +} + +Thread *Thread::currentThread() { + return currentThreadPtr; } diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index 3b62d2ce..00905c4d 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -31,192 +31,40 @@ #include #include "../Object/Object.hpp" -#include "../String/String.hpp" #include "../Runnable/Runnable.hpp" #include "../../util/Concurrent/Semaphore/Semaphore.hpp" +using Java::Util::Concurrent::Semaphore; namespace Java { namespace Lang { class Thread : public Object, public virtual Runnable { private: boolean alive = false; - String name; - int priority; - - /** - * Whether or not to single_step this thread. - */ - boolean single_step; - - /** - * Whether or not the thread is a daemon thread. - */ - boolean daemon = false; - - /** - * JVM state - */ - boolean stillborn = false; - - /** - * What will be run. - */ + long long tid = 0; Runnable *target = NULL; - - // TODO(thoangminh): Need Class ThreadGroup - /** - * The group of this thread - */ -// ThreadGroup group; - - // TODO(thoangminh): Need Class ClassLoader - /** - * The context ClassLoader for this thread - */ -// ClassLoader contextClassLoader; - - // TODO(thoangminh): Need Class AccessControlContext - /** - * The inherited AccessControlContext of this thread - */ -// AccessControlContext inheritedAccessControlContext; - - /** - * For autonumbering anonymous threads. - */ - static int threadInitNumber; - - // TODO(thoangminh): Need Class ThreadLocal - /** - * ThreadLocal values pertaining to this thread. - * This map is maintained - * by the ThreadLocal class. - */ -// ThreadLocal.ThreadLocalMap threadLocals = null; - - // TODO(thoangminh): Need Class ThreadLocal - /** - * InheritableThreadLocal values pertaining to this thread. - * This map is maintained by - * the InheritableThreadLocal class. - */ -// ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; - - /** - * The requested stack size for this thread, or 0 if the creator did - * not specify a stack size. It is up to the VM to do - * whatever it likes with this number; some VMs will ignore it. * - */ - long stackSize; - - /** - * JVM-private state that persists after native thread termination. - */ - long nativeParkEventPointer; - - /** - * Thread ID - */ - long tid; - - /** - * For generating thread ID - */ - static long threadSeqNumber; - - /** - * Java thread status for tools, - * initialized to indicate thread 'not yet started' - */ - volatile int threadStatus = 0; - - // TODO(thoangminh): Need Class Interruptible - /** - * The object in which this thread is blocked in an interruptible I/O - * operation, if any. The blocker's interrupt method should be invoked - * after setting this thread's interrupt status. - */ -// volatile Interruptible blocker; -// const Object blockerLock = new Object(); - + Semaphore semahoreObject; std::thread threadObject; std::mutex mutexObject; - Java::Util::Concurrent::Semaphore semahoreObject; private: /** * Initializes a Thread. * - * @param g the Thread group * @param target the object whose run() method gets called * @param name the name of the new Thread * @param stackSize the desired stack size for the new thread, or * zero to indicate that this parameter is to be ignored. - * @param acc the AccessControlContext to inherit, or - * AccessController.getContext() if null */ -// void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc); - - // TODO(thoangminh): Need to improve this medthod - /** - * Initializes a Thread. - * - * @param target the object whose run() method gets called - * @param name the name of the new Thread - * @param stackSize the desired stack size for the new thread, or - * zero to indicate that this parameter is to be ignored. - */ - void init(Runnable *target, String name, long stackSize); - - // TODO(thoangminh): Set synchronized for this method - static int nextThreadNum(); - - // TODO(thoangminh): Set synchronized for this method - static long nextThreadID(); - - public: - /** - * The minimum priority that a thread can have. - */ - static int const MIN_PRIORITY = 1; - - /** - * The default priority that is assigned to a thread. - */ - static int const NORM_PRIORITY = 5; - - /** - * The maximum priority that a thread can have. - */ - static int const MAX_PRIORITY = 10; - - public: - void *pthread_run(void *context) { - ((Thread *) (context))->target->run(); - } - - static void *pthread_helper(void *context) { - return ((Thread *) (context))->pthread_run(context); - } + void init(Runnable *target, String name); public: Thread(); Thread(Runnable* target); -// Thread(Runnable &target); -// Thread(String name); -// Thread(Runnable target, AccessControlContext acc); -// Thread(ThreadGroup group, Runnable target); -// Thread(ThreadGroup group, String name); -// Thread(Runnable &target, String name); -// Thread(ThreadGroup group, Runnable target, String name, long stackSize); -// Thread(ThreadGroup group, Runnable target, String name); ~Thread(); - - public: - void run() override ; - // TODO(thoangminh): Set synchronized for this method + void run() override; + /** * Changes the name of this thread to be equal to the argument * name. @@ -243,67 +91,7 @@ namespace Java { boolean isAlive(); - /** - * Tests if this thread is a daemon thread. - * - * @return true if this thread is a daemon thread; - * false otherwise. - * @see #setDaemon(boolean) - */ - boolean isDaemon() ; - - /** - * Marks this thread as either a {#isDaemon daemon} thread - * or a user thread. The Java Virtual Machine exits when the only - * threads running are all daemon threads. - * - * This method must be invoked before the thread is started. - * - * @param on - * if {true}, marks this thread as a daemon thread - * - * @throws IllegalThreadStateException - * if this thread is {#isAlive alive} - * - * @throws SecurityException - * if {#checkAccess} determines that the current - * thread cannot modify this thread - */ - void setDaemon(boolean on); - - /** - * Changes the priority of this thread. - * - * First the checkAccess method of this thread is called - * with no arguments. This may result in throwing a - * SecurityException. - * - * Otherwise, the priority of this thread is set to the smaller of - * the specified newPriority and the maximum permitted - * priority of the thread's thread group. - * - * @param newPriority priority to set this thread to - * @exception IllegalArgumentException If the priority is not in the - * range MIN_PRIORITY to - * MAX_PRIORITY. - * @exception SecurityException if the current thread cannot modify - * this thread. - * @see #getPriority - * @see #checkAccess() - * @see #getThreadGroup() - * @see #MAX_PRIORITY - * @see #MIN_PRIORITY - * @see ThreadGroup#getMaxPriority() - */ - void setPriority(int newPriority); - - /** - * Returns this thread's priority. - * - * @return this thread's priority. - * @see #setPriority - */ - int getPriority(); + long long getId(); void start(); @@ -312,9 +100,11 @@ namespace Java { void join(long millis); static void sleep(long millis); - }; - } // namespace Lang -} // namespace Java + + static Thread* currentThread(); + }; + } // namespace Lang +} // namespace Java #endif // JAVA_LANG_THREAD_THREAD_HPP_ diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index b22d5d46..28f4b065 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -28,8 +28,14 @@ extern "C" { #include "../../../kernel/test.h" }; +#include +#include + +#include #include "Thread.hpp" +#include "../InterruptedException/InterruptedException.hpp" +using namespace std; using namespace Java::Lang; class RunnableTarget1 : public virtual Runnable { @@ -46,7 +52,7 @@ class RunnableTarget1 : public virtual Runnable { void run() override { value = 0xb00b; - Thread::sleep(1000); + this_thread::sleep_for(chrono::milliseconds(1000)); } }; @@ -64,121 +70,112 @@ class RunnableTarget2 : public virtual Runnable { void run() override { value = 0xb00b; - Thread::sleep(1000); + this_thread::sleep_for(chrono::milliseconds(1000)); value = 0xbeef; } }; -// TODO(thoangminh): Need to improve it -TEST(JavaLang, ThreadConstructor) { -} +class RunnableTarget3 : public virtual Runnable { +public: + String threadIdString; -TEST(JavaLang, ThreadRun) { - long expect = 0xb00b; - long result = 0; - RunnableTarget1* target = new RunnableTarget1(); + RunnableTarget3() { - { - Thread thread(target); - thread.start(); - thread.join(); - result = target->value; } - delete target; - ASSERT_EQUAL(expect, result); -} + ~RunnableTarget3() { -TEST(JavaLang, ThreadSetDaemon) { - Thread thread; - - thread.setDaemon(true); - ASSERT_TRUE(thread.isDaemon()); - - thread.setDaemon(false); - ASSERT_FALSE(thread.isDaemon()); -} + } -TEST(JavaLang, ThreadIsDaemon) { - Thread thread; + void run() override { + stringstream out; + out << this_thread::get_id(); + this->threadIdString = out.str(); + } +}; - thread.setDaemon(true); - ASSERT_TRUE(thread.isDaemon()); +class RunnableTarget4 : public virtual Runnable { +public: + thread_t threadHandle; - thread.setDaemon(false); - ASSERT_FALSE(thread.isDaemon()); -} + RunnableTarget4() { -TEST(JavaLang, ThreadSetPriority) { - Thread thread; + } - thread.setPriority(-1); - ASSERT_EQUAL(1, thread.getPriority()); + ~RunnableTarget4() { - thread.setPriority(0); - ASSERT_EQUAL(1, thread.getPriority()); + } - thread.setPriority(3); - ASSERT_EQUAL(3, thread.getPriority()); + void run() override { + this->threadHandle = pthread_self(); + + try { + if (Thread::currentThread()) + printf("tid: %lld\n", Thread::currentThread()->getId()); + Thread::sleep(3000); + } catch (InterruptedException e) { + printf("yeah\n"); + } + } +}; - thread.setPriority(Thread::MIN_PRIORITY); - ASSERT_EQUAL(1, thread.getPriority()); +TEST(JavaLang, ThreadRun) { + long expect = 0xb00b; + long result = 0; + RunnableTarget1* target = new RunnableTarget1(); - thread.setPriority(Thread::NORM_PRIORITY); - ASSERT_EQUAL(5, thread.getPriority()); + { + Thread thread(target); + thread.start(); + thread.join(); + result = target->value; + } - thread.setPriority(Thread::MAX_PRIORITY); - ASSERT_EQUAL(10, thread.getPriority()); + delete target; + ASSERT_EQUAL(expect, result); } -TEST(JavaLang, ThreadGetPriority) { +TEST(JavaLang, ThreadSetName) { Thread thread; - thread.setPriority(-1); - ASSERT_EQUAL(1, thread.getPriority()); - - thread.setPriority(0); - ASSERT_EQUAL(1, thread.getPriority()); - - thread.setPriority(3); - ASSERT_EQUAL(3, thread.getPriority()); - - thread.setPriority(Thread::MIN_PRIORITY); - ASSERT_EQUAL(1, thread.getPriority()); + String name = "Thread 1"; + thread.setName(name); + ASSERT_STR("Thread 1", thread.getName().toString()); - thread.setPriority(Thread::NORM_PRIORITY); - ASSERT_EQUAL(5, thread.getPriority()); + thread.setName("Thread 2"); + ASSERT_STR("Thread 2", thread.getName().toString()); - thread.setPriority(Thread::MAX_PRIORITY); - ASSERT_EQUAL(10, thread.getPriority()); + thread.setName("Thread 5"); + ASSERT_NOT_STR("Thread 1", thread.getName().toString()); } -TEST(JavaLang, ThreadSetName) { +TEST(JavaLang, ThreadGetName) { Thread thread; String name = "Thread 1"; thread.setName(name); - ASSERT_STR((string) "Thread 1", thread.getName().toString()); + ASSERT_STR("Thread 1", thread.getName().toString()); - thread.setName((string) "Thread 2"); - ASSERT_STR((string) "Thread 2", thread.getName().toString()); + thread.setName("Thread 2"); + ASSERT_STR("Thread 2", thread.getName().toString()); - thread.setName((string) "Thread 5"); - ASSERT_NOT_STR((string) "Thread 1", thread.getName().toString()); + thread.setName("Thread 5"); + ASSERT_NOT_STR("Thread 1", thread.getName().toString()); } -TEST(JavaLang, ThreadGetName) { - Thread thread; +TEST(JavaLang, ThreadGetThreadId) { + RunnableTarget3 target; + Thread thread(&target); - String name = "Thread 1"; - thread.setName(name); - ASSERT_STR((string) "Thread 1", thread.getName().toString()); + thread.start(); + thread.join(); - thread.setName((string) "Thread 2"); - ASSERT_STR((string) "Thread 2", thread.getName().toString()); + String expect = target.threadIdString.toString(); + //String result = String::format("%lld", thread.getId()); + stringstream out; + out << thread.getId(); - thread.setName((string) "Thread 5"); - ASSERT_NOT_STR((string) "Thread 1", thread.getName().toString()); + ASSERT_STR(expect.toString(), out.str().c_str()); } TEST(JavaLang, ThreadJoinWithTimeout) { @@ -204,3 +201,15 @@ TEST(JavaLang, ThreadJoinWithTimeout) { ASSERT_EQUAL(expect1, result1); ASSERT_EQUAL(expect2, result2); } + +TEST(JavaLang, ThreadSleepWithInterruptedException) { +// RunnableTarget4 target; +// Thread thread(&target); +// +// thread.start(); +// +// Thread::sleep(1000); +// pthread_cancel(target.threadHandle); +// +// thread.join(); +} From 536f0ecc5a8efeeda5e6873f908e67b103bad196 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Wed, 27 Sep 2017 21:39:37 +0700 Subject: [PATCH 20/41] #231 Add print long long to String:format(), remove Thread::sleep() test case --- java/lang/String/String.cpp | 22 +++++++++++++- java/lang/String/String.hpp | 2 ++ java/lang/Thread/Thread.cpp | 7 +---- java/lang/Thread/ThreadTest.cpp | 52 ++++----------------------------- 4 files changed, 29 insertions(+), 54 deletions(-) diff --git a/java/lang/String/String.cpp b/java/lang/String/String.cpp index a74c96fa..8d457b46 100644 --- a/java/lang/String/String.cpp +++ b/java/lang/String/String.cpp @@ -744,6 +744,16 @@ String String::print(const String &format, long value) { return result; } +String String::print(const String &format, long long value) { + String result; + char buffer[DEFAULT_BUFFER_LENGTH] = {0}; + const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); + if (length > 0) { + result = String(buffer, length); + } + return result; +} + String String::print(const String &format, unsigned short value) { String result; char buffer[DEFAULT_BUFFER_LENGTH] = {0}; @@ -774,6 +784,16 @@ String String::print(const String &format, unsigned long value) { return result; } +String String::print(const String &format, unsigned long long value) { + String result; + char buffer[DEFAULT_BUFFER_LENGTH] = {0}; + const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); + if (length > 0) { + result = String(buffer, length); + } + return result; +} + String String::print(const String &format, double value) { String result; char buffer[DEFAULT_BUFFER_LENGTH] = {0}; @@ -881,4 +901,4 @@ String String::format(const String &format) { regfree(®ex); return result; -} +} \ No newline at end of file diff --git a/java/lang/String/String.hpp b/java/lang/String/String.hpp index 078bfe27..45043121 100644 --- a/java/lang/String/String.hpp +++ b/java/lang/String/String.hpp @@ -1097,9 +1097,11 @@ namespace Java { static String print(const String& format, short value); static String print(const String& format, int value); static String print(const String& format, long value); + static String print(const String& format, long long value); static String print(const String& format, unsigned short value); static String print(const String& format, unsigned int value); static String print(const String& format, unsigned long value); + static String print(const String& format, unsigned long long value); static String print(const String& format, double value); static String print(const String& format, float value); static String print(const String& format, char* value); diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index 95e3123a..3193e733 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -116,12 +116,7 @@ void Thread::join(long millis) { } void Thread::sleep(long millis) { - if (currentThreadPtr) { - if (currentThreadPtr->semahoreObject.tryAcquire(1, millis)) - throw InterruptedException("interrupted"); - } else { - this_thread::sleep_for(chrono::milliseconds(millis)); - } + this_thread::sleep_for(chrono::milliseconds(millis)); } Thread *Thread::currentThread() { diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 28f4b065..0e4c6b37 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -28,9 +28,6 @@ extern "C" { #include "../../../kernel/test.h" }; -#include -#include - #include #include "Thread.hpp" #include "../InterruptedException/InterruptedException.hpp" @@ -52,7 +49,7 @@ class RunnableTarget1 : public virtual Runnable { void run() override { value = 0xb00b; - this_thread::sleep_for(chrono::milliseconds(1000)); + Thread::sleep(1000); } }; @@ -70,7 +67,7 @@ class RunnableTarget2 : public virtual Runnable { void run() override { value = 0xb00b; - this_thread::sleep_for(chrono::milliseconds(1000)); + Thread::sleep(1000); value = 0xbeef; } }; @@ -94,31 +91,6 @@ class RunnableTarget3 : public virtual Runnable { } }; -class RunnableTarget4 : public virtual Runnable { -public: - thread_t threadHandle; - - RunnableTarget4() { - - } - - ~RunnableTarget4() { - - } - - void run() override { - this->threadHandle = pthread_self(); - - try { - if (Thread::currentThread()) - printf("tid: %lld\n", Thread::currentThread()->getId()); - Thread::sleep(3000); - } catch (InterruptedException e) { - printf("yeah\n"); - } - } -}; - TEST(JavaLang, ThreadRun) { long expect = 0xb00b; long result = 0; @@ -171,11 +143,9 @@ TEST(JavaLang, ThreadGetThreadId) { thread.join(); String expect = target.threadIdString.toString(); - //String result = String::format("%lld", thread.getId()); - stringstream out; - out << thread.getId(); + String result = String::format("%lld", thread.getId()); - ASSERT_STR(expect.toString(), out.str().c_str()); + ASSERT_STR(expect.toString(), result.toString()); } TEST(JavaLang, ThreadJoinWithTimeout) { @@ -200,16 +170,4 @@ TEST(JavaLang, ThreadJoinWithTimeout) { ASSERT_EQUAL(expect1, result1); ASSERT_EQUAL(expect2, result2); -} - -TEST(JavaLang, ThreadSleepWithInterruptedException) { -// RunnableTarget4 target; -// Thread thread(&target); -// -// thread.start(); -// -// Thread::sleep(1000); -// pthread_cancel(target.threadHandle); -// -// thread.join(); -} +} \ No newline at end of file From 19d8ae44d0a7bf3190bf01109fc79b25fc80202c Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Wed, 27 Sep 2017 21:53:30 +0700 Subject: [PATCH 21/41] #231 Debug getting thread id in appveyor env --- java/lang/Thread/ThreadTest.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 0e4c6b37..45ac4f3f 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -28,7 +28,7 @@ extern "C" { #include "../../../kernel/test.h" }; -#include +#include #include "Thread.hpp" #include "../InterruptedException/InterruptedException.hpp" @@ -88,6 +88,10 @@ class RunnableTarget3 : public virtual Runnable { stringstream out; out << this_thread::get_id(); this->threadIdString = out.str(); + + // debug + cout << endl; + cout << "[debug] tid = " << this_thread::get_id() << endl; } }; @@ -145,7 +149,7 @@ TEST(JavaLang, ThreadGetThreadId) { String expect = target.threadIdString.toString(); String result = String::format("%lld", thread.getId()); - ASSERT_STR(expect.toString(), result.toString()); + //ASSERT_STR(expect.toString(), result.toString()); } TEST(JavaLang, ThreadJoinWithTimeout) { From eda2316523d1381acdbb55ac1242c83ede4a8a46 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Wed, 27 Sep 2017 22:21:05 +0700 Subject: [PATCH 22/41] #231 Change method get thread id --- java/lang/Thread/Thread.cpp | 10 +++------- java/lang/Thread/Thread.hpp | 4 ++-- java/lang/Thread/ThreadTest.cpp | 7 +------ 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index 3193e733..5e7f04f4 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include "Thread.hpp" @@ -51,12 +52,7 @@ Thread::~Thread() { void Thread::run() { // set thread id - { - stringstream out; - out << this_thread::get_id(); - stringstream in(out.str()); - in >> this->tid; - } + this->tid = pthread_self(); // set tls if (currentThreadPtr == NULL) { @@ -93,7 +89,7 @@ boolean Thread::isAlive() { return alive; } -long long Thread::getId() { +unsigned long Thread::getId() { return this->tid; } diff --git a/java/lang/Thread/Thread.hpp b/java/lang/Thread/Thread.hpp index 00905c4d..09e9c62b 100755 --- a/java/lang/Thread/Thread.hpp +++ b/java/lang/Thread/Thread.hpp @@ -41,7 +41,7 @@ namespace Java { private: boolean alive = false; String name; - long long tid = 0; + unsigned long tid = 0; Runnable *target = NULL; Semaphore semahoreObject; std::thread threadObject; @@ -91,7 +91,7 @@ namespace Java { boolean isAlive(); - long long getId(); + unsigned long getId(); void start(); diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 45ac4f3f..fe669f87 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -28,7 +28,6 @@ extern "C" { #include "../../../kernel/test.h" }; -#include #include "Thread.hpp" #include "../InterruptedException/InterruptedException.hpp" @@ -88,10 +87,6 @@ class RunnableTarget3 : public virtual Runnable { stringstream out; out << this_thread::get_id(); this->threadIdString = out.str(); - - // debug - cout << endl; - cout << "[debug] tid = " << this_thread::get_id() << endl; } }; @@ -149,7 +144,7 @@ TEST(JavaLang, ThreadGetThreadId) { String expect = target.threadIdString.toString(); String result = String::format("%lld", thread.getId()); - //ASSERT_STR(expect.toString(), result.toString()); + ASSERT_STR(expect.toString(), result.toString()); } TEST(JavaLang, ThreadJoinWithTimeout) { From 10e2604c2e7ac2292715a176ac74a64624f3caf4 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Tue, 10 Oct 2017 22:07:24 +0700 Subject: [PATCH 23/41] #231 Fix getting thread id --- java/lang/Thread/Thread.cpp | 2 +- java/lang/Thread/ThreadTest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index 51d50f2a..31e4276d 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -52,7 +52,7 @@ Thread::~Thread() { void Thread::run() { // set thread id - this->tid = (unsigned long) pthread_self(); + this->tid = *(unsigned long*)pthread_self(); // set tls if (currentThreadPtr == NULL) { diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 19808807..d2db8c72 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -136,7 +136,7 @@ TEST(JavaLang, ThreadGetThreadId) { String expect = target.threadIdString.toString(); String result = String::format("%lld", thread.getId()); - ASSERT_STR("25770228112", result.toString()); + ASSERT_STR(expect.toString(), result.toString()); } TEST(JavaLang, ThreadJoinWithTimeout) { From e6d5b2fce2cf00bc629000f0342c379881001a85 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Tue, 10 Oct 2017 22:18:02 +0700 Subject: [PATCH 24/41] #231 Fix getting thread id --- java/lang/Thread/Thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/lang/Thread/Thread.cpp b/java/lang/Thread/Thread.cpp index 31e4276d..ce343cef 100755 --- a/java/lang/Thread/Thread.cpp +++ b/java/lang/Thread/Thread.cpp @@ -52,7 +52,7 @@ Thread::~Thread() { void Thread::run() { // set thread id - this->tid = *(unsigned long*)pthread_self(); + this->tid = (unsigned long)pthread_self(); // set tls if (currentThreadPtr == NULL) { From 51a3b9eedf82e82813e5bb18fa41ebb79b0b4332 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Tue, 10 Oct 2017 22:28:35 +0700 Subject: [PATCH 25/41] #231 Fix getting thread id --- java/lang/Thread/ThreadTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index d2db8c72..5c0fe2e4 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -71,7 +71,7 @@ class RunnableTarget2 : public virtual Runnable { class RunnableTarget3 : public virtual Runnable { public: - String threadIdString; + unsigned long tid; RunnableTarget3() { @@ -84,7 +84,7 @@ class RunnableTarget3 : public virtual Runnable { void run() override { stringstream out; out << this_thread::get_id(); - this->threadIdString = out.str(); + tid = (unsigned long)pthread_self(); } }; @@ -133,7 +133,7 @@ TEST(JavaLang, ThreadGetThreadId) { thread.start(); thread.join(); - String expect = target.threadIdString.toString(); + String expect = String::format("%lld", target.tid); String result = String::format("%lld", thread.getId()); ASSERT_STR(expect.toString(), result.toString()); From 4ca1d9504eb09c711758c61e994883e03243ccb3 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Thu, 12 Oct 2017 20:23:43 +0700 Subject: [PATCH 26/41] #231 Remove unused ostream --- java/lang/Thread/ThreadTest.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp index 5c0fe2e4..ca3aa238 100755 --- a/java/lang/Thread/ThreadTest.cpp +++ b/java/lang/Thread/ThreadTest.cpp @@ -82,8 +82,6 @@ class RunnableTarget3 : public virtual Runnable { } void run() override { - stringstream out; - out << this_thread::get_id(); tid = (unsigned long)pthread_self(); } }; From be8932be6e8022db927b6a65b29e4d753eceb8aa Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 21:23:49 +0700 Subject: [PATCH 27/41] #231 Try installing clang++ --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 89da88c2..538b982b 100755 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,8 @@ addons: before_script: - export CC=gcc - export CXX=g++ +- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then brew install llvm; export +CXX=clang++;fi - ./misc/benchmark.sh - cmake . -DCMAKE_BUILD_TYPE=Debug && make native_test -j8 - cmake . -DCMAKE_BUILD_TYPE=Release && make native_benchmark From 3dd94e00fc793de1bc49b2b8efcd0cb908118cc9 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 21:26:32 +0700 Subject: [PATCH 28/41] Try installing clang++ --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 538b982b..bcbc2270 100755 --- a/.travis.yml +++ b/.travis.yml @@ -19,8 +19,7 @@ addons: before_script: - export CC=gcc - export CXX=g++ -- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then brew install llvm; export -CXX=clang++;fi +- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then brew install llvm; export CXX=clang++; fi - ./misc/benchmark.sh - cmake . -DCMAKE_BUILD_TYPE=Debug && make native_test -j8 - cmake . -DCMAKE_BUILD_TYPE=Release && make native_benchmark From 9a6db9f3fe02db38b456d04e5fa29eaa403a2ace Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 21:49:21 +0700 Subject: [PATCH 29/41] Try installing clang++ --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bcbc2270..466a44c2 100755 --- a/.travis.yml +++ b/.travis.yml @@ -17,9 +17,9 @@ addons: - valgrind - lcov before_script: +- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then brew install llvm; export CXX=clang++; fi - export CC=gcc - export CXX=g++ -- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then brew install llvm; export CXX=clang++; fi - ./misc/benchmark.sh - cmake . -DCMAKE_BUILD_TYPE=Debug && make native_test -j8 - cmake . -DCMAKE_BUILD_TYPE=Release && make native_benchmark From a7cf8859d479dfc6bd39117073e1a26e2fcd93f2 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 22:01:33 +0700 Subject: [PATCH 30/41] Try installing clang++ --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 466a44c2..175f045a 100755 --- a/.travis.yml +++ b/.travis.yml @@ -12,12 +12,11 @@ addons: apt: sources: - ubuntu-toolchain-r-test - - llvm-toolchain-precise-3.6 + - llvm-toolchain-precise-3.7 packages: - valgrind - lcov before_script: -- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then brew install llvm; export CXX=clang++; fi - export CC=gcc - export CXX=g++ - ./misc/benchmark.sh From 715385ab8222a1cb4da8347421fac95e591be2fb Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 22:14:28 +0700 Subject: [PATCH 31/41] Test brew --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 175f045a..0074c0f2 100755 --- a/.travis.yml +++ b/.travis.yml @@ -12,11 +12,12 @@ addons: apt: sources: - ubuntu-toolchain-r-test - - llvm-toolchain-precise-3.7 + - llvm-toolchain-precise-3.6 packages: - valgrind - lcov before_script: +- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then brew help; fi - export CC=gcc - export CXX=g++ - ./misc/benchmark.sh From bf111d324487eada10ec66066ac13f74d0f0c453 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 22:35:23 +0700 Subject: [PATCH 32/41] Test brew --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0074c0f2..34168ef6 100755 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ addons: - valgrind - lcov before_script: -- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then brew help; fi +- if [ "$TRAVIS_OS_NAME" != "osx" ]; then brew help; fi - export CC=gcc - export CXX=g++ - ./misc/benchmark.sh From a675a45bff5b1c6af12c89f25465aa40dea81ff0 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 22:46:58 +0700 Subject: [PATCH 33/41] Test brew --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 34168ef6..fdd6af9b 100755 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ addons: - valgrind - lcov before_script: -- if [ "$TRAVIS_OS_NAME" != "osx" ]; then brew help; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew help; fi - export CC=gcc - export CXX=g++ - ./misc/benchmark.sh From c4c4596f289a76b8f485d10145ef193aa2083c46 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 22:57:29 +0700 Subject: [PATCH 34/41] #231 Try installing clang++ --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fdd6af9b..b4d4a2b8 100755 --- a/.travis.yml +++ b/.travis.yml @@ -17,9 +17,9 @@ addons: - valgrind - lcov before_script: -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew help; fi - export CC=gcc - export CXX=g++ +- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install llvm; export CXX=clang++; fi - ./misc/benchmark.sh - cmake . -DCMAKE_BUILD_TYPE=Debug && make native_test -j8 - cmake . -DCMAKE_BUILD_TYPE=Release && make native_benchmark From 7e6926fb89d1400aa8528922fcbdc46669a99fb2 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 23:17:38 +0700 Subject: [PATCH 35/41] #231 Try installing clang++ --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b4d4a2b8..e4f62f48 100755 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ addons: before_script: - export CC=gcc - export CXX=g++ -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install llvm; export CXX=clang++; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; brew install llvm; export CXX=clang++; fi - ./misc/benchmark.sh - cmake . -DCMAKE_BUILD_TYPE=Debug && make native_test -j8 - cmake . -DCMAKE_BUILD_TYPE=Release && make native_benchmark From 55af6766905936c034610e517ecbeea9de398bde Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 23:35:21 +0700 Subject: [PATCH 36/41] #231 Try installing clang++ --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e4f62f48..6da91665 100755 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ addons: before_script: - export CC=gcc - export CXX=g++ -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; brew install llvm; export CXX=clang++; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ruby; brew update; brew install llvm; export CXX=clang++; fi - ./misc/benchmark.sh - cmake . -DCMAKE_BUILD_TYPE=Debug && make native_test -j8 - cmake . -DCMAKE_BUILD_TYPE=Release && make native_benchmark From d627740c62c72050c5934af23ea6f322980d90ae Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 15 Oct 2017 23:54:51 +0700 Subject: [PATCH 37/41] #231 Try installing clang++ --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6da91665..66f5e180 100755 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ addons: before_script: - export CC=gcc - export CXX=g++ -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ruby; brew update; brew install llvm; export CXX=clang++; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ruby; brew update; brew install llvm; export CXX=clang++-5.0; fi - ./misc/benchmark.sh - cmake . -DCMAKE_BUILD_TYPE=Debug && make native_test -j8 - cmake . -DCMAKE_BUILD_TYPE=Release && make native_benchmark From c1bae3ebc2ae6bf74c8f71daee3d5ec12f00fda1 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Mon, 16 Oct 2017 00:15:06 +0700 Subject: [PATCH 38/41] #231 Try installing clang++ --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 66f5e180..5bab98d9 100755 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ addons: before_script: - export CC=gcc - export CXX=g++ -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ruby; brew update; brew install llvm; export CXX=clang++-5.0; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ruby; brew update;brew install llvm50; export CXX=clang++-5.0; fi - ./misc/benchmark.sh - cmake . -DCMAKE_BUILD_TYPE=Debug && make native_test -j8 - cmake . -DCMAKE_BUILD_TYPE=Release && make native_benchmark From cee3245a946d190ac32c00974a91fdc3ed3c560b Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Sun, 25 Mar 2018 10:35:53 +0700 Subject: [PATCH 39/41] #231 Fix travis config. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ef4010cc..51915750 100755 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,6 @@ addons: before_script: - export CC=gcc - export CXX=g++ -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ruby; brew update;brew install llvm50; export CXX=clang++-5.0; fi - ./misc/benchmark.sh script: - cmake . -DCMAKE_BUILD_TYPE=Debug && make native_test -j8 From e52716b0f572a3312dab6058c4d173428ff57cde Mon Sep 17 00:00:00 2001 From: sonda Date: Sun, 25 Mar 2018 21:41:12 +0700 Subject: [PATCH 40/41] #231 Remove unused files. --- java/lang/Float/Float.hpp | 592 ------------ .../InterruptedException.cpp | 24 - .../InterruptedException.hpp | 45 - .../InterruptedExceptionTest.cpp | 77 -- java/lang/String/String.cpp | 852 ------------------ java/lang/Thread/ThreadTest.cpp | 162 ---- 6 files changed, 1752 deletions(-) delete mode 100755 java/lang/Float/Float.hpp delete mode 100644 java/lang/InterruptedException/InterruptedException.cpp delete mode 100644 java/lang/InterruptedException/InterruptedException.hpp delete mode 100644 java/lang/InterruptedException/InterruptedExceptionTest.cpp delete mode 100755 java/lang/String/String.cpp delete mode 100755 java/lang/Thread/ThreadTest.cpp diff --git a/java/lang/Float/Float.hpp b/java/lang/Float/Float.hpp deleted file mode 100755 index a3f6776f..00000000 --- a/java/lang/Float/Float.hpp +++ /dev/null @@ -1,592 +0,0 @@ -/** - * Copyright 2017 Food Tiny Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JAVA_LANG_FLOAT_HPP_ -#define JAVA_LANG_FLOAT_HPP_ - -#include "../Object/Object.hpp" -#include "../Number/Number.hpp" -#include -#include "../String/String.hpp" -#include "../Byte/Byte.hpp" -#include "../Comparable/Comparable.hpp" - -namespace Java { - namespace Lang { - - class Float : - virtual public Number, - virtual public Comparable { - private: - float original; - string originalString; - - public: - /** - * A constant holding the positive infinity of type float. - */ - static constexpr float POSITIVE_INFINITY = INFINITY; - - /** - * A constant holding the negative infinity of type float. - */ - static constexpr float NEGATIVE_INFINITY = -INFINITY; - - /** - * A constant holding a Not-a-Number NaN value of type float. - */ - static constexpr float NaN = NAN; - - /** - * A constant holding the largest positive finite value of type - */ - static constexpr float MAX_VALUE = std::numeric_limits::max(); // 3.40282e+38 - - /** - * The smallest subnormal value has sign bit = 0, exponent = 0 - * and only the least significant bit of the fraction is 1 - */ - static constexpr float MIN_NORMAL = 1.4013e-45f; - - /** - * A constant holding the smallest value of type - */ - static constexpr float MIN_VALUE = std::numeric_limits::min(); // 1.17549e-38 - - /** - * Minimum exponent a normalized float number may have - */ - static constexpr int MIN_EXPONENT = -126; - - /** - * Maximum exponent a finite float variable may have. - */ - static constexpr int MAX_EXPONENT = 127; - - /** - * The number of bits used to represent a float value. - * - */ - static constexpr int SIZE = 32; - - /** - * The number of bytes used to represent a float value. - */ - static constexpr int BYTES = SIZE / Bytes::SIZE; - - /** - * The number of logical bits in the significand of a float number, - * including the implicit bit. - */ - static constexpr int SIGNIFICAND_WIDTH = 24; - - /** - * The exponent the smallest positive float subnormal value would have - * if it could be normalized. - */ - static constexpr int MIN_SUB_EXPONENT = MIN_EXPONENT - (SIGNIFICAND_WIDTH - 1); - - /** - * Bias used in representing a float exponent. - */ - static const int EXP_BIAS = 127; - - /** - * Bit mask to isolate the sign bit of a float. - */ - static const int SIGN_BIT_MASK = 0x80000000; - - /** - * Bit mask to isolate the exponent field of a float. - */ - static const int EXP_BIT_MASK = 0x7F800000; - - /** - * Bit mask to isolate the significand field of a float. - */ - static const int SIGNIF_BIT_MASK = 0x007FFFFF; - - public: - /** - * Float initialization - */ - Float(); - - /** - * Float initialization - * - * @param original - float value - */ - Float(float original); - - /** - * Float initialization - * - * @param target - Float - */ - Float(const Float &target); - - /** - * Float initialization - * - * @param inputString - String - */ - Float(String inputString); - - /** - * Float destructor - */ - ~Float(); - - public: - /** - * Adds two operands - * - * @return Float - */ - Float operator+(const Float &target); - - /** - * Subtracts second operand from the first - * - * @return Float - */ - Float operator-(const Float &target); - - /** - * Multiplies both operands - * - * @return Float - */ - Float operator*(const Float &target); - - /** - * Divides numerator by de-numerator - * - * @return Float - */ - Float operator/(const Float &target); - - /** - * Checks if the values of two operands - * are equal or not, - * - * @return boolean - */ - boolean operator==(const Float &target) const; - - /** - * Checks if the values of two operands - * are equal or not - * - * @return boolean - */ - boolean operator!=(const Float &target) const; - - /** - * Checks if the value of left operand - * is greater than the value of right operand - * - * @return boolean - */ - boolean operator>(const Float &target) const; - - /** - * Checks if the value of left operand - * is less than the value of right operand - * - * @return boolean - */ - boolean operator<(const Float &target) const; - - /** - * Checks if the value of left operand - * is greater than or equal to the value of right operand - * - * @return boolean - */ - boolean operator>=(const Float &target) const; - - /** - * Checks if the value of left operand - * is less than or equal to the value of right operand - * - * @return boolean - */ - boolean operator<=(const Float &target) const; - - /** - * Called Logical AND operator. - * If both the operands are non-zero - * - * @return boolean - */ - boolean operator&&(const Float &target) const; - - /** - * Called Logical OR Operator. - * If any of the two operands is non-zero - * - * @return boolean - */ - boolean operator||(const Float &target) const; - - - /** - * Simple assignment operator, - * Assigns values from right side operands - * to left side operand - * - * @param target - * @return Float - */ - Float& operator=(const Float &target); - - /** - * Add AND assignment operator, - * It adds right operand to the left operand - * and assign the result to left operand - * - * @param target - * @return Float - */ - Float operator+=(const Float &target) const; - - /** - * Subtract AND assignment operator, - * It subtracts right operand from the left operand - * and assign the result to left operand - * - * @param target - * @return Float - */ - Float operator-=(const Float &target) const; - - /** - * Multiply AND assignment operator, - * It multiplies right operand with the left operand - * and assign the result to left operand - * - * @param target - * @return Float - */ - Float operator*=(const Float &target) const; - - /** - * Divide AND assignment operator, - * It divides left operand with the right operand - * and assign the result to left operand - * - * @param target - * @return Float - */ - Float operator/=(const Float &target) const; - - /** - * Short value of Float - * - * @return short - */ - short shortValue() const override; - - /** - * Float value in Float - * - * @return int - */ - int intValue() const override; - - /** - * Float value in Long - * - * @return long - */ - long longValue() const override; - - /** - * Float value in float - * - * @return float - */ - float floatValue() const override; - - /** - * Float value in double - * - * @return double - */ - double doubleValue() const override; - - /** - * Float to String - * - * @return String - */ - string toString() const override; - - /** - * Returns a string representation of the float - * argument. All characters mentioned below are ASCII characters. - * - * @param inputFloat the float to be converted. - * @return a string representation of the argument. - */ - static String toString(float inputFloat); - - /** - * String to Float - * - * @param inputString - * @return Float - */ - static Float parseFloat(String inputString); - - /** - * Returns the value of this Float as a byte - * after a narrowing primitive conversion. - * - * @return the float value represented by this object - * converted to type byte - */ - byte byteValue() const ; - - /** - * Compares the two specified float values. The sign - * of the integer value returned is the same as that of the - * integer that would be returned by the call: - * Float(float1).compareTo(Float(d2)) - * - * @param float1 - the first float to compare - * @param float2 - the second float to compare - * @return the value 0 if float1 is - * numerically equal to float2; a value less than - * 0 if float1 is numerically less than - * float2; and a value greater than 0 - * if float1 is numerically greater than - * float2. - */ - static int compare(float float1, float float2); - - /** - * Compares two Float objects numerically. - * - * @param anotherFloat the Float to be compared. - * @return the value 0 if anotherFloat is - * numerically equal to this Float; a value - * less than 0 if this Float - * is numerically less than anotherFloat; - * and a value greater than 0 if this - * Float is numerically greater than - * anotherFloat. - */ - int compareTo(const Float &anotherFloat) const override; - - /** - * Compares this object against the specified object. - * - * @param obj the object to compare with. - * @return true if the objects are the same; - * false otherwise. - * @see java.lang.Float#floatToLongBits(float) - */ - boolean equals(const Float &object) const; - - /** - * Returns a hash code for this Float object. - * - * @return a hash code value for this object. - */ - int hashCode(); - - /** - * Returns a hash code for a float value; compatible with - * Float.hashCode(). - * - * @param value the value to hash - * @return a hash code value for a float value. - */ - static int hashCode(float floatInput); - - /** - * Returns true if the argument is a finite floating-point - * value; returns false otherwise (for NaN and infinity - * arguments). - * - * @param inputFloat the float value to be tested - * @return true if the argument is a finite - * floating-point value, - * false otherwise. - */ - static boolean isFinite(float inputFloat); - - /** - * Returns true if the specified number is infinitely - * large in magnitude, false otherwise. - * - * @param valueFloat the value to be tested. - * @return true - if the value of the argument is positive - * infinity or negative infinity; - * false - otherwise. - */ - static boolean isInfinite(float valueFloat); - - /** - * Returns true if this Float value is - * infinitely large in magnitude, false otherwise. - * - * @return true - if the value represented by this object is - * positive infinity or negative infinity; - * false - otherwise. - */ - boolean isInfinite(); - - /** - * Returns true if the specified number is a - * Not-a-Number NaN value, false otherwise. - * - * @param valueFloat - the value to be tested. - * @return true - if the value of the argument is NaN; - * false - otherwise. - */ - static boolean isNaN(float valueFloat); - - /** - * Returns true if this Float value is - * a Not-a-Number NaN, false otherwise. - * - * @return true - if the value represented by this - * object is NaN; - * false - otherwise. - */ - boolean isNaN() ; - - /** - * Returns the float value corresponding to a given - * bit representation. - * - * @param bits - any int integer. - * @return the float floating-point value with the same - * bit pattern. - */ - static float intBitsToFloat(int intBitsInput); - - /** - * Returns the smaller of two float values - * as if by calling Math#min(float, float) Math.min. - * - * @param numberFloat the first operand - * @param anotherNumberFloat the second operand - * @return the smaller of a and b. - */ - static float min(float numberFloat, float anotherNumberFloat); - - // TODO(thoangminh): Implement this method later -// /** -// * Returns a hexadecimal string representation of the -// * float argument. All characters mentioned below -// * are ASCII characters. -// * -// * @param inputFloat the float to be converted. -// * @return a hex string representation of the argument. -// */ -// static String toHexString(float inputFloat); - - /** - * Convert from string to float - * - * @param stringInput - the string to be parsed. - * @return a Float object holding the value - * represented by the {String} argument. - * @throws NumberFormatException if the string does not contain a - * parsable number. - */ - static Float valueOf(String stringInput); - - /** - * Assign value to Float variable - * - * @param inputFloat - float value. - * @return a Float instance representing inputFloat. - */ - static Float valueOf(float inputFloat); - - /** - * Returns a representation of the specified floating-point value - * according to the IEEE 754 floating-point "float - * format" bit layout, preserving Not-a-Number NaN values. - * - * @param floatInput - float precision floating-point number. - * @return int - the bits that represent the floating-point number. - */ - static int floatToRawIntBits(float floatInput); - - /** - * Returns a representation of the specified floating-point value - * according to the IEEE 754 floating-point "float - * format" bit layout, preserving Not-a-Number NaN values. - * - * @param floatInput - value a float precision floating-point number. - * @return int - the bits that represent the floating-point number. - */ - static int floatToIntBits(float inputFloat); - - private: - /** - * Convert float to binary 32 bit - * (Single-precision floating-point format - * In IEEE 754-2008) - * - * @param floatInput - * @return String binary 32 bit of input - */ - static String floatToBinary32StringType(float floatInput); - - /** - * Convert binary32StringType To Float - * (Float-precision floating-point format - * In IEEE 754-2008) - * To Float - * - * @param binary32StringTypeInput - * @return float - */ - static float binary32StringTypeToFloat( - String binary32StringTypeInput); - - /** - * Convert intBits To Binary64StringType - * (Float-precision floating-point format - * In IEEE 754-2008) - * - * @param intBitsInput - * @return string - */ - static String intBitsToBinary32StringType(int intBitsInput); - }; - } // namespace Lang -} // namespace Java - -#endif // JAVA_LANG_FLOAT_FLOAT_HPP_ \ No newline at end of file diff --git a/java/lang/InterruptedException/InterruptedException.cpp b/java/lang/InterruptedException/InterruptedException.cpp deleted file mode 100644 index 5f280bac..00000000 --- a/java/lang/InterruptedException/InterruptedException.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// Created by home on 9/26/17. -// - -#include "InterruptedException.hpp" - -InterruptedException::InterruptedException() : Exception() { - -} - -InterruptedException::InterruptedException(String message) : - Exception(message) { - -} - -InterruptedException::InterruptedException(Throwable *cause) : - Exception(cause){ - -} - -InterruptedException::InterruptedException(String message, Throwable *cause) - : Exception(message, cause) { - -} diff --git a/java/lang/InterruptedException/InterruptedException.hpp b/java/lang/InterruptedException/InterruptedException.hpp deleted file mode 100644 index 30690a69..00000000 --- a/java/lang/InterruptedException/InterruptedException.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2016 Food Tiny Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NATIVE_JAVA_LANG_INTERRUPTEDEXCEPTION_HPP -#define NATIVE_JAVA_LANG_INTERRUPTEDEXCEPTION_HPP - -#include "../Exception/Exception.hpp" -#include "../../Lang.hpp" - -namespace Java { - namespace Lang { - class InterruptedException : public Exception { - public: - InterruptedException(); - InterruptedException(String message); - InterruptedException(Throwable *cause); - InterruptedException(String message, Throwable *cause); - }; - } // namespace Lang -} // namespace Java - -#endif //NATIVE_JAVA_LANG_INTERRUPTEDEXCEPTION_HPP diff --git a/java/lang/InterruptedException/InterruptedExceptionTest.cpp b/java/lang/InterruptedException/InterruptedExceptionTest.cpp deleted file mode 100644 index 71b64276..00000000 --- a/java/lang/InterruptedException/InterruptedExceptionTest.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2016 Food Tiny Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "../../../kernel/Test.hpp" - -#include "../InterruptedException/InterruptedException.hpp" - -using namespace Java::Lang; - -TEST(JavaLang, InterruptedExceptionConstructor) { - - InterruptedException interruptedExceptionWithNullMessage; - assertEquals( - "", - interruptedExceptionWithNullMessage.getMessage().toString()); - - InterruptedException interruptedExceptionWithMessage = - InterruptedException( - "InterruptedException with the specified message"); - - assertEquals( - "InterruptedException with the specified message", - interruptedExceptionWithMessage.getMessage().toString()); - - InterruptedException interruptedExceptionWithMessageAndCause = - InterruptedException( - "InterruptedException with the specified message and cause", - &interruptedExceptionWithMessage); - assertEquals( - "InterruptedException with the specified message and cause", - interruptedExceptionWithMessageAndCause.getMessage().toString()); - assertEquals( - "InterruptedException with the specified message", - interruptedExceptionWithMessageAndCause.getCause() - ->getMessage().toString()); - - InterruptedException interruptedExceptionWithCause = - InterruptedException(&interruptedExceptionWithMessageAndCause); - assertEquals("InterruptedException with the specified message and cause", - interruptedExceptionWithCause.getCause() - ->getMessage().toString()); - assertEquals("InterruptedException with the specified message", - interruptedExceptionWithCause.getCause() - ->getCause() - ->getMessage().toString()); -} - -TEST(JavaLang, InterruptedExceptionTryCatch) { - try { - throw InterruptedException("Throw InterruptedException"); - } catch (Exception e) { - assertEquals("Throw InterruptedException", e.getMessage().toString()); - } -} diff --git a/java/lang/String/String.cpp b/java/lang/String/String.cpp deleted file mode 100755 index 81abb661..00000000 --- a/java/lang/String/String.cpp +++ /dev/null @@ -1,852 +0,0 @@ -/** - * Copyright 2017 Food Tiny Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "String.hpp" -#include "../StringIndexOutOfBoundsException/StringIndexOutOfBoundsException.hpp" -#include "../StringBuilder/StringBuilder.hpp" -#include "../StringBuffer/StringBuffer.hpp" -#include "../IllegalArgumentException/IllegalArgumentException.hpp" - -using namespace Java::Lang; - -#define DEFAULT_CAPACITY 32 - -#define DEFAULT_BUFFER_LENGTH 128 - -#define STRING_CONSTRUCTOR_ARRAY \ - if (offset < 0) {\ - throw StringIndexOutOfBoundsException(offset);\ - }\ - if (length < 0) {\ - throw StringIndexOutOfBoundsException(length);\ - }\ - if (offset > array.length - length) {\ - throw StringIndexOutOfBoundsException(offset + length);\ - }\ - this->original = (string) malloc(( length + 1) * sizeof(char));\ - int index;\ - for (index = 0; index < length; offset++, index++) {\ - this->original [index] = array.get(offset);\ - }\ - this->original [length] = '\0';\ - this->size = length;\ - this->capacity = this->size == 0 ? -1 : this->size;\ - -String::String() { - this->original = (string) malloc(DEFAULT_CAPACITY * sizeof(char)); - this->original[0] = '\0'; - this->size = 0; - this->capacity = DEFAULT_CAPACITY; -} - -String::String(const_string target) { - if (target == nullptr) { - target = "\0"; - } - this->original = strdup(target); - this->size = lengthPointerChar((string) target); - this->capacity = this->size == 0 ? -1 : this->size; -} - -String::String(string target) { - if (target == nullptr) { - target = (string) "\0"; - } - this->original = strdup(target); - this->size = lengthPointerChar(target); - this->capacity = this->size == 0 ? -1 : this->size; -} - -String::String(string original, int length) { - this->original = strndup(original, (size_t) length); - this->size = length; - this->capacity = this->size == 0 ? -1 : this->size; -} - -String::String(Array &charArray) { - this->original = charArray.toString(); - this->size = charArray.length; - this->capacity = this->size == 0 ? -1 : this->size; -} - -String::String(Array &byteArray) { - Array chars; - for (byte byte : byteArray) { - chars.push((char) byte); - } - this->original = strdup(String::fromCharArray(chars).toString()); - this->size = chars.length; - this->capacity = this->size == 0 ? -1 : this->size; -} - -String::String(const String &target) { - this->original = strdup(target.original); - this->size = target.size; - this->capacity = this->size == 0 ? -1 : this->size; - this->hash = target.hash; -} - -String::String(const std::string &target) { - this->original = (string) strdup(target.c_str()); - this->size = (int) target.size(); - this->capacity = this->size == 0 ? -1 : this->size; -} - -String::String(const StringBuilder &stringBuilder) { - this->original = strdup(stringBuilder.toString()); - this->size = stringBuilder.length(); - this->capacity = this->size == 0 ? -1 : this->size; -} - -String::String(const StringBuffer &stringBuffer) { - this->original = strdup(stringBuffer.getValue()); - this->size = stringBuffer.length(); - this->capacity = this->size == 0 ? -1 : this->size; -} - -String::String(Array &array, int offset, int length) { - STRING_CONSTRUCTOR_ARRAY -} - -String::String(Array &array, int offset, int length) { - STRING_CONSTRUCTOR_ARRAY -} - -String::~String() { - free(original); -} - -int String::getSize() const { - return this->size; -} - -String String::clone() { - string pointerHolder = strdup(this->original); - String result = pointerHolder; - free(pointerHolder); - return result; -} - -char String::charAt(int index) const { - if (index < 0 || index > this->size - 1) { - throw StringIndexOutOfBoundsException("String index out of range"); - } - return (this->original[ index ]); -} - -int String::compareTo(const String &anotherString) const { - return strcmp(this->original, anotherString.original); -} - -int String::compareToIgnoreCase(const String &anotherString) const { - return strcasecmp(this->original, anotherString.original); -} - -String String::concat(String target) { - string targetValue = target.original; - int targetLength = target.size; - int newLength = this->size + target.size; - STRING_OPERATOR_PLUS - return *this; -} - -boolean String::contains(const CharSequence &charSequence) { - return (stringIndex(this->original, charSequence.toString(), 1) != NOT_FOUND); -} - -Array String::getBytes() const { - Array bytes; - String originalString = this->original; - for (char character : originalString.toCharArray()) { - bytes.push((byte) character); - } - return bytes; -} - -String String::getStringFromIndex(int index) const { - if (index < 0 || index > this->size - 1) { - throw StringIndexOutOfBoundsException(index); - } - return &(this->original[ index ]); -} - -boolean String::endsWith(const String &suffixString) const { - return (bool) stringEndswith(this->original, suffixString.original); -} - -String String::fromCharArray(Array &charArray) { - string str = (string) malloc((charArray.length + 1) * sizeof(char)); -#ifdef LINUX - register -#endif - int index = 0; - for (char character : charArray) { - str[ index++ ] = character; - } - str[ index ] = '\0'; - String result = str; - free(str); - return result; -} - -int String::indexOf(int character) const { - string pointerHolder = stringFromChar((char) character); - int result = stringIndex(this->original, pointerHolder, 1); - free(pointerHolder); - return result; -} - -int String::indexOf(int character, int fromIndex) const { - if (fromIndex > this->size) { - return -1; - } - if (fromIndex < 0) { - return this->indexOf(character); - } - -#ifdef LINUX - register -#endif - int index = 0; - - for (index = fromIndex; index < this->size; index++) { - if (this->original[ index ] == (char) character) { - return index; - } - } - return -1; -} - -int String::indexOf(String subString) const { - return stringIndex(this->original, subString.original, 1); -} - -int String::indexOf(String subString, int fromIndex) const { - if (fromIndex < 0) { - return this->indexOf(subString); - } - if (fromIndex > this->size - 1) { - return -1; - } - string stringFromIndex = stringFrom(this->original, fromIndex); - int result = stringIndex(stringFromIndex, subString.original, 1); - free(stringFromIndex); - if (result == -1) { - return result; - } - result = fromIndex + result; - return result; -} - -boolean String::isEmpty() const { - return (boolean) isEmptyString(this->original); -} - -int String::lastIndexOf(int character) { -#ifdef LINUX - register -#endif - int index = 0; - - for (index = this->size - 1; index >= 0; index--) { - if (this->charAt(index) == (char) character) { - return index; - } - } - return -1; -} - -int String::lastIndexOf(int character, int fromIndex) { - if (fromIndex < 0) { - return -1; - } - if (fromIndex > this->size - 1) { - return this->lastIndexOf(character); - } -#ifdef LINUX - register -#endif - int index = 0; - - for (index = fromIndex - 1; index >= 0; index--) { - if (this->charAt(index) == (char) character) { - return index; - } - } - return -1; -} - -int String::lastIndexOf(String subString) const { - string reversedString = stringReverse(subString.toString()); - string currentReversedString = stringReverse(this->toString()); - int result = stringIndex(currentReversedString, reversedString, 1); - free(reversedString); - free(currentReversedString); - if (result == NOT_FOUND) { - return result; - } - // Re-calculate first character of subString - result = this->size - (result + subString.size); - return result; -} - -int String::lastIndexOf(String subString, int fromIndex) const { - if (fromIndex < 0) { - return -1; - } - if (fromIndex > this->size - 1) { - return this->lastIndexOf(subString); - } - string thisStringReversed = stringReverse(this->original); - string subStringFromIndex = &(thisStringReversed)[ this->size - fromIndex - subString.size]; - string reversedString = stringReverse(subString.toString()); - // string currentReversedString = stringReverse(subStringFromIndex); - int result = stringIndex(subStringFromIndex, reversedString, 1); - free(reversedString); - free(thisStringReversed); - if (result == NOT_FOUND) { - return result; - } - // Re-calculate first character of str - result = fromIndex - result; - return result; -} - -int String::length() const { - return this->size; -} - -// boolean String::matches(String regex) const { -// int result = stringMatches(this->original, regex.toString()); -// return result == true; -// } - -String String::replace(char oldChar, char newChar) const { - string oldString = stringFromChar(oldChar); - string newString = stringFromChar(newChar); - string pointerHolder = stringReplace(this->original, oldString, newString); - String result = pointerHolder; - free(pointerHolder); - free(oldString); - free(newString); - return result; -} - -String String::replaceAll(String regex, String replacement) const { - // TODO (anhnt) fix this later, temporary use replace, need Pattern - return replace(regex, replacement); -} - -Array String::split(String regex) const { - // TODO (anhnt) fix this later, temporary use replace, need Pattern - string *splitStrings = stringSplit(this->original, regex.toString()); - Array strings; - -#ifdef LINUX - register -#endif - int index = 0; - - int splitStringsLength = lengthPointerPointerChar(splitStrings); - for (index = 0; index < splitStringsLength; index++) { - strings.push(splitStrings[ index ]); - } - - freePointerPointerChar(splitStrings); - return strings; -} - -boolean String::startsWith(String prefix) const { - return (bool) stringStartswith(this->original, prefix.original); -} - -boolean String::startsWith(String prefix, int thisOffset) const { - if (this->original == nullptr || - prefix.original == nullptr || thisOffset < 0) { - return false; - } - int originalLength = lengthPointerChar(this->original); - int prefixLength = lengthPointerChar(prefix.original); - if (originalLength < prefixLength || - thisOffset > (originalLength - prefixLength)) { - return false; - } -#ifdef LINUX - register -#endif - int firstIndex = 0; - -#ifdef LINUX - register -#endif - int secondIndex = thisOffset; - for (; firstIndex < prefixLength; firstIndex++) { - if (prefix.original[ firstIndex ] != this->original[ secondIndex ]) { - return false; - } - secondIndex++; - } - return true; -} - -Array String::toCharArray() const { - Array chars; - -#ifdef LINUX - register -#endif - int index = 0; - - while (this->original[ index ] != '\0') { - chars.push(this->original[ index++ ]); - } - return chars; -} - -string String::toString() const { - return this->original; -} - -String String::toLowerCase() const { - string holdPointer = stringLower(this->original); - String result = holdPointer; - free(holdPointer); - return result; -} - -String String::toUpperCase() { - string holdPointer = stringUpper(this->original); - String result = holdPointer; - free(holdPointer); - return result; -} - -String String::trim() { - string holdPointer = stringTrim(this->original); - String result = holdPointer; - free(holdPointer); - return result; -} - -String String::valueOf(boolean target) { - if (target) { - return (string) "true"; - } - return (string) "false"; -} - -String String::valueOf(char charValue) { - string pointerHolder = stringFromChar(charValue); - String result = pointerHolder; - free(pointerHolder); - return result; -} - -String String::valueOf(string stringValue) { - if (isEmptyString(stringValue) != 0) { - return (string) ""; - } - return stringValue; -} - -String String::valueOf(short shortValue) { - string pointerHolder = stringFromShort(shortValue); - String result = pointerHolder; - free(pointerHolder); - return result; -} - -String String::valueOf(int intValue) { - string pointerHolder = stringFromInt(intValue); - String result = pointerHolder; - free(pointerHolder); - return result; -} - -String String::valueOf(long longValue) { - string pointerHolder = stringFromLong(longValue); - String result = pointerHolder; - free(pointerHolder); - return result; -} - -String String::valueOf(float floatValue) { - string pointerHolder = stringFromFloat(floatValue); - String result = pointerHolder; - free(pointerHolder); - return result; -} - -String String::valueOf(double doubleValue) { - string pointerHolder = stringFromDouble(doubleValue); - String result = pointerHolder; - free(pointerHolder); - return result; -} - -String String::subString(int beginIndex) const { - return this->subString(beginIndex, this->size); -} - -String String::subString(int beginIndex, int endIndex) const { - string holder = stringFromTo(this->original, beginIndex, endIndex - 1); - String result = holder; - free(holder); - return result; -} - -boolean String::contentEquals(const CharSequence &charSequence) { - // TODO (anhnt) instanceof return false -/* if (instanceof(&charSequence)) { - std::mutex mutex; - std::lock_guard guard(mutex); - return strcmp(this->original, charSequence.toString()) == 0; - }*/ - return strcmp(this->original, charSequence.toString()) == 0; -} - -String String::copyValueOf(Array &charArray) { - return String(charArray); -} - -String String::copyValueOf(Array &charArray, int offset, int count) { - return String(charArray, offset, count); -} - -boolean String::equalsIgnoreCase(String anotherString) { - return this->compareToIgnoreCase(anotherString) == 0; -} - -long String::hashCode() const { - int hashCode = this->hash; - if (hashCode == 0 && this->size > 0) { - for (int i = 0; i < this->size; i++) { - hashCode = 31 * hashCode + this->original[i]; - } - this->hash = hashCode; - } - return hashCode; -} - -boolean String::regionMatches(int thisOffset, - String otherString, int otherOffset, int len) { - - return this->regionMatches(false, thisOffset, otherString, otherOffset, len); -} - -boolean String::regionMatches(boolean ignoreCase, int thisOffset, - String otherString, int otherOffset, int len) { - - String thisString = this->subString(thisOffset, thisOffset + len); - otherString = otherString.subString(otherOffset, otherOffset + len); - if (ignoreCase) { - return thisString.compareToIgnoreCase(otherString) == 0; - } - return thisString.compareTo(otherString) == 0; -} - -void String::getChars(int sourceBegin, int sourceEnd, - Array &destination, int destinationBegin) { - if (sourceBegin < 0) { - throw StringIndexOutOfBoundsException(sourceBegin); - } - - if (sourceBegin > sourceEnd) { - throw StringIndexOutOfBoundsException(sourceEnd - sourceBegin); - } - - if (sourceEnd > this->size) { - throw StringIndexOutOfBoundsException(sourceEnd); - } - - if (destinationBegin < 0) { - throw StringIndexOutOfBoundsException(destinationBegin); - } - - if (destinationBegin + (sourceEnd - sourceBegin) > destination.length) { - throw StringIndexOutOfBoundsException(destinationBegin - + (sourceEnd - sourceBegin)); - } - - int index; - int len = sourceEnd - sourceBegin; - for (index = 0; index < destinationBegin + len; index++) { - if (index >= destinationBegin && index < destinationBegin + len) { - destination[index] = this->charAt(sourceBegin); - sourceBegin++; - } else { - destination[index] = destination[index]; - } - } -} - -String String::replace(CharSequence &target, CharSequence &replacement) const { - string oldString = target.toString(); - string newString = replacement.toString(); - string pointerHolder = stringReplace(this->original, oldString, newString); - String result = pointerHolder; - free(pointerHolder); - return result; -} - -String String::replaceFirst(String regex, String replacement) const { - // TODO (anhnt) fix this later, temporary, need Pattern - int stringWithFirstRegexLength = this->indexOf(regex) + regex.length(); - String stringWithFirstRegex = this->subString(0, stringWithFirstRegexLength); - String remainString = this->getStringFromIndex(stringWithFirstRegexLength); - stringWithFirstRegex = stringWithFirstRegex.replace(regex, replacement); - return stringWithFirstRegex + remainString; -} - -Array String::split(String regex, int limit) const { - // TODO (anhnt) fix this later, temporary, need Pattern - Array stringArrayNoLimit = this->split(regex); - if (limit == 1) { - return Array{*this}; - } - if (limit > stringArrayNoLimit.length || limit <= 0) { - return stringArrayNoLimit; - } - int indexOfRegexBelowLimit = stringIndex(this->original, regex.toString(), limit - 1); - int remainStringLength = indexOfRegexBelowLimit + regex.length(); - String remainString = this->getStringFromIndex(remainStringLength); - Array stringArrayLimit; -#ifdef LINUX - register -#endif - int index; - for (index = 0; index < limit - 1; index++) { - stringArrayLimit.push(stringArrayNoLimit[index]); - } - stringArrayLimit.push(remainString); - return stringArrayLimit; -} - -String String::print(const String &format, short value) { - String result; - char buffer[DEFAULT_BUFFER_LENGTH] = {0}; - const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); - if (length > 0) { - result = String(buffer, length); - } - return result; -} - -String String::print(const String &format, int value) { - String result; - char buffer[DEFAULT_BUFFER_LENGTH] = {0}; - const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); - if (length > 0) { - result = String(buffer, length); - } - return result; -} - -String String::print(const String &format, long value) { - String result; - char buffer[DEFAULT_BUFFER_LENGTH] = {0}; - const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); - if (length > 0) { - result = String(buffer, length); - } - return result; -} - -String String::print(const String &format, long long value) { - String result; - char buffer[DEFAULT_BUFFER_LENGTH] = {0}; - const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); - if (length > 0) { - result = String(buffer, length); - } - return result; -} - -String String::print(const String &format, unsigned short value) { - String result; - char buffer[DEFAULT_BUFFER_LENGTH] = {0}; - const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); - if (length > 0) { - result = String(buffer, length); - } - return result; -} - -String String::print(const String &format, unsigned int value) { - String result; - char buffer[DEFAULT_BUFFER_LENGTH] = {0}; - const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); - if (length > 0) { - result = String(buffer, length); - } - return result; -} - -String String::print(const String &format, unsigned long value) { - String result; - char buffer[DEFAULT_BUFFER_LENGTH] = {0}; - const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); - if (length > 0) { - result = String(buffer, length); - } - return result; -} - -String String::print(const String &format, unsigned long long value) { - String result; - char buffer[DEFAULT_BUFFER_LENGTH] = {0}; - const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); - if (length > 0) { - result = String(buffer, length); - } - return result; -} - -String String::print(const String &format, double value) { - String result; - char buffer[DEFAULT_BUFFER_LENGTH] = {0}; - const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); - if (length > 0) { - result = String(buffer, length); - } - return result; -} - -String String::print(const String &format, float value) { - String result; - char buffer[DEFAULT_BUFFER_LENGTH] = {0}; - const int length = snprintf(buffer, sizeof(buffer), format.toString(), value); - if (length > 0) { - result = String(buffer, length); - } - return result; -} - -String String::print(const String &format, string value) { - String result; - char* buffer = (char*)calloc(DEFAULT_BUFFER_LENGTH, sizeof(char)); - int length = snprintf(buffer, DEFAULT_BUFFER_LENGTH, format.toString(), value); - - if (length > DEFAULT_BUFFER_LENGTH) { - free(buffer); - buffer = (char*)calloc(++length, sizeof(char)); - length = snprintf(buffer, (size_t)length, format.toString(), value); - } - - if (length > 0) { - result = String(buffer, length); - } - - free(buffer); - return result; -} - -String String::print(const String &format, Short value) { - return String::print(format, value.shortValue()); -} - -String String::print(const String &format, Integer value) { - return String::print(format, value.intValue()); -} - -String String::print(const String &format, Long value) { - return String::print(format, value.longValue()); -} - -String String::print(const String &format, Float value) { - return String::print(format, value.floatValue()); -} - -String String::print(const String &format, Double value) { - return String::print(format, value.doubleValue()); -} - -String String::print(const String &format, String value) { - return String::print(format, value.toString()); -} - -String String::format(const String &format) { - const String pattern = "%([[:digit:]]+)?([-#+0 ]*)?([[:digit:]]+)?(\\" \ - ".[[:digit:]]+)?(l){0,2}([diuoxXfFeEgGaAcspn%])"; - String result; - string inputStringPtr = format.toString(); - int inputStringLength = format.getSize(); - int inputStringOffset = 0; - int errorCode = 0; - regex_t regex; - - errorCode = regcomp(®ex, pattern.toString(), REG_EXTENDED); - while (errorCode == 0 && inputStringOffset < format.getSize()) { - regmatch_t matchedResult[16] = {0}; // max 16 groups - errorCode = regexec(®ex, inputStringPtr, 16, matchedResult, 0); - if (errorCode != 0) { - result += String(inputStringPtr, inputStringLength); - break; - } - - int unmatchedStringLength = matchedResult[0].rm_so; - int matchedStringLength = matchedResult[0].rm_eo - matchedResult[0].rm_so; - - if (unmatchedStringLength > 0) { - result += String(inputStringPtr, unmatchedStringLength); - } - - if (matchedStringLength > 0) { - String matchedString(inputStringPtr + unmatchedStringLength, matchedStringLength); - if (matchedString.charAt(matchedString.getSize() - 1) != '%') { - regfree(®ex); - throw IllegalArgumentException("Missing arguments."); - } else { - result += "%"; - } - } - - inputStringPtr += matchedResult[0].rm_eo; - inputStringOffset += matchedResult[0].rm_eo; - inputStringLength -= matchedResult[0].rm_eo; - } - - regfree(®ex); - return result; -} - -String String::valueOf(unsigned long longValue) { - string pointerHolder = stringFromLong(longValue); - String result = pointerHolder; - free(pointerHolder); - return result; -} - -String String::valueOf(const_string constStringValue) { - if (isEmptyString(constStringValue) != 0) { - return (string) ""; - } - return constStringValue; -} - -String String::valueOf(String stringValue) { - return stringValue; -} diff --git a/java/lang/Thread/ThreadTest.cpp b/java/lang/Thread/ThreadTest.cpp deleted file mode 100755 index 87014c72..00000000 --- a/java/lang/Thread/ThreadTest.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/** - * Copyright (c) 2016 Food Tiny Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "../../../kernel/Test.hpp" - -#include "Thread.hpp" -#include "../InterruptedException/InterruptedException.hpp" - -using namespace std; -using namespace Java::Lang; - -class RunnableTarget1 : public virtual Runnable { -public: - long value; - - RunnableTarget1() { - value = 0; - } - - ~RunnableTarget1() { - - } - - void run() override { - value = 0xb00b; - Thread::sleep(1000); - } -}; - -class RunnableTarget2 : public virtual Runnable { -public: - long value; - - RunnableTarget2() { - value = 0; - } - - ~RunnableTarget2() { - - } - - void run() override { - value = 0xb00b; - Thread::sleep(1000); - value = 0xbeef; - } -}; - -class RunnableTarget3 : public virtual Runnable { -public: - unsigned long tid; - - RunnableTarget3() { - - } - - ~RunnableTarget3() { - - } - - void run() override { - tid = (unsigned long)pthread_self(); - } -}; - -TEST(JavaLang, ThreadRun) { - long expect = 0xb00b; - long result = 0; - RunnableTarget1* target = new RunnableTarget1(); - - { - Thread thread(target); - thread.start(); - thread.join(); - result = target->value; - } - - delete target; - assertEquals(expect, result); -} - -TEST(JavaLang, ThreadSetName) { - Thread thread; - - String name = "Thread 1"; - thread.setName(name); - assertEquals("Thread 1", thread.getName().toString()); - - thread.setName("Thread 2"); - assertEquals("Thread 2", thread.getName().toString()); -} - -TEST(JavaLang, ThreadGetName) { - Thread thread; - - String name = "Thread 1"; - thread.setName(name); - assertEquals("Thread 1", thread.getName().toString()); - - thread.setName("Thread 2"); - assertEquals("Thread 2", thread.getName().toString()); -} - -TEST(JavaLang, ThreadGetThreadId) { - RunnableTarget3 target; - Thread thread(&target); - - thread.start(); - thread.join(); - - String expect = String::format("%lld", target.tid); - String result = String::format("%lld", thread.getId()); - - assertEquals(expect.toString(), result.toString()); -} - -TEST(JavaLang, ThreadJoinWithTimeout) { - long expect1 = 0xb00b; - long result1 = 0; - long expect2 = 0xbeef; - long result2 = 0; - - { - RunnableTarget2 target; - Thread thread(&target); - thread.start(); - - // - thread.join(100); - result1 = target.value; - - // - thread.join(); - result2 = target.value; - } - - assertEquals(expect1, result1); - assertEquals(expect2, result2); -} From 1cd6bc52b367be25b66949ad532da943ec90d74e Mon Sep 17 00:00:00 2001 From: sonda Date: Sun, 25 Mar 2018 22:06:13 +0700 Subject: [PATCH 41/41] #231 Implement Thread::detach(). --- library/Java/Lang/Thread/Thread.cpp | 9 +++++++ library/Java/Lang/Thread/Thread.hpp | 3 +++ library/Java/Lang/Thread/ThreadTest.cpp | 34 ++++++++++++++++++------- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/library/Java/Lang/Thread/Thread.cpp b/library/Java/Lang/Thread/Thread.cpp index 887989ed..1cbd011e 100755 --- a/library/Java/Lang/Thread/Thread.cpp +++ b/library/Java/Lang/Thread/Thread.cpp @@ -118,6 +118,15 @@ void Thread::join(long millis) { } } +void Thread::detach() { + if (this->detached) { + throw IllegalArgumentException("Detached thread"); + } else { + this->threadObject.detach(); + this->detached = true; + } +} + void Thread::sleep(long millis) { this_thread::sleep_for(chrono::milliseconds(millis)); } diff --git a/library/Java/Lang/Thread/Thread.hpp b/library/Java/Lang/Thread/Thread.hpp index 37aeeeb5..86cc8964 100755 --- a/library/Java/Lang/Thread/Thread.hpp +++ b/library/Java/Lang/Thread/Thread.hpp @@ -39,6 +39,7 @@ namespace Java { class Thread : public Object, public virtual Runnable { private: boolean alive = false; + boolean detached = false; String name; unsigned long tid = 0; Runnable *target = NULL; @@ -100,6 +101,8 @@ namespace Java { void join(long millis); + void detach(); + static void sleep(long millis); static Thread* currentThread(); diff --git a/library/Java/Lang/Thread/ThreadTest.cpp b/library/Java/Lang/Thread/ThreadTest.cpp index c5fb6796..34d87cc7 100755 --- a/library/Java/Lang/Thread/ThreadTest.cpp +++ b/library/Java/Lang/Thread/ThreadTest.cpp @@ -31,10 +31,6 @@ using namespace std; using namespace Java::Lang; -TEST (JavaLangThread, Sleep) { - Thread::sleep(1); -} - class RunnableTarget1 : public virtual Runnable { public: long value; @@ -95,7 +91,11 @@ void runnableFunc() { Thread::sleep(100); } -TEST(JavaLang, ThreadRun) { +TEST (JavaLangThread, Sleep) { + Thread::sleep(1); +} + +TEST(JavaLangThread, ThreadRun) { { long expect = 0xb00b; long result = 0; @@ -137,7 +137,7 @@ TEST(JavaLang, ThreadRun) { } -TEST(JavaLang, ThreadSetName) { +TEST(JavaLangThread, ThreadSetName) { Thread thread; String name = "Thread 1"; @@ -148,7 +148,7 @@ TEST(JavaLang, ThreadSetName) { assertEquals("Thread 2", thread.getName().toString()); } -TEST(JavaLang, ThreadGetName) { +TEST(JavaLangThread, ThreadGetName) { Thread thread; String name = "Thread 1"; @@ -159,7 +159,7 @@ TEST(JavaLang, ThreadGetName) { assertEquals("Thread 2", thread.getName().toString()); } -TEST(JavaLang, ThreadGetThreadId) { +TEST(JavaLangThread, ThreadGetThreadId) { RunnableTarget3 target; Thread thread(&target); @@ -172,7 +172,7 @@ TEST(JavaLang, ThreadGetThreadId) { assertEquals(expect.toString(), result.toString()); } -TEST(JavaLang, ThreadJoinWithTimeout) { +TEST(JavaLangThread, ThreadJoinWithTimeout) { long expect1 = 0xb00b; long result1 = 0; long expect2 = 0xbeef; @@ -194,4 +194,20 @@ TEST(JavaLang, ThreadJoinWithTimeout) { assertEquals(expect1, result1); assertEquals(expect2, result2); +} + +TEST(JavaLangThread, ThreadDetach) { + { + Thread thread([](){ + Thread::sleep(100); + }); + + try { + thread.start(); + thread.detach(); + thread.join(); + } catch (IllegalArgumentException &e) { + assertEquals("Detached thread", e.getMessage()); + } + } } \ No newline at end of file