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

This commit is contained in:
tqcq 2023-12-27 11:22:39 +08:00
parent bbdc7d6988
commit 44f0021d30
10 changed files with 304 additions and 7 deletions

View File

@ -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

View File

@ -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")

View 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
View 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_

View 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_

View File

@ -5,17 +5,20 @@
#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>
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( \
fmt::format(fmt_str, ##__VA_ARGS__).c_str()) 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 #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
View 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
View 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_

View File

@ -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

View 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);
}