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
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 120
|
||||
ColumnLimit: 80
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 4
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
@ -70,3 +70,4 @@ SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
|
||||
|
@ -23,6 +23,8 @@ else()
|
||||
add_library(${PROJECT_NAME} STATIC "")
|
||||
endif()
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
src/ulib/base/location.h
|
||||
src/ulib/base/location.cpp
|
||||
src/ulib/concorrency/barrier.cpp
|
||||
src/ulib/concorrency/barrier.h
|
||||
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.h
|
||||
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)
|
||||
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,17 +5,20 @@
|
||||
#ifndef ULIB_SRC_LOG_LOG_H_
|
||||
#define ULIB_SRC_LOG_LOG_H_
|
||||
|
||||
#include "ulib/base/location.h"
|
||||
#include "logger.h"
|
||||
#include "level.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace tqcq {
|
||||
|
||||
#define _ULOG(level, tag, fmt_str, ...) \
|
||||
tqcq::Logger::GetInstance().Log(level, __FILE__, __FUNCTION__, __LINE__, tag, \
|
||||
fmt::format(fmt_str, ##__VA_ARGS__).c_str())
|
||||
#define _ULOG(level, tag, fmt_str, ...) \
|
||||
tqcq::Logger::GetInstance().Log( \
|
||||
level, __FILE__, __FUNCTION__, __LINE__, tag, \
|
||||
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
|
||||
#define ULOG_TRACE(tag, ...) _ULOG(ULOG_LEVEL_TRACE, tag, __VA_ARGS__)
|
||||
@ -53,6 +56,17 @@ namespace tqcq {
|
||||
#define ULOG_FATAL(...) ((void) 0)
|
||||
#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
|
||||
|
||||
#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/event_unittest.cpp
|
||||
ulib/concorrency/countdown_latch_unittest.cpp
|
||||
ulib/system/thread_unittest.cpp
|
||||
)
|
||||
target_link_libraries(ulib_test PRIVATE
|
||||
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