feat add thread
Some checks failed
linux-mips64-gcc / linux-gcc-mips64el (push) Waiting to run
linux-x64-gcc / linux-gcc (push) Waiting to run
rpcrypto-build / build (Debug, himix200.toolchain.cmake) (push) Failing after 57s
linux-hisiv500-gcc / linux-gcc-hisiv500 (push) Failing after 58s
rpcrypto-build / build (Debug, hisiv510.toolchain.cmake) (push) Failing after 1m3s
rpcrypto-build / build (Release, himix200.toolchain.cmake) (push) Failing after 1m11s
rpcrypto-build / build (Release, hisiv510.toolchain.cmake) (push) Failing after 1m22s
Some checks failed
linux-mips64-gcc / linux-gcc-mips64el (push) Waiting to run
linux-x64-gcc / linux-gcc (push) Waiting to run
rpcrypto-build / build (Debug, himix200.toolchain.cmake) (push) Failing after 57s
linux-hisiv500-gcc / linux-gcc-hisiv500 (push) Failing after 58s
rpcrypto-build / build (Debug, hisiv510.toolchain.cmake) (push) Failing after 1m3s
rpcrypto-build / build (Release, himix200.toolchain.cmake) (push) Failing after 1m11s
rpcrypto-build / build (Release, hisiv510.toolchain.cmake) (push) Failing after 1m22s
This commit is contained in:
parent
bbdc7d6988
commit
44f0021d30
@ -36,7 +36,7 @@ BreakBeforeTernaryOperators: true
|
|||||||
BreakConstructorInitializers: BeforeColon
|
BreakConstructorInitializers: BeforeColon
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
BreakInheritanceList: BeforeColon
|
BreakInheritanceList: BeforeColon
|
||||||
ColumnLimit: 120
|
ColumnLimit: 80
|
||||||
CompactNamespaces: false
|
CompactNamespaces: false
|
||||||
ContinuationIndentWidth: 4
|
ContinuationIndentWidth: 4
|
||||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||||
@ -70,3 +70,4 @@ SpacesInParentheses: false
|
|||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
TabWidth: 4
|
TabWidth: 4
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ else()
|
|||||||
add_library(${PROJECT_NAME} STATIC "")
|
add_library(${PROJECT_NAME} STATIC "")
|
||||||
endif()
|
endif()
|
||||||
target_sources(${PROJECT_NAME} PRIVATE
|
target_sources(${PROJECT_NAME} PRIVATE
|
||||||
|
src/ulib/base/location.h
|
||||||
|
src/ulib/base/location.cpp
|
||||||
src/ulib/concorrency/barrier.cpp
|
src/ulib/concorrency/barrier.cpp
|
||||||
src/ulib/concorrency/barrier.h
|
src/ulib/concorrency/barrier.h
|
||||||
src/ulib/concorrency/mutex.cpp
|
src/ulib/concorrency/mutex.cpp
|
||||||
@ -36,7 +38,10 @@ target_sources(${PROJECT_NAME} PRIVATE
|
|||||||
src/ulib/concorrency/internal/condition_variable_impl.cpp
|
src/ulib/concorrency/internal/condition_variable_impl.cpp
|
||||||
src/ulib/concorrency/internal/condition_variable_impl.h
|
src/ulib/concorrency/internal/condition_variable_impl.h
|
||||||
src/ulib/concorrency/event.cpp
|
src/ulib/concorrency/event.cpp
|
||||||
src/ulib/concorrency/event.h)
|
src/ulib/concorrency/event.h
|
||||||
|
src/ulib/system/thread.h
|
||||||
|
src/ulib/system/thread.cpp
|
||||||
|
)
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
60
src/ulib/base/location.cpp
Normal file
60
src/ulib/base/location.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "location.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace ulib {
|
||||||
|
#if defined(__clang__) && defined(_MSC_VER)
|
||||||
|
const char stripped[] = "ulib\\base\\location.cpp";
|
||||||
|
#else
|
||||||
|
const char stripped[] = "ulib/base/location.cpp";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(ULIB_LOCATION_STRIPPED_PREFIX_LENGTH) \
|
||||||
|
&& !defined(ULIB_PROJECT_ROOT_PATH)
|
||||||
|
inline size_t
|
||||||
|
StrippedFilePathPrefixLength()
|
||||||
|
{
|
||||||
|
const char path[] = __FILE__;
|
||||||
|
static size_t stripped_file_path_prefix_length =
|
||||||
|
sizeof(path) - sizeof(stripped);
|
||||||
|
return stripped_file_path_prefix_length;
|
||||||
|
}
|
||||||
|
#elif defined(ULIB_LOCATION_STRIPPED_PREFIX_LENGTH)
|
||||||
|
inline size_t
|
||||||
|
StrippedFilePathPrefixLength()
|
||||||
|
{
|
||||||
|
return ULIB_LOCATION_STRIPPED_PREFIX_LENGTH;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
inline size_t
|
||||||
|
StrippedFilePathPrefixLength()
|
||||||
|
{
|
||||||
|
return sizeof(ULIB_PROJECT_ROOT_PATH);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Location::Location() = default;
|
||||||
|
|
||||||
|
Location::Location(const Location &other)
|
||||||
|
: function_name_(other.function_name_),
|
||||||
|
file_name_(other.file_name_),
|
||||||
|
line_number_(other.line_number_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Location &
|
||||||
|
Location::operator=(const Location &other)
|
||||||
|
{
|
||||||
|
function_name_ = other.function_name_;
|
||||||
|
file_name_ = other.file_name_;
|
||||||
|
line_number_ = other.line_number_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Location::ToString() const
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << function_name_ << "@" << file_name_ << ":" << line_number_;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace ulib
|
37
src/ulib/base/location.h
Normal file
37
src/ulib/base/location.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef ULIB_SRC_ULIB_BASE_LOCATION_H_
|
||||||
|
#define ULIB_SRC_ULIB_BASE_LOCATION_H_
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "stringize_macros.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ulib {
|
||||||
|
class Location {
|
||||||
|
public:
|
||||||
|
Location();
|
||||||
|
Location(const Location &other);
|
||||||
|
Location &operator=(const Location &other);
|
||||||
|
|
||||||
|
std::string ToString() const;
|
||||||
|
|
||||||
|
const char *function_name() const { return function_name_; }
|
||||||
|
|
||||||
|
const char *file_name() const { return file_name_; }
|
||||||
|
|
||||||
|
int line_number() const { return line_number_; }
|
||||||
|
|
||||||
|
static Location Current(const char *function_name = __builtin_FUNCTION(),
|
||||||
|
const char *file_name = __builtin_FILE(),
|
||||||
|
int line_number = __builtin_LINE());
|
||||||
|
|
||||||
|
private:
|
||||||
|
Location(const char *function_name, const char *file_name, int line_number);
|
||||||
|
const char *function_name_ = nullptr;
|
||||||
|
const char *file_name_ = nullptr;
|
||||||
|
int line_number_ = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ULIB_FROM_HERE ::ulib::Location::Current()
|
||||||
|
|
||||||
|
}// namespace ulib
|
||||||
|
#endif// ULIB_SRC_ULIB_BASE_LOCATION_H_
|
8
src/ulib/base/stringize_macros.h
Normal file
8
src/ulib/base/stringize_macros.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef ULIB_SRC_ULIB_BASE_STRINGIZE_MACROS_H_
|
||||||
|
#define ULIB_SRC_ULIB_BASE_STRINGIZE_MACROS_H_
|
||||||
|
|
||||||
|
#define STRINGIZE_NO_EXPANSION(x) #x
|
||||||
|
|
||||||
|
#define STRINGIZE STRINGIZE_NO_EXPANSION(x)
|
||||||
|
|
||||||
|
#endif// ULIB_SRC_ULIB_BASE_STRINGIZE_MACROS_H_
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef ULIB_SRC_LOG_LOG_H_
|
#ifndef ULIB_SRC_LOG_LOG_H_
|
||||||
#define ULIB_SRC_LOG_LOG_H_
|
#define ULIB_SRC_LOG_LOG_H_
|
||||||
|
|
||||||
|
#include "ulib/base/location.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "level.h"
|
#include "level.h"
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
@ -12,10 +13,12 @@
|
|||||||
namespace tqcq {
|
namespace tqcq {
|
||||||
|
|
||||||
#define _ULOG(level, tag, fmt_str, ...) \
|
#define _ULOG(level, tag, fmt_str, ...) \
|
||||||
tqcq::Logger::GetInstance().Log(level, __FILE__, __FUNCTION__, __LINE__, tag, \
|
tqcq::Logger::GetInstance().Log( \
|
||||||
|
level, __FILE__, __FUNCTION__, __LINE__, tag, \
|
||||||
fmt::format(fmt_str, ##__VA_ARGS__).c_str())
|
fmt::format(fmt_str, ##__VA_ARGS__).c_str())
|
||||||
|
|
||||||
#define ULOG_SET_STRIPPED_PREFIX_LEN(len) ::tqcq::Logger::GetInstance().SetStrippedPrefixLen(len)
|
#define ULOG_SET_STRIPPED_PREFIX_LEN(len) \
|
||||||
|
::tqcq::Logger::GetInstance().SetStrippedPrefixLen(len)
|
||||||
|
|
||||||
#if ULOG_LEVEL <= ULOG_LEVEL_TRACE
|
#if ULOG_LEVEL <= ULOG_LEVEL_TRACE
|
||||||
#define ULOG_TRACE(tag, ...) _ULOG(ULOG_LEVEL_TRACE, tag, __VA_ARGS__)
|
#define ULOG_TRACE(tag, ...) _ULOG(ULOG_LEVEL_TRACE, tag, __VA_ARGS__)
|
||||||
@ -53,6 +56,17 @@ namespace tqcq {
|
|||||||
#define ULOG_FATAL(...) ((void) 0)
|
#define ULOG_FATAL(...) ((void) 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ULOG_ASSERT_WITH_TAG(expr, tag, ...) \
|
||||||
|
do { \
|
||||||
|
if (!(expr)) { \
|
||||||
|
_ULOG(ULOG_LEVEL_FATAL, tag, ##__VA_ARGS__); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define ULOG_ASSERT(expr, ...) \
|
||||||
|
ULOG_ASSERT_WITH_TAG(expr, "ulib_assert", ##__VA_ARGS__)
|
||||||
|
|
||||||
}// namespace tqcq
|
}// namespace tqcq
|
||||||
|
|
||||||
#endif//ULIB_SRC_LOG_LOG_H_
|
#endif//ULIB_SRC_LOG_LOG_H_
|
||||||
|
125
src/ulib/system/thread.cpp
Normal file
125
src/ulib/system/thread.cpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#include "thread.h"
|
||||||
|
#include <climits>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include "ulib/log/log.h"
|
||||||
|
#include "ulib/concorrency/countdown_latch.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
namespace ulib {
|
||||||
|
|
||||||
|
pid_t
|
||||||
|
GetTid()
|
||||||
|
{
|
||||||
|
// TODO cache tid
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
|
||||||
|
uint64_t tid64;
|
||||||
|
pthread_threadid_np(NULL, &tid64);
|
||||||
|
return static_cast<pid_t>(tid64);
|
||||||
|
#else
|
||||||
|
return static_cast<pid_t>(::syscall(SYS_gettid));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
class Thread::Impl {
|
||||||
|
public:
|
||||||
|
Impl(const ThreadFunc &func, const std::string &thread_name)
|
||||||
|
: thread_(0),
|
||||||
|
started_(false),
|
||||||
|
joined_(false),
|
||||||
|
thread_name_(thread_name),
|
||||||
|
func_(func),
|
||||||
|
tid_(new pid_t(0)),
|
||||||
|
latch_(1)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~Impl()
|
||||||
|
{
|
||||||
|
if (started_ && !joined_) { pthread_detach(thread_); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *ThreadRun(void *obj)
|
||||||
|
{
|
||||||
|
Impl *impl = static_cast<Impl *>(obj);
|
||||||
|
*impl->tid_ = GetTid();
|
||||||
|
impl->latch_.CountDown();
|
||||||
|
try {
|
||||||
|
impl->func_();
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
// do nothing
|
||||||
|
ULOG_ERROR("system.thread",
|
||||||
|
"exception caught in Thread %s, reson: %s",
|
||||||
|
impl->thread_name_.c_str(), ex.what());
|
||||||
|
} catch (...) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
ULOG_ASSERT(!started_, "thread already started");
|
||||||
|
started_ = true;
|
||||||
|
if (pthread_create(&thread_, NULL, Impl::ThreadRun, this)) {
|
||||||
|
started_ = false;
|
||||||
|
} else {
|
||||||
|
latch_.Await();
|
||||||
|
ULOG_ASSERT(tid_.get(), "tid_ is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Join()
|
||||||
|
{
|
||||||
|
ULOG_ASSERT(started_, "thread not started");
|
||||||
|
ULOG_ASSERT(!joined_, "thread already joined");
|
||||||
|
joined_ = true;
|
||||||
|
return pthread_join(thread_, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Started() const { return started_; }
|
||||||
|
|
||||||
|
bool Tid() const { return *tid_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
pthread_t thread_;
|
||||||
|
bool started_;
|
||||||
|
bool joined_;
|
||||||
|
|
||||||
|
std::string thread_name_;
|
||||||
|
ThreadFunc func_;
|
||||||
|
std::shared_ptr<pid_t> tid_;
|
||||||
|
CountDownLatch latch_;
|
||||||
|
};
|
||||||
|
|
||||||
|
Thread::Thread(const ThreadFunc &func, const std::string &thread_name)
|
||||||
|
: impl_(new Impl(func, thread_name))
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Thread(ThreadFunc &&func, const std::string &thread_name = std::string());
|
||||||
|
Thread::~Thread() { delete impl_; }
|
||||||
|
|
||||||
|
void
|
||||||
|
Thread::Start()
|
||||||
|
{
|
||||||
|
impl_->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Thread::Join()
|
||||||
|
{
|
||||||
|
return impl_->Join();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Thread::Started() const
|
||||||
|
{
|
||||||
|
return impl_->Started();
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t
|
||||||
|
Thread::Tid() const
|
||||||
|
{
|
||||||
|
return impl_->Tid();
|
||||||
|
}
|
||||||
|
}// namespace ulib
|
29
src/ulib/system/thread.h
Normal file
29
src/ulib/system/thread.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef ULIB_SRC_ULIB_SYSTEM_THREAD_H_
|
||||||
|
#define ULIB_SRC_ULIB_SYSTEM_THREAD_H_
|
||||||
|
#include "ulib/base/types.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ulib {
|
||||||
|
class Thread {
|
||||||
|
public:
|
||||||
|
using ThreadFunc = std::function<void()>;
|
||||||
|
Thread(const ThreadFunc &func,
|
||||||
|
const std::string &thread_name = std::string());
|
||||||
|
// Thread(ThreadFunc &&func, const std::string &thread_name = std::string());
|
||||||
|
~Thread();
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
int Join();
|
||||||
|
|
||||||
|
bool Started() const;
|
||||||
|
pid_t Tid() const;
|
||||||
|
const std::string &name() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Impl;
|
||||||
|
Impl *impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace ulib
|
||||||
|
#endif// ULIB_SRC_ULIB_SYSTEM_THREAD_H_
|
@ -7,6 +7,7 @@ add_executable(ulib_test
|
|||||||
ulib/concorrency/mutex_unittest.cpp
|
ulib/concorrency/mutex_unittest.cpp
|
||||||
ulib/concorrency/event_unittest.cpp
|
ulib/concorrency/event_unittest.cpp
|
||||||
ulib/concorrency/countdown_latch_unittest.cpp
|
ulib/concorrency/countdown_latch_unittest.cpp
|
||||||
|
ulib/system/thread_unittest.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(ulib_test PRIVATE
|
target_link_libraries(ulib_test PRIVATE
|
||||||
ulib
|
ulib
|
||||||
|
17
tests/ulib/system/thread_unittest.cpp
Normal file
17
tests/ulib/system/thread_unittest.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include <ulib/system/thread.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <ulib/concorrency/countdown_latch.h>
|
||||||
|
|
||||||
|
TEST(Thread, Start)
|
||||||
|
{
|
||||||
|
volatile int i = 0;
|
||||||
|
ulib::Thread thread([&]() {
|
||||||
|
EXPECT_EQ(i, 0);
|
||||||
|
i = 1;
|
||||||
|
EXPECT_EQ(i, 1);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(i, 0);
|
||||||
|
thread.Start();
|
||||||
|
thread.Join();
|
||||||
|
EXPECT_EQ(i, 1);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user