添加AOP、IoC

main
parent 7d81f2a594
commit 7f121cf0fc

@ -12,7 +12,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
project(cpp_start LANGUAGES CXX VERSION 1.0.0) project(cpp_start LANGUAGES CXX VERSION 1.0.0)
# #
set(CMAKE_CXX_FLAGS "-fno-elide-constructors") # #set(CMAKE_CXX_FLAGS "-fno-elide-constructors") #
# #
message(STATUS "message from cmake file") message(STATUS "message from cmake file")
@ -23,16 +23,19 @@ add_executable(${PROJECT_NAME} src/main.cpp)
aux_source_directory(src/aspect ASPECT_DIR) aux_source_directory(src/aspect ASPECT_DIR)
aux_source_directory(src/base BASE_DIR) aux_source_directory(src/base BASE_DIR)
aux_source_directory(src/util UTIL_DIR) aux_source_directory(src/util UTIL_DIR)
aux_source_directory(src/ioc IOC_DIR)
aux_source_directory(src/bus BUS_DIR)
aux_source_directory(src/test TEST_DIR) aux_source_directory(src/test TEST_DIR)
target_include_directories(${PROJECT_NAME} PRIVATE target_include_directories(${PROJECT_NAME} PRIVATE
) )
target_sources(${PROJECT_NAME} PRIVATE target_sources(${PROJECT_NAME} PRIVATE
${ASPECT_DIR} ${ASPECT_DIR}
${TEST_DIR} ${TEST_DIR}
${BASE_DIR} ${BASE_DIR}
${IOC_DIR}
${BUS_DIR}
${UTIL_DIR} ${UTIL_DIR}
) )

@ -0,0 +1,86 @@
#ifndef CPP_START_ANY_H
#define CPP_START_ANY_H
#include <memory>
#include <typeindex>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
struct Any {
Any() : m_tpIndex(std::type_index(typeid(void))) {}
Any(const Any &that) : m_ptr(that.Clone()), m_tpIndex(that.m_tpIndex) {}
Any(Any &&that) noexcept: m_ptr(std::move(that.m_ptr)), m_tpIndex(that.m_tpIndex) {}
//创建智能指针时对于一般的类型通过std::decay来移除引用和cv符从而获取原始类型
template<typename U, class = typename std::enable_if<!std::is_same<typename std::decay<U>::type, Any>::value, U>::type>
Any(U &&value) : m_ptr(new Derived<typename std::decay<U>::type>(std::forward<U>(value))),
m_tpIndex(type_index(typeid(typename std::decay<U>::type))) {}
bool IsNull() const { return !bool(m_ptr); }
template<class U>
bool Is() const {
return m_tpIndex == type_index(typeid(U));
}
//将Any转换为实际的类型
template<class U>
U &AnyCast() {
if (!Is<U>()) {
cout << "can not cast " << typeid(U).name() << " to " << m_tpIndex.name() << endl;
throw bad_cast();
}
auto derived = dynamic_cast<Derived <U> *> (m_ptr.get());
return derived->m_value;
}
Any &operator=(const Any &a) {
if (m_ptr == a.m_ptr)
return *this;
m_ptr = a.Clone();
m_tpIndex = a.m_tpIndex;
return *this;
}
private:
struct Base;
typedef std::unique_ptr<Base> BasePtr;
struct Base {
virtual ~Base() = default;
virtual BasePtr Clone() const = 0;
};
template<typename T>
struct Derived : Base {
template<typename U>
Derived(U &&value) : m_value(std::forward<U>(value)) {}
BasePtr Clone() const override {
return BasePtr(new Derived<T>(m_value));
}
T m_value;
};
BasePtr Clone() const {
if (m_ptr != nullptr)
return m_ptr->Clone();
return nullptr;
}
BasePtr m_ptr;
std::type_index m_tpIndex;
};
#endif //CPP_START_ANY_H

