blob: 91623dca8b219ea50a2bb292e9a4520d744ad134 [file] [log] [blame]
/*
* Copyright (C) 2017-2018 Intel 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.
*/
#pragma once
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
namespace icamera {
typedef std::mutex Mutex;
typedef std::lock_guard<std::mutex> AutoMutex;
typedef std::unique_lock<std::mutex> ConditionLock;
enum {
PRIORITY_LOWEST = 19,
PRIORITY_BACKGROUND = 10,
PRIORITY_NORMAL = 0,
PRIORITY_FOREGROUND = -2,
PRIORITY_DISPLAY = -4,
PRIORITY_URGENT_DISPLAY = -8,
PRIORITY_AUDIO = -16,
PRIORITY_URGENT_AUDIO = -19,
PRIORITY_HIGHEST = -20,
PRIORITY_DEFAULT = 0,
PRIORITY_MORE_FAVORABLE = -1,
PRIORITY_LESS_FAVORABLE = 1,
};
class Condition {
public:
Condition() {}
~Condition() {}
/**
* Wait on the condition variable. MUST be locked with ConditionLock before being called.
*
* \param[in] lock: An object of type ConditionLock, which must be locked by the current thread.
*/
void wait(ConditionLock& lock) {
mCondition.wait(lock);
}
/**
* Wait on the condition variable with a period of time.
*
* \param[in] lock: An object of type ConditionLock, which must be locked by the current thread.
* \param[in] reltime: The maximum time to spend waiting.
*
* \return TIMED_OUT if it's not notified to wake up within reltime, otherwise return OK.
*/
int waitRelative(ConditionLock& lock, int64_t reltime);
/**
* Wake up one thread that is waiting on the condition variable.
*/
void signal() { mCondition.notify_one(); }
/**
* Wake up all threads that are waiting on the condition variable.
*/
void broadcast() { mCondition.notify_all(); }
private:
Condition(const Condition& other) = delete;
Condition& operator=(const Condition&) = delete;
std::condition_variable mCondition;
};
/**
* Thread is a wrapper class to std::thread
*
* Thread helps manager the thread's state and make the std::thread is easier to used.
* Thread also hides the platform specific implementation details.
*/
class Thread {
public:
Thread();
virtual ~Thread();
/**
* Start the thread.
*/
virtual int run(std::string name = ("nameless"), int priority = PRIORITY_DEFAULT);
/**
* Ask this object's thread to exit. This function is asynchronous, so when it
* returns the thread might still be running.
*/
virtual void requestExit();
/**
* Wait until this object's thread exits. Returns immediately if not yet running.
*
* join will not trigger the thread to exit, it just wait for the thread exits.
* Do not call it from this object's thread, will return WOULD_BLOCK in that case.
*/
int join();
/**
* Ask this object's thread to exit. This function is synchronous, so when it
* returns the thread must exit already.
* It has same effect with calling requestExit and join combined.
*
* Do not call from this object's thread, will return WOULD_BLOCK in that case.
*/
int requestExitAndWait();
/**
* Indicates whether this thread is running or not.
*/
bool isRunning() const;
/**
* Indicates whether this thread is going to exit or not.
*/
bool isExiting() const;
/**
* Indicates whether this thread exited or not.
*/
bool isExited() const;
private:
/**
* threadLoop is the function which is called by the thread.
* The derived class MUST override this function. The thread starts its life here.
*
* There are two ways of using the thread object:
* 1. loop: threadLoop will be called again as long as it returns true,
* and requestExit() wasn't called.
* 2. once: If threadLoop() returns false, the thread will exit upon return.
*
* There are three ways of exiting the thread.
* 1. threadLoop return false.
* 2. requestExit is called.
* 3. requestExitAndWait is called.
*/
virtual bool threadLoop() { return false; }
private:
Thread(const Thread& other) = delete;
Thread& operator=(const Thread&) = delete;
/**
* The function which is used to create the std::thread.
*/
static void _threadLoop(Thread* self);
/**
* Set thread's property such as thread's name or priority.
*/
void setProperty();
private:
enum {
NOT_STARTED,
RUNNING,
EXITING,
EXITED,
} mState;
// The max length for thread name is 15.
static const int MAX_THREAD_NAME_LEN = 15;
std::thread* mThread;
std::string mName;
std::thread::id mId;
int mPriority;
// A lock used to protect internal data and API accessing.
mutable Mutex mLock;
// To make sure the thread not dead before "run" not finish.
Condition mStartCondition;
// To make sure API like join be able to wait until thread exits.
Condition mExitedCondition;
};
} // namespace icamera