commit 7cdca9d25587ac2f97c33254ca3f5af99a676eef Author: 还不如一只猪威武 Date: Thu Feb 22 15:59:28 2024 +0800 init diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..40bec28 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,36 @@ +# 设置CMAKE 的最低要求版本 +cmake_minimum_required(VERSION 3.25) + +# 设置c++版本要求 +set(CMAKE_CXX_STANDARD 11) +# 强制指定,不允许编译器降级 +set(CMAKE_CXX_STANDARD_REQUIRED ON) +# 关闭编译器扩展功能 +set(CMAKE_CXX_EXTENSIONS OFF) + +# 项目名称 +project(cpp_start LANGUAGES CXX VERSION 1.0.0) + +# 设置编译器参数 +set(CMAKE_CXX_FLAGS "-fno-elide-constructors") # 关闭编译优化 + +# 消息提示 +message(STATUS "message from cmake file!") + +# 添加用于生成可执行文件 +add_executable(${PROJECT_NAME} src/main.cpp) + +aux_source_directory(src/aspect ASPECT_DIR) +aux_source_directory(src/test TEST_DIR) + +target_include_directories(${PROJECT_NAME} PRIVATE + sync_queue.h + stop_watch.h + thread_pool.h +) + +target_sources(${PROJECT_NAME} PRIVATE + ${ASPECT_DIR} + ${TEST_DIR} +) + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e2f9819 --- /dev/null +++ b/readme.md @@ -0,0 +1,3 @@ +# c++ 学习 + +现代C++入门学习,C++11及以上, LLVM编译器 \ No newline at end of file diff --git a/src/aspect/aspect.h b/src/aspect/aspect.h new file mode 100644 index 0000000..e8afe3d --- /dev/null +++ b/src/aspect/aspect.h @@ -0,0 +1,81 @@ + +#ifndef CPP_START_ASPECT_H +#define CPP_START_ASPECT_H + +#define HAS_MEMBER(member)\ +template\ +class HasMember_##member\ +{\ +private:\ + template\ + static auto check(int) -> decltype(std::declval().member(std::declval()...), std::true_type());\ +\ + template\ + static std::false_type check(...);\ +\ +public:\ + enum { value = std::is_same(0)), std::true_type>::value };\ +};\ + + +HAS_MEMBER(before) + +HAS_MEMBER(after) + +#include "non_copy_able.h" + +template +class Aspect : NonCopyAble { +private: + Func mFunc; + +public: + explicit Aspect(Func &&f) : mFunc(std::forward(f)) { + } + + template + typename std::enable_if::value && HasMember_after::value>::type + invoke(Args &&... args, T &&aspect) { + aspect.before(std::forward(args)...); + // TODO 推断返回类型,若有返回值则将返回值作为后置处理的参数 + mFunc(std::forward(args)...); + aspect.after(std::forward(args)...); + } + + template + typename std::enable_if::value && !HasMember_after::value>::type + invoke(Args &&... args, T &&aspect) { + aspect.before(std::forward(args)...); + mFunc(std::forward(args)...); + } + + template + typename std::enable_if::value && HasMember_after::value + >::type invoke(Args &&... args, T &&aspect) { + mFunc(std::forward(args)...); + aspect.after(std::forward(args)...); + } + + template + void invoke(Args... args, Head &&headAspect, Tail &&... tailAspect) { + headAspect.before(std::forward(args)...); + invoke(std::forward(args)..., std::forward(tailAspect)...); + headAspect.after(std::forward(args)...); + } +}; + +/** + * 辅助函数,简化调用 + * @tparam AOP 切点 + * @tparam Func 切点方法类型 + * @tparam Args 方法参数类型 + * @param func 切点方法 + * @param args 方法参数 + */ +template +void aop(Func &&func, Args &&... args) { + Aspect asp(std::forward(func)); + asp.invoke(std::forward(args)..., AOP()...); +} + +#endif //CPP_START_ASPECT_H diff --git a/src/aspect/non_copy_able.h b/src/aspect/non_copy_able.h new file mode 100644 index 0000000..e654eab --- /dev/null +++ b/src/aspect/non_copy_able.h @@ -0,0 +1,22 @@ + +#ifndef CPP_START_NON_COPY_ABLE_H +#define CPP_START_NON_COPY_ABLE_H + + +class NonCopyAble { + +protected: + NonCopyAble() = default; + + ~NonCopyAble() = default; + +public: + // 禁用复制构造 + NonCopyAble(const NonCopyAble &) = delete; + + // 禁用赋值构造 + NonCopyAble &operator=(const NonCopyAble &) = delete; +}; + + +#endif //CPP_START_NON_COPY_ABLE_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..909edef --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,292 @@ +#include +#include +#include + +template +class iterator { +public: + using value_type = T; + using size_type = size_t; + +private: + size_type cursor_; + const value_type step_; + value_type value_; + +public: + + iterator(size_type cur_satrt, value_type begin_val, value_type step_val) + : + cursor_(cur_satrt), + step_(step_val), + value_(begin_val) { + + }; + + value_type operator*() const { + return value_; + }; + + bool operator!=(const iterator &rhs) const { + return (cursor_ != rhs.cursor_); + }; + + iterator *operator++() { + value_ += step_; + ++cursor_; + return (*this); + }; +}; + + +void foreach() { + std::map mm = { + {"a", 1}, + {"b", 2}, + {"c", 3} + }; + + for (const auto &m: mm) { + std::cout << m.first << " -> " << m.second << std::endl; + } +} + +int g_constructCount = 0; +int g_copy_constructCount = 0; +int g_destructCount = 0; + +class A { + +public: + A() { + std::cout << "construct: " << ++g_constructCount << std::endl; + } + + A(const A &a) { + std::cout << "copy construct: " << ++g_copy_constructCount << std::endl; + } + + ~A() { + std::cout << "destruct: " << ++g_destructCount << std::endl; + } + +}; + +A getA() { + return A{}; +} + + +template +struct GetLeftSize : std::integral_constant { + +}; + +template +void f(T ... args) { + std::cout << sizeof...(args) << std::endl; +} + + +template +void expand(T ... args) { + std::initializer_list{(std::cout << args << std::endl, 0)...}; +} + +template +auto Func(F f, Arg arg) -> decltype(f(arg)) { + return f(arg); +} + + +template +auto GroupBy(const std::vector &vt, Fn &&keySelector) +-> std::multimap +{ +typedef decltype(keySelector(*(Arg * ) nullptr)) +key_type; +std::multimap map; +std::for_each(vt +. + +begin(), vt + +. + +end(), + +[&]( +const Arg &arg +){ +map. +insert(make_pair(keySelector(arg), arg) +); +}); +return +map; +} + +std::mutex g_lock; + +void func() { + std::lock_guard locker(g_lock); + std::this_thread::sleep_for(std::chrono::seconds(2)); +} + +#include "sync_queue.h" +void sync_test(){ + // 同步队列 + auto queue = new SyncQueue(3); + + // 每2秒取出进行消费 + std::thread producer([&](){ + int i = 0; + while (i < 9){ + queue->dequeue(i); + std::this_thread::sleep_for(std::chrono::seconds(2)); + std::cout << "dequeue: " << i << std::endl; + } + }); + + // 持续写入 + std::thread consumer([&](){ + for (int i = 0; i < 10; ++i) { + queue->enqueue(i); + std::cout << "enqueue: " << i << std::endl; + } + }); + + producer.join(); + consumer.join(); +} + + +#include +#include +#include "stop_watch.h" + +void chrono_test(){ + + StopWatch stopWatch; + + std::chrono::minutes t1(10); + std::chrono::seconds t2(60); + std::chrono::seconds t3 = t1 - t2; + std::cout << "duration time: " << t3.count() << std::endl; + + std::cout << "\ncost time: " << stopWatch.elapsed() << " us\n" << std::endl; + + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + // 将 time_point 转为 ctime + std::time_t last = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24)); + std::time_t next = std::chrono::system_clock::to_time_t(now + std::chrono::hours (24)); + + // 使用put_time格式化时间 + std::cout + << "One day ago, the time was " + << std::put_time(std::localtime(&last), "%F %T") + << "\n" + << "NExt day ago, the time is " + << std::put_time(std::localtime(&next), "%F %T") + + << std::endl; + + std::cout << "\ncost time: " << stopWatch.elapsed() << " ms\n" << std::endl; + +} + +#include "thread_pool.h" +void thread_test(){ + ThreadPool pool(3,10); + + std::thread t0([&pool]{ + for (int i = 0; i < 100; ++i) { + auto thdId = std::this_thread::get_id(); + pool.add([thdId]{ + std::cout << "thread 1 id:" << thdId << std::endl; + }); + } + }); + + std::thread t1([&pool]{ + for (int i = 0; i < 100; ++i) { + auto thdId = std::this_thread::get_id(); + pool.add([thdId]{ + std::cout << "thread 2 id:" << thdId << std::endl; + }); + } + }); + + std::this_thread::sleep_for(std::chrono::seconds(2)); +// getchar(); + + pool.stop(); + t0.join(); + t1.join(); +} + + +#include "aspect/aspect.h" +#include "test/time_elapsed_aspect.h" +#include "test/log_aspect.h" +void HT(int a) +{ + std::cout << "real HT function " << a << std::endl; +} +void aop_test(){ + using namespace std; + + aop([](int a){ + std::thread t([a](){ + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << "run function, arg is " << a << std::endl; + }); + t.join(); + }, 1); + + cout << endl; + + std::function f = std::bind(&HT, std::placeholders::_1); + aop(f, 100); +} + +int main() { + // 同步队列测试 +// sync_test(); + // 时间工具测试 +// chrono_test(); + // 线程池测试 +// thread_test(); + // AOP测试 + aop_test(); + + +// auto start = std::chrono::duration_cast( +// std::chrono::system_clock::now().time_since_epoch()).count(); +// std::cout << "start time: " << start / 1000 << std::endl; +// std::thread t0(func); +// std::thread t1(func); +// std::thread t2(func); +// t0.join(); // 阻塞执行 +// t1.detach(); // 分离线程何对象,之后就无法何线程发送联系 +// t2.join(); +// auto end = std::chrono::duration_cast( +// std::chrono::system_clock::now().time_since_epoch()).count(); +// std::cout << " end time: " << end / 1000 << std::endl; + +// A&& a = getA(); +// +// expand(1,2,3,4); +// +// std::cout << GetLeftSize::value << std::endl; +// +// f(); +// f(1); +// f(1,2.5,""); +// +// foreach(); + + return 0; +} \ No newline at end of file diff --git a/src/stop_watch.h b/src/stop_watch.h new file mode 100644 index 0000000..453af42 --- /dev/null +++ b/src/stop_watch.h @@ -0,0 +1,32 @@ + +#ifndef CPP_START_STOP_WATCH_H +#define CPP_START_STOP_WATCH_H + +#include + + +class StopWatch { + +private: + + std::chrono::time_point mBegin; + +public: + StopWatch() : mBegin(std::chrono::high_resolution_clock::now()) { + + } + + void reset() { + mBegin = std::chrono::high_resolution_clock::now(); + } + + template + int64_t elapsed() const { + return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - mBegin) + .count(); + } + +}; + + +#endif //CPP_START_STOP_WATCH_H diff --git a/src/sync_queue.h b/src/sync_queue.h new file mode 100644 index 0000000..9e28f8a --- /dev/null +++ b/src/sync_queue.h @@ -0,0 +1,104 @@ + +#ifndef CPP_START_SYNC_QUEUE_H +#define CPP_START_SYNC_QUEUE_H + +#include +#include +#include +#include + +template +class SyncQueue { + +private: + int mMaxSize; // 同步队列最大数量 + std::mutex mMutex; // 互斥锁 + std::list mQueue; // 缓冲区 + std::condition_variable mNotFull; // 没满的条件 + std::condition_variable mNotEmpty; // 不为空的条件 + bool mStop; // 停止标识 + +public: + explicit SyncQueue(int maxSize) + : mMaxSize(maxSize) { + } + + /** + * 入队 + * @param item 队列元素 + */ + void enqueue(const T &item) { + add(item); + } + + void enqueue(T &&item) { + add(std::forward(item)); + } + + + template + void add(F &&f) { + std::unique_lock locker(mMutex); + mNotFull.wait(locker, [this] { return mStop || mQueue.size() != mMaxSize; }); + if (mStop) return; + mQueue.push_back(std::forward(f)); + mNotEmpty.notify_all(); + mNotEmpty.notify_all(); + } + + + /** + * 出队,获取队列内的首个元素 + * @param item 元素 + */ + void dequeue(T &item) { + std::unique_lock locker(mMutex); + mNotEmpty.wait(locker, [this] { return mStop || !mQueue.empty(); }); + if (mStop) return; + item = mQueue.front(); + mQueue.pop_front(); + mNotFull.notify_all(); + } + + /** + * 出队,获取队列内的首个元素 + * @param item 元素 + */ + void dequeue(std::list &list) { + std::unique_lock locker(mMutex); + mNotEmpty.wait(locker, [this] { return mStop || !mQueue.empty(); }); + if (mStop) return; + list = std::move(mQueue); + mNotFull.notify_all(); + } + + /** + * 当前队列数量 + * @return 当前队列数量 + */ + size_t size() { + std::lock_guard locker(mMutex); + return mQueue.size(); + } + + /** + * 查看最大容量 + * @return 最大容量 + */ + int getMaxSize() const { + return mMaxSize; + } + + void stop() { + { + std::lock_guard locker(mMutex); + mStop = true; + } + mNotFull.notify_all(); + mNotEmpty.notify_all(); + } + +}; + + +#endif //CPP_START_SYNC_QUEUE_H diff --git a/src/test/log_aspect.h b/src/test/log_aspect.h new file mode 100644 index 0000000..02bab8c --- /dev/null +++ b/src/test/log_aspect.h @@ -0,0 +1,20 @@ + +#ifndef CPP_START_LOG_ASPECT_H +#define CPP_START_LOG_ASPECT_H + +#include + +class LogAspect { + +public: + void before(int i) { + std::cout << "log info: before: " << i << std::endl; + } + + void after(int i) { + std::cout << "log info: after: " << i << std::endl; + } +}; + + +#endif //CPP_START_LOG_ASPECT_H diff --git a/src/test/time_elapsed_aspect.h b/src/test/time_elapsed_aspect.h new file mode 100644 index 0000000..00ac87e --- /dev/null +++ b/src/test/time_elapsed_aspect.h @@ -0,0 +1,23 @@ + +#ifndef CPP_START_TIME_ELAPSED_ASPECT_H +#define CPP_START_TIME_ELAPSED_ASPECT_H + +#include +#include "../stop_watch.h" + +class TimeElapsedAspect { +private: + StopWatch mStopWatch; +public: + + void before(int a) { + mStopWatch.reset(); + } + + void after(int a) { + std::cout << "cost time : " << mStopWatch.elapsed() << " ms" << std::endl; + } +}; + + +#endif //CPP_START_TIME_ELAPSED_ASPECT_H diff --git a/src/thread_pool.h b/src/thread_pool.h new file mode 100644 index 0000000..3be56f1 --- /dev/null +++ b/src/thread_pool.h @@ -0,0 +1,88 @@ + +#ifndef CPP_START_THREAD_POOL_H +#define CPP_START_THREAD_POOL_H + +#include +#include +#include +#include +#include +#include "sync_queue.h" + +class ThreadPool { + + using Task = std::function; + +private: + + // 线程组 + std::list> mThreadGroup; + + // 任务队列 + SyncQueue mQueue; + + // 运行状态 + std::atomic_bool mRunning; + + // 标识 + std::once_flag mFlag; + +private: + + void init(int numThreads) { + mRunning = true; + for (int i = 0; i < numThreads; ++i) { + mThreadGroup.push_back(std::make_shared(&ThreadPool::run, this)); + } + } + + void run() { + while (mRunning) { + std::list tasks; + mQueue.dequeue(tasks); + + for (auto &task: tasks) { + if (!mRunning) { + return; + } + task(); + } + } + } + + void stopThreadGroup() { + mQueue.stop(); + mRunning = false; + for (const auto &thread: mThreadGroup) { + if (thread) { + thread->join(); + } + } + mThreadGroup.clear(); + } + +public: + ThreadPool(int numThreads = std::thread::hardware_concurrency(), int maxTask = 1000) : + mQueue(maxTask) { + init(numThreads); + } + + ~ThreadPool() { + stop(); + } + + void stop() { + std::call_once(mFlag, [this] { stopThreadGroup(); }); + } + + void add(Task &&task) { + mQueue.enqueue(std::forward(task)); + } + + void add(const Task &task) { + mQueue.enqueue(task); + } + +}; + +#endif //CPP_START_THREAD_POOL_H