@ -0,0 +1,82 @@
#ifndef CPP_START_FUNCTION_TRAITS_H
#define CPP_START_FUNCTION_TRAITS_H
#include <functional>
#include <tuple>
//function_traits 获取普通函数、函数指针、std::function、函数对象以及成员函数的函数类型、返回类型、参数个数和参数的具体类型。
//转换为std::function和函数指针
template<typename T>
struct function_traits;
//普通函数
//返回类型Ret 参数列表Args
template<typename Ret, typename... Args>
struct function_traits<Ret(Args...)> {
public:
enum {
arity = sizeof...(Args)
}; //enum 定义参数列表的个数arity常量
//定义别名
typedef Ret function_type(Args...);
typedef Ret return_type;
using std_function_type = std::function<function_type>;
typedef Ret (*pointer)(Args...);
template<size_t I>
struct args {
//static_assert(常量表达式,错误提示字符串) 静态断言,
static_assert(I < arity, "index is out of range,index less than sizeof Args");
//std::tuple_element 获取元素的类型
using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
};
};
template<typename Ret, typename... Args>
struct function_traits<Ret(*)(Args...)> : function_traits<Ret(Args...)> {
};
template<typename Ret, typename... Args>
struct function_traits<std::function<Ret(Args...)>> : function_traits<Ret(Args...)> {
};
#define FUNCTION_TRAITS(...) \
template <typename ReturnType,typename ClassType,typename... Args> \
struct function_traits<ReturnType(ClassType::*)(Args...) __VA_ARGS__>:function_traits<ReturnType(Args...)>{}; \
FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)
//函数对象
template<typename Callable>
//decltype 类型说明符 作用时选择并返回操作数的数据类型.
struct function_traits : function_traits<decltype(&Callable::operator())> {
};
// lambda表达式是一个匿名类使用一个lambda表达式实际就是使用一个匿名类的匿名对象匿名类内部包含operator()调用符。
// operator()的返回类型、形参列表以及 函数体与lambda表达式相对应因此可像函数调用一样使用lambda表达式。
//可通过function_traits获取lambda表达式的operator()类型之后再将其转换为std::function
template<typename Function>
typename function_traits<Function>::std_function_type to_function(const Function &lambda) {
return static_cast<typename function_traits<Function>::std_function_type>(lambda);
}
template<typename Function>
typename function_traits<Function>::std_function_type to_function(Function &&lamdba) {
return static_cast<typename function_traits<Function>::std_function_type>(std::forward<Function>(lamdba));
}
template<typename Function>
typename function_traits<Function>::pointer to_function_pointer(const Function &lambda) {
return static_cast<typename function_traits<Function>::pointer>(lambda);
}
#endif //CPP_START_FUNCTION_TRAITS_H

@ -0,0 +1,81 @@
#ifndef CPP_START_MESSAGE_BUS_H
#define CPP_START_MESSAGE_BUS_H
#include <string>
#include <functional>
#include <map>
#include "../base/any.h"
#include "../base/function_traits.h"
#include "../base/non_copy_able.h"
using namespace std;
class MessageBus : public NonCopyAble {
public:
//注册消息
template<typename F>
void Attach(F &&f, const string &strTopic = "") {
auto func = to_function(std::forward<F>(f));
Add(strTopic, std::move(func));
}
//发送消息
template<typename R>
//无参数
void SendReq(const string &strTopic = "") {
//std::function 函数对象类包装了满足该函数模板类型的任意函数对象这些目标实体包括普通函数、Lambda表达式、函数指针、模函数、类成员函数、类静态函数以及其它的函数对象
using function_type = std::function<R()>;
string strMsgType = strTopic + string("##") + typeid(function_type).name();
std::pair<std::multimap<string, Any>::iterator, std::multimap<string, Any>::iterator> range = m_map.equal_range(
strMsgType);
for (Iterator it = range.first; it != range.second; ++it) {
auto f = it->second.AnyCast<function_type>();
f();
}
}
template<typename R, typename... Args>
//有参数
void SendReq(Args &&... args, const string &strTopic = "") {
using function_type = std::function<R(Args...)>;
string strMsgType = strTopic + string("##") + typeid(function_type).name();
cout << "send Msg: " << strMsgType << endl;
auto range = m_map.equal_range(strMsgType);
for (Iterator it = range.first; it != range.second; ++it) {
auto f = it->second.AnyCast<function_type>();
f(std::forward<Args>(args)...);
}
}
//移除某个主题,需要主题和消息类型
template<typename R, typename... Args>
void Remove(const string &strTopic = "") {
using function_type = std::function<R(Args...)>;
string strMsgType = strTopic + string("##") + typeid(function_type).name();
cout << "remove message: " << strMsgType << endl;
int count = m_map.count(strMsgType);
auto range = m_map.equal_range(strMsgType);
m_map.erase(range.first, range.second);
}
private:
template<typename F>
void Add(const string &strTopic, F &&f) {
string strMsgType = strTopic + string("##") + typeid(F).name();//主题
//emplace 插入操作相比inset其能就地通过参数构造对象不需要拷贝或者移动内存使容器插入元素的性能得到进一步提升。
m_map.emplace(std::move(strMsgType), std::forward<F>(f));
cout << "register message: " << strMsgType << endl;
}
private:
std::multimap<string, Any> m_map; //存储注册的消息
typedef std::multimap<string, Any>::iterator Iterator;
};
#endif //CPP_START_MESSAGE_BUS_H

