Kajetan Johannes Hammerle пре 3 месеци
родитељ
комит
424bf8008e
4 измењених фајлова са 87 додато и 5 уклоњено
  1. 10 1
      include/core/thread/Thread.hpp
  2. 0 1
      include/core/utils/Buffer.hpp
  3. 46 3
      src/Thread.cpp
  4. 31 0
      test/modules/ThreadTests.cpp

+ 10 - 1
include/core/thread/Thread.hpp

@@ -7,9 +7,18 @@
 
 namespace Core {
     class Thread final {
-        AlignedData<8, 8> thread{};
+        AlignedData<8, 8> thread;
 
     public:
+        Thread();
+        Thread(const Thread& other) = delete;
+        Thread(Thread&& other);
+        ~Thread();
+        Thread& operator=(const Thread& other) = delete;
+        Thread& operator=(Thread&& other);
+
+        void swap(Thread& other);
+
         using Function = int (*)(void*);
 
         check_return Error start(Function f, void* p);

+ 0 - 1
include/core/utils/Buffer.hpp

@@ -33,7 +33,6 @@ namespace Core {
 
         void clear();
 
-    private:
         void swap(Buffer& other);
     };
 }

+ 46 - 3
src/Thread.cpp

@@ -2,6 +2,42 @@
 
 #include <threads.h>
 
+#include "core/utils/Meta.hpp"
+#include "core/utils/Utility.hpp"
+
+Core::Thread::Thread() : thread() {
+}
+
+Core::Thread::Thread(Thread&& other) : thread() {
+    swap(other);
+}
+
+static bool doesExist(thrd_t* t) {
+    thrd_t zero{};
+    return !Core::memoryCompare(&zero, t, sizeof(thrd_t));
+}
+
+static void reset(thrd_t* t) {
+    Core::memorySet(t, 0, sizeof(thrd_t));
+}
+
+Core::Thread::~Thread() {
+    if(doesExist(thread.as<thrd_t>())) {
+        (void)join(nullptr);
+    }
+}
+
+Core::Thread& Core::Thread::operator=(Thread&& other) {
+    if(this != &other) {
+        if(doesExist(thread.as<thrd_t>())) {
+            (void)join(nullptr);
+        }
+        reset(thread.as<thrd_t>());
+        swap(other);
+    }
+    return *this;
+}
+
 check_return Core::Error Core::Thread::start(Function f, void* p) {
     CORE_ASSERT_ALIGNED_DATA(thread, thrd_t);
     return thrd_create(thread.as<thrd_t>(), f, p) != thrd_success
@@ -10,7 +46,14 @@ check_return Core::Error Core::Thread::start(Function f, void* p) {
 }
 
 check_return Core::Error Core::Thread::join(int* returnValue) {
-    return thrd_join(*thread.as<thrd_t>(), returnValue) != thrd_success
-               ? Error::THREAD_ERROR
-               : Error::NONE;
+    int e = thrd_join(*thread.as<thrd_t>(), returnValue);
+    reset(thread.as<thrd_t>());
+    return e != thrd_success ? Error::THREAD_ERROR : Error::NONE;
+}
+
+void Core::Thread::swap(Thread& other) {
+    thrd_t tmp;
+    memoryCopy(&tmp, thread.as<thrd_t>(), sizeof(thrd_t));
+    memoryCopy(thread.as<thrd_t>(), other.thread.as<thrd_t>(), sizeof(thrd_t));
+    memoryCopy(other.thread.as<thrd_t>(), &tmp, sizeof(thrd_t));
 }

+ 31 - 0
test/modules/ThreadTests.cpp

@@ -41,8 +41,39 @@ static void testJoinWithoutStart() {
     CORE_TEST_EQUAL(Core::Error::THREAD_ERROR, t.join(nullptr));
 }
 
+static void testAutoJoin() {
+    Core::Thread t;
+    CORE_TEST_ERROR(t.start([](void*) { return 0; }, nullptr));
+}
+
+static void testMove() {
+    Core::Thread t;
+    CORE_TEST_ERROR(t.start([](void*) { return 0; }, nullptr));
+    Core::Thread m = Core::move(t);
+    CORE_TEST_ERROR(m.join());
+}
+
+static void testMoveAssignment() {
+    Core::Thread t;
+    CORE_TEST_ERROR(t.start([](void*) { return 0; }, nullptr));
+    Core::Thread m;
+    m = Core::move(t);
+    CORE_TEST_ERROR(m.join());
+}
+
+static void testDoubleJoin() {
+    Core::Thread t;
+    CORE_TEST_ERROR(t.start([](void*) { return 0; }, nullptr));
+    CORE_TEST_ERROR(t.join(nullptr));
+    CORE_TEST_EQUAL(Core::Error::THREAD_ERROR, t.join(nullptr));
+}
+
 void Core::testThread() {
     testStart();
     testLambda();
     testJoinWithoutStart();
+    testAutoJoin();
+    testMove();
+    testMoveAssignment();
+    testDoubleJoin();
 }