libvideorender: CF2 new git for libvideorender [1/1]

PD#SWPL-134637

Problem:
new git for libvideorender

Solution:
new git for libvideorender

Verify:
ap222

Change-Id: I23196f65a8a94fe6244df5bb45d676623b10d8cc
Signed-off-by: fei.deng <fei.deng@amlogic.com>
diff --git a/tools/Thread.cpp b/tools/Thread.cpp
new file mode 100644
index 0000000..b472a80
--- /dev/null
+++ b/tools/Thread.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2021 Amlogic Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <assert.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <string.h>
+#include <errno.h>
+#include "Thread.h"
+namespace Tls {
+pthread_t getThreadId()
+{
+    return (pthread_t)pthread_self();
+}
+
+Thread::Thread()
+    :mThread(pthread_t(-1)),
+    mStatus(0),
+    mExitPending(false),
+    mRunning(false),
+    mPriority(0)
+{
+}
+
+Thread::~Thread()
+{
+}
+
+void Thread::setThreadPriority(int priority)
+{
+    mPriority = priority;
+}
+
+void Thread::readyToRun()
+{
+
+}
+
+void Thread::readyToExit()
+{
+
+}
+
+int Thread::run(const char* name)
+{
+    std::unique_lock<std::mutex> lck(mMutex);
+    if (mRunning) {
+        // thread already started
+        return -1;
+    }
+
+    mStatus = 0;
+    mExitPending = false;
+    mThread = pthread_t(-1);
+    memset(mThreadName, '\0', sizeof(mThreadName));
+    if (name) {
+        if (strlen(name) <= sizeof(mThreadName)-1) {
+            strcpy(mThreadName, name);
+        } else {
+            strncpy(mThreadName, name, sizeof(mThreadName)-1);
+        }
+    } else {
+        strcpy(mThreadName, "unknown");
+    }
+
+    //set running at this ,if request exit immediately when invoking run
+    //this will let requestExitAndWait block until thread running
+    mRunning = true;
+
+    int res;
+    res = _createThread(_threadLoop);
+    if (res != 0) {
+        mStatus = -1;   // something happened!
+        mRunning = false;
+        mThread = pthread_t(-1);
+        mCond.notify_all();
+        return -1;
+    }
+    return 0;
+}
+
+int Thread::_createThread(pthread_entry_func entryFunction)
+{
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+    errno = 0;
+    int result = pthread_create(&mThread, &attr,
+                    (pthread_entry_func)entryFunction, (void *)this);
+    pthread_attr_destroy(&attr);
+    if (result != 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+void* Thread::_threadLoop(void* user)
+{
+    Thread* const self = static_cast<Thread*>(user);
+    struct sched_param schedParam;
+    int maxPriority,miniPriority;
+
+    self->mRunning = true;
+    if (self->mPriority > 0) {
+        maxPriority = sched_get_priority_max(SCHED_FIFO);
+        miniPriority = sched_get_priority_min(SCHED_FIFO);
+        schedParam.sched_priority = self->mPriority;
+        if (self->mPriority > maxPriority) {
+            schedParam.sched_priority = maxPriority;
+        } else if (self->mPriority < miniPriority) {
+            schedParam.sched_priority = miniPriority;
+        }
+        pthread_setschedparam(pthread_self(), SCHED_FIFO, &schedParam );
+    }
+    pthread_setname_np(pthread_self(), self->mThreadName);
+
+    self->readyToRun();
+
+    //maybe readyToRun will do something that take a long time,
+    //so we need to check exit thread status
+    if (self->mExitPending) {
+        goto exit;
+    }
+
+    do {
+        bool result = true;
+
+        result = self->threadLoop();
+        if (result == false || self->mExitPending) {
+            break;
+        }
+    } while(self->mRunning);
+
+exit:
+    //must call readyToExit before set mRunning to false
+    self->readyToExit();
+    std::unique_lock<std::mutex> lck(self->mMutex);
+    self->mExitPending = true;
+    // clear thread ID so that requestExitAndWait() does not exit if
+    // called by a new thread using the same thread ID as this one.
+    self->mThread = pthread_t(-1);
+    self->mRunning = false;
+    // note that interested observers blocked in requestExitAndWait are
+    // awoken by broadcast, but blocked on mLock until break exits scope
+    self->mCond.notify_all();
+    return 0;
+}
+
+void Thread::requestExit()
+{
+    std::lock_guard<std::mutex> lck(mMutex);
+    mExitPending = true;
+}
+
+int Thread::requestExitAndWait()
+{
+    std::unique_lock<std::mutex> lck(mMutex);
+    if (mThread == getThreadId()) {
+        return -1;
+    }
+
+    mExitPending = true;
+
+    while (mRunning == true) {
+        mCond.wait(lck);
+    }
+    // This next line is probably not needed any more, but is being left for
+    // historical reference. Note that each interested party will clear flag.
+    mExitPending = false;
+    return mStatus;
+}
+
+int Thread::join()
+{
+    std::unique_lock<std::mutex> lck(mMutex);
+    if (mThread == getThreadId()) {
+        return -1;
+    }
+
+    while (mRunning == true) {
+        mCond.wait(lck);
+    }
+    return mStatus;
+}
+
+bool Thread::isRunning() const {
+    std::lock_guard<std::mutex> lck(mMutex);
+    return mRunning;
+}
+
+bool Thread::isExitPending() const
+{
+    std::lock_guard<std::mutex> lck(mMutex);
+    return mExitPending;
+}
+}
\ No newline at end of file