@ -0,0 +1,107 @@
#ifndef CPP_START_CONTAINER_H
#define CPP_START_CONTAINER_H
#include <unordered_map>
#include "../base/any.h"
#include "../base/non_copy_able.h"
#include <string>
#include <unordered_map>
#include <memory>
#include <functional>
using namespace std;
class IocContainer : NonCopyAble {
public:
IocContainer() {}
~IocContainer() {}
// 注册需要创建对象的构造函数
template<class T, typename Depend, typename... Args>
void RegisterType(const string &strKey) {
// 注意,这里创建的是依赖的对象!不再是创建对象!
// 通过闭包擦除了Depend参数类型
std::function<T *(Args...)> function = [](Args... args) { return new T(new Depend(args...)); };
RegisterType(strKey, function);
}
// 根据唯一标识查找对应的构造函数,并创建指针对象
template<class T, typename... Args>
T *Resolve(const string &strKey, Args... args) {
if (m_creatorMap.find(strKey) == m_creatorMap.end()) {
return nullptr;
}
Any resolver = m_creatorMap[strKey];
// 将查找到的Any转换为function
std::function<T *(Args...)> function = resolver.AnyCast<std::function<T *(Args...)>>();
return function(args...);
}
// 创建智能指针对象
template<class T, typename... Args>
std::shared_ptr<T> ResolveShared(const string &strKey, Args... args) {
T *ptr = Resolve<T>(strKey, args...);
return std::shared_ptr<T>(ptr);
}
void RegisterType(const string &strKey, Any constructor) {
if (m_creatorMap.find(strKey) != m_creatorMap.end()) {
throw std::invalid_argument("this key has already exist!");
}
// 通过Any擦除不同类型的构造器
m_creatorMap.emplace(strKey, constructor);
}
private:
unordered_map<string, Any> m_creatorMap;
};
/*
class Container : NonCopyAble {
private:
std::unordered_map<std::string, Any> mCreatorMap;
public:
Container() {};
~Container() {};
template<typename T, typename Depend, typename... Args>
void registerType(const std::string &key) {
std::function<T *(Args...)> func = [](Args... args) {
return new T(new Depend(args...));
};
registerType(key, func);
}
template<typename T, typename... Args>
T *resolve(const std::string &key, Args ... args) {
if (mCreatorMap.find(key) == mCreatorMap.end()) {
return nullptr;
}
Any constructor = mCreatorMap[key];
std::function<T *(Args...)> function = constructor.cast<std::function<T *(Args...)>>();
return function(args...);
}
private:
void registerType(const std::string &key, Any constructor) {
auto it = mCreatorMap.find(key);
auto end = mCreatorMap.end();
if (mCreatorMap.find(key) != mCreatorMap.end()) {
// TODO 多次添加
throw std::invalid_argument("this key has aleady exist!");
}
mCreatorMap.emplace(key, constructor);
}
};
*/
#endif //CPP_START_CONTAINER_H

@ -1,133 +1,6 @@
#include <iostream> #include <iostream>
#include <map>
#include <thread> #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; std::mutex g_lock;
void func() { void func() {
@ -135,15 +8,31 @@ void func() {
std::this_thread::sleep_for(std::chrono::seconds(2)); std::this_thread::sleep_for(std::chrono::seconds(2));
} }
void thread_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;
}
#include "base/sync_queue.h" #include "base/sync_queue.h"
void sync_test(){
void sync_test() {
// 同步队列 // 同步队列
auto queue = new SyncQueue<int>(3); auto queue = new SyncQueue<int>(3);
// 每2秒取出进行消费 // 每2秒取出进行消费
std::thread producer([&](){ std::thread producer([&]() {
int i = 0; int i = 0;
while (i < 9){ while (i < 9) {
queue->dequeue(i); queue->dequeue(i);
std::this_thread::sleep_for(std::chrono::seconds(2)); std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "dequeue: " << i << std::endl; std::cout << "dequeue: " << i << std::endl;
@ -151,7 +40,7 @@ void sync_test(){
}); });
// 持续写入 // 持续写入
std::thread consumer([&](){ std::thread consumer([&]() {
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
queue->enqueue(i); queue->enqueue(i);
std::cout << "enqueue: " << i << std::endl; std::cout << "enqueue: " << i << std::endl;
@ -162,12 +51,11 @@ void sync_test(){
consumer.join(); consumer.join();
} }
#include <chrono> #include <chrono>
#include <iomanip> #include <iomanip>
#include "util/stop_watch.h" #include "util/stop_watch.h"
void chrono_test(){ void chrono_test() {
StopWatch stopWatch; StopWatch stopWatch;
@ -181,7 +69,7 @@ void chrono_test(){
std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
// 将 time_point 转为 ctime // 将 time_point 转为 ctime
std::time_t last = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24)); 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)); std::time_t next = std::chrono::system_clock::to_time_t(now + std::chrono::hours(24));
// 使用put_time格式化时间 // 使用put_time格式化时间
std::cout std::cout
@ -198,22 +86,23 @@ void chrono_test(){
} }
#include "base/thread_pool.h" #include "base/thread_pool.h"
void thread_test(){
ThreadPool pool(3,10);
std::thread t0([&pool]{ void threadpool_test() {
ThreadPool pool(3, 10);
std::thread t0([&pool] {
for (int i = 0; i < 100; ++i) { for (int i = 0; i < 100; ++i) {
auto thdId = std::this_thread::get_id(); auto thdId = std::this_thread::get_id();
pool.add([thdId]{ pool.add([thdId] {
std::cout << "thread 1 id:" << thdId << std::endl; std::cout << "thread 1 id:" << thdId << std::endl;
}); });
} }
}); });
std::thread t1([&pool]{ std::thread t1([&pool] {
for (int i = 0; i < 100; ++i) { for (int i = 0; i < 100; ++i) {
auto thdId = std::this_thread::get_id(); auto thdId = std::this_thread::get_id();
pool.add([thdId]{ pool.add([thdId] {
std::cout << "thread 2 id:" << thdId << std::endl; std::cout << "thread 2 id:" << thdId << std::endl;
}); });
} }
@ -227,19 +116,19 @@ void thread_test(){
t1.join(); t1.join();
} }
#include "aspect/aspect.h" #include "aspect/aspect.h"
#include "test/time_elapsed_aspect.h" #include "test/time_elapsed_aspect.h"
#include "test/log_aspect.h" #include "test/log_aspect.h"
void HT(int a)
{ void HT(int a) {
std::cout << "real HT function " << a << std::endl; std::cout << "real HT function " << a << std::endl;
} }
void aop_test(){
void aop_test() {
using namespace std; using namespace std;
aop<LogAspect, TimeElapsedAspect>([](int a){ aop<LogAspect, TimeElapsedAspect>([](int a) {
std::thread t([a](){ std::thread t([a]() {
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "run function, arg is " << a << std::endl; std::cout << "run function, arg is " << a << std::endl;
}); });
@ -252,41 +141,140 @@ void aop_test(){
aop<LogAspect>(f, 100); aop<LogAspect>(f, 100);
} }
int main() {
// 同步队列测试
// sync_test();
// 时间工具测试
// chrono_test();
// 线程池测试
// thread_test();
// AOP测试
aop_test();
#include "base/any.h"
void any_test() {
Any n;
auto r = n.IsNull();//true
string s1 = "hello";
n = s1;
n = "world";
n.AnyCast<int>(); //can not cast int to string
Any n1 = 1;
n1.Is<int>(); //true
}
#include "ioc/container.h"
void ioc_test() {
struct Base {
virtual ~Base() = default;
virtual void Func() = 0;
};
struct DerivedB : public Base {
DerivedB(int a, double b) : m_a(a), m_b(b) {
}
~DerivedB() override = default;
void Func() override {
cout << "DerivedB run :" << m_a + m_b << endl;
}
private:
int m_a;
double m_b;
};
struct DerivedC : public Base {
~DerivedC() override = default;
void Func() override {
std::cout << "DerivedC " << std::endl;
};
};
struct A {
A(Base *ptr) : m_ptr(ptr) {
}
~A() {
if (m_ptr != nullptr) {
delete m_ptr;
m_ptr = nullptr;
}
}
void Func() {
m_ptr->Func();
}
private:
Base *m_ptr;
};
IocContainer ioc;
// TODO 可通过CRTP奇怪的重复模板模式进行自动注册
// 注册依赖关系
ioc.RegisterType<A, DerivedC>("C");
ioc.RegisterType<A, DerivedB, int, double>("B");
// 通过容器进行初始化
auto pc = ioc.ResolveShared<A>("C");
// 注意DerivedB的参数int,double
auto pb = ioc.ResolveShared<A>("B", 1, 2.0);
// auto start = std::chrono::duration_cast<std::chrono::milliseconds>( pc->Func();
// std::chrono::system_clock::now().time_since_epoch()).count(); pb->Func();
// std::cout << "start time: " << start / 1000 << std::endl; }
// std::thread t0(func);
// std::thread t1(func); #include "bus/message_bus.h"
// std::thread t2(func);
// t0.join(); // 阻塞执行 void message_test() {
// t1.detach(); // 分离线程何对象,之后就无法何线程发送联系 MessageBus bus;
// t2.join(); //注册消息
// auto end = std::chrono::duration_cast<std::chrono::milliseconds>( bus.Attach([](int a) { cout << "no reference: " << a << endl; });
// std::chrono::system_clock::now().time_since_epoch()).count(); bus.Attach([](int &a) { cout << "lvalue reference: " << a << endl; });
// std::cout << " end time: " << end / 1000 << std::endl; bus.Attach([](int &&a) { cout << "rvalue reference: " << a << endl; });
bus.Attach([](const int &a) { cout << "const lvalue reference: " << a << endl; });
// A&& a = getA(); bus.Attach([](int a) {
// cout << "no reference has return value and key: " << a << endl;
// expand(1,2,3,4); return a;
// }, "a");
// std::cout << GetLeftSize<int>::value << std::endl;
// int i = 2;
// f(); bus.SendReq<void, int>(2);
// f(1); bus.SendReq<int, int>(2, "a");
// f(1,2.5,""); bus.SendReq<void, int &>(i);
// bus.SendReq<void, const int &>(2);
// foreach(); bus.SendReq<void, int &&>(2);
bus.Remove<void, int>();
bus.Remove<int, int>("a");
bus.Remove<void, int &>();
bus.Remove<void, const int &>();
bus.Remove<void, int &&>();
bus.SendReq<void, int>(2);
bus.SendReq<int, int>(2, "a");
bus.SendReq<void, int &>(i);
bus.SendReq<void, const int &>(2);
bus.SendReq<void, int &&>(2);
}
int main() {
// 线程测试
thread_test();
// 同步队列测试
sync_test();
// 时间工具测试
chrono_test();
// 线程池测试
threadpool_test();
// AOP测试
aop_test();
// Any测试
any_test();
// IoC测试
ioc_test();
// 总线测试
message_test();
return 0; return 0;
} }
Loading…
Cancel
Save