commit 7cdca9d255

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

@ -0,0 +1,3 @@
# c++ 学习
现代C++入门学习C++11及以上, LLVM编译器

@ -0,0 +1,81 @@
#ifndef CPP_START_ASPECT_H
#define CPP_START_ASPECT_H
#define HAS_MEMBER(member)\
template<typename T, typename... Args>\
class HasMember_##member\
{\
private:\
template<typename U>\
static auto check(int) -> decltype(std::declval<U>().member(std::declval<Args>()...), std::true_type());\
\
template<typename U>\
static std::false_type check(...);\
\
public:\
enum { value = std::is_same<decltype(check<T>(0)), std::true_type>::value };\
};\
HAS_MEMBER(before)
HAS_MEMBER(after)
#include "non_copy_able.h"
template<typename Func, typename... Args>
class Aspect : NonCopyAble {
private:
Func mFunc;
public:
explicit Aspect(Func &&f) : mFunc(std::forward<Func>(f)) {
}
template<typename T>
typename std::enable_if<HasMember_before<T, Args...>::value && HasMember_after<T, Args...>::value>::type
invoke(Args &&... args, T &&aspect) {
aspect.before(std::forward<Args>(args)...);
// TODO 推断返回类型,若有返回值则将返回值作为后置处理的参数
mFunc(std::forward<Args>(args)...);
aspect.after(std::forward<Args>(args)...);
}
template<typename T>
typename std::enable_if<HasMember_before<T, Args...>::value && !HasMember_after<T, Args...>::value>::type
invoke(Args &&... args, T &&aspect) {
aspect.before(std::forward<Args>(args)...);
mFunc(std::forward<Args>(args)...);
}
template<typename T>
typename std::enable_if<!HasMember_before<T, Args...>::value && HasMember_after<T, Args...>::value
>::type invoke(Args &&... args, T &&aspect) {
mFunc(std::forward<Args>(args)...);
aspect.after(std::forward<Args>(args)...);
}
template<typename Head, typename... Tail>
void invoke(Args... args, Head &&headAspect, Tail &&... tailAspect) {
headAspect.before(std::forward<Args>(args)...);
invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...);
headAspect.after(std::forward<Args>(args)...);
}
};
/**
*
* @tparam AOP
* @tparam Func
* @tparam Args
* @param func
* @param args
*/
template<typename... AOP, typename Func, typename... Args>
void aop(Func &&func, Args &&... args) {
Aspect<Func, Args...> asp(std::forward<Func>(func));
asp.invoke(std::forward<Args>(args)..., AOP()...);
}
#endif //CPP_START_ASPECT_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

@ -0,0 +1,292 @@
#include <iostream>
#include <map>
#include <thread>
template<typename T>
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<std::string, int> 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<typename T>
struct GetLeftSize : std::integral_constant<int, 10> {
};
template<typename ... T>
void f(T ... args) {
std::cout << sizeof...(args) << std::endl;
}
template<typename ... T>
void expand(T ... args) {
std::initializer_list<int>{(std::cout << args << std::endl, 0)...};
}
template<typename F, typename Arg>
auto Func(F f, Arg arg) -> decltype(f(arg)) {
return f(arg);
}
template<typename Fn, typename Arg>
auto GroupBy(const std::vector<Arg> &vt, Fn &&keySelector)
-> std::multimap<decltype(keySelector((Arg & )
nullptr)), Arg>
{
typedef decltype(keySelector(*(Arg * ) nullptr))
key_type;
std::multimap<key_type, Arg> 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<std::mutex> locker(g_lock);
std::this_thread::sleep_for(std::chrono::seconds(2));
}
#include "sync_queue.h"
void sync_test(){
// 同步队列
auto queue = new SyncQueue<int>(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 <chrono>
#include <iomanip>
#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<std::chrono::microseconds>() << " 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<LogAspect, TimeElapsedAspect>([](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<void(int)> f = std::bind(&HT, std::placeholders::_1);
aop<LogAspect>(f, 100);
}
int main() {
// 同步队列测试
// sync_test();
// 时间工具测试
// chrono_test();
// 线程池测试
// thread_test();
// AOP测试
aop_test();
// auto start = std::chrono::duration_cast<std::chrono::milliseconds>(
// 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::milliseconds>(
// 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<int>::value << std::endl;
//
// f();
// f(1);
// f(1,2.5,"");
//
// foreach();
return 0;
}

@ -0,0 +1,32 @@
#ifndef CPP_START_STOP_WATCH_H
#define CPP_START_STOP_WATCH_H
#include <chrono>
class StopWatch {
private:
std::chrono::time_point<std::chrono::high_resolution_clock> mBegin;
public:
StopWatch() : mBegin(std::chrono::high_resolution_clock::now()) {
}
void reset() {
mBegin = std::chrono::high_resolution_clock::now();
}
template<typename Duration=std::chrono::milliseconds>
int64_t elapsed() const {
return std::chrono::duration_cast<Duration>(std::chrono::high_resolution_clock::now() - mBegin)
.count();
}
};
#endif //CPP_START_STOP_WATCH_H

@ -0,0 +1,104 @@
#ifndef CPP_START_SYNC_QUEUE_H
#define CPP_START_SYNC_QUEUE_H
#include <mutex>
#include <list>
#include <thread>
#include <condition_variable>
template<typename T>
class SyncQueue {
private:
int mMaxSize; // 同步队列最大数量
std::mutex mMutex; // 互斥锁
std::list<T> 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<T>(item));
}
template<typename F>
void add(F &&f) {
std::unique_lock<std::mutex> locker(mMutex);
mNotFull.wait(locker, [this] { return mStop || mQueue.size() != mMaxSize; });
if (mStop) return;
mQueue.push_back(std::forward<F>(f));
mNotEmpty.notify_all();
mNotEmpty.notify_all();
}
/**
*
* @param item
*/
void dequeue(T &item) {
std::unique_lock<std::mutex> 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<T> &list) {
std::unique_lock<std::mutex> 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<std::mutex> locker(mMutex);
return mQueue.size();
}
/**
*
* @return
*/
int getMaxSize() const {
return mMaxSize;
}
void stop() {
{
std::lock_guard<std::mutex> locker(mMutex);
mStop = true;
}
mNotFull.notify_all();
mNotEmpty.notify_all();
}
};
#endif //CPP_START_SYNC_QUEUE_H

@ -0,0 +1,20 @@
#ifndef CPP_START_LOG_ASPECT_H
#define CPP_START_LOG_ASPECT_H
#include <iostream>
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

@ -0,0 +1,23 @@
#ifndef CPP_START_TIME_ELAPSED_ASPECT_H
#define CPP_START_TIME_ELAPSED_ASPECT_H
#include <iostream>
#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

@ -0,0 +1,88 @@
#ifndef CPP_START_THREAD_POOL_H
#define CPP_START_THREAD_POOL_H
#include <list>
#include <thread>
#include <memory>
#include <atomic>
#include <functional>
#include "sync_queue.h"
class ThreadPool {
using Task = std::function<void()>;
private:
// 线程组
std::list<std::shared_ptr<std::thread>> mThreadGroup;
// 任务队列
SyncQueue<Task> 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<std::thread>(&ThreadPool::run, this));
}
}
void run() {
while (mRunning) {
std::list<Task> 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>(task));
}
void add(const Task &task) {
mQueue.enqueue(task);
}
};
#endif //CPP_START_THREAD_POOL_H
Loading…
Cancel
Save