/*
0.创建log文件对应的配置指针 log.cpp:590
sylar::ConfigVar >::ptr g_log_define = sylar::Config::Lookup("logs", std::set(), "logs config");在构造函数中,加入该配置对应的回调函数,并将其声明为静态变量,使其在main之前初始化
struct LogIniter{LogIniter() {g_log_define->addListener(匿名函数)}
}
static LogIniter __log_init;1.加载yaml文件 sylar::Config::LoadFromYaml(root);
2.LoadFromYaml中解析yaml,将yaml格式化为string:yaml;依次取出,判断key是否存在于std::map中
3.通过ConfigVarBase基类指针调用ConfigVar::fromString()方法,执行setValue()方法
4.setValue中若旧值和新值不同,触发回调函数
*/
log的基本配置信息
struct LogDefine {std::string name;LogLevel::Level level = LogLevel::UNKNOW;std::string formatter;std::vector appenders;bool operator==(const LogDefine& oth) const {return name == oth.name&& level == oth.level&& formatter == oth.formatter&& appenders ==oth.appenders;}bool operator<(const LogDefine& oth) const {return name < oth.name;}
};
logappender的基本配置信息
struct LogAppenderDefine {int type = 0; //1 File 2 StdoutLogLevel::Level level = LogLevel::UNKNOW;std::string formatter;std::string file;bool operator==(const LogAppenderDefine& oth) const {return type == oth.type&& level == oth.level&& formatter == oth.formatter&& file == oth.file;}
};
template<>
class LexicalCast > {
public:std::set operator() (const std::string& v) {YAML::Node node = YAML::Load(v);std::set vec;for(size_t i = 0; i < node.size(); ++i){auto n=node[i];if(!n["name"].IsDefined()) {std::cout<<"log config error: name is null, " << n<< std::endl;continue;}LogDefine ld;ld.name = n["name"].as();ld.level = LogLevel::FromString(n["level"].IsDefined() ? n["level"].as() : "");if(n["formatter"].IsDefined()) {ld.formatter = n["formatter"].as();}if(n["appenders"].IsDefined()){for(size_t x = 0; x < n["appenders"].size(); ++x) {auto a = n["appenders"][x];if(!a["type"].IsDefined()) {std::cout << "log config error: appenders.type is null, " << a << std::endl;continue;}std::string type = a["type"].as();LogAppenderDefine lad;if(type == "FileLogAppender"){lad.type = 1;if(!a["file"].IsDefined()){std::cout << "log config error: fileappenders.file is null, " << a << std::endl;continue;}lad.file = a["file"].as();}else if(type == "StdoutLogAppender"){lad.type = 2;}else{std::cout << "log config error: appenders.type is invaild, " << a << std::endl;continue;}ld.appenders.push_back(lad);}}vec.insert(ld);}return vec;}
};template<>
class LexicalCast, std::string> {
public:std::string operator() (const std::set& v) {YAML::Node node;for(auto& i : v){YAML::Node n;n["name"] = i.name;if(i.level != LogLevel::UNKNOW) {n["level"] = LogLevel::ToString(i.level);}if(i.formatter.empty()){n["formatter"] = i.formatter;}for(auto& a:i.appenders){YAML::Node na;if(a.type==1){na["type"] = "FileLogAppender";na["file"] = a.file;}else if(a.type==2){na["type"] = "StdoutLogAppender";}if(a.level != LogLevel::UNKNOW) {na["level"] = LogLevel::ToString(a.level);}if(!a.formatter.empty()){na["formatter"] = a.formatter;}n["appenders"].push_back(na);}node.push_back(n);}std::stringstream ss;ss << node;return ss.str();}
};
实现将当前配置输出为string
LoggerManger::toYamlString() —》 Logger::toYamlString() —》 LogAppender::toYamlString() 虚函数 --> StdoutLogAppender::toYamlString()
|
V
FileLogAppender::toYamlString()
通过封装semaphore和pthread实现
class Semaphore {
public:Semaphore(uint32_t count = 0);~Semaphore();void wait();void notify();
private:Semaphore(const Semaphore&) = delete;Semaphore(const Semaphore&&) = delete;Semaphore& operator=(const Semaphore&) = delete;private:sem_t m_semaphore;
};
通过模板的方式实现,离开锁的作用域后先解锁,再析构锁
template
struct ScopedLockImpl {
public:ScopedLockImpl(T& mutex):m_mutex(mutex) {m_mutex.lock();m_locked = true;}~ScopedLockImpl() {unlock();}void lock() {if(!m_locked) {m_mutex.lock();m_locked = true;}}void unlock() {if(m_locked) {m_mutex.unlock();m_locked = false;}}
private:T& m_mutex;bool m_locked;
};
同一时间只允许一个线程使用共享资源,读写速度较慢
包含ScopedLockImpl< Mutex >,当锁离开了作用域后先调用ScopedLockImpl::~ScopedLockImpl()析构函数实现解锁操作,再进行析构锁
class Mutex{
public:typedef ScopedLockImpl Lock;Mutex() {pthread_mutex_init(&m_mutex, nullptr);}~Mutex() {pthread_mutex_destroy(&m_mutex);}void lock() {pthread_mutex_lock(&m_mutex);}void unlock() {pthread_mutex_unlock(&m_mutex);}
private:pthread_mutex_t m_mutex;
};
读写分离,封装pthread_rwlock
速度较快,适合读多写少的情况
//读写模板
template
struct ReadScopedLockImpl {
public:ReadScopedLockImpl(T& mutex):m_mutex(mutex) {m_mutex.rdlock();m_locked = true;}~ReadScopedLockImpl() {unlock();}void lock() {if(!m_locked) {m_mutex.rdlock();m_locked = true;}}void unlock() {if(m_locked) {m_mutex.unlock();m_locked = false;}}
private:T& m_mutex;bool m_locked;
};
template
struct WriteScopedLockImpl {
public:WriteScopedLockImpl(T& mutex):m_mutex(mutex) {m_mutex.wrlock();m_locked = true;}~WriteScopedLockImpl() {unlock();}void lock() {if(!m_locked) {m_mutex.wrlock();m_locked = true;}}void unlock() {if(m_locked) {m_mutex.unlock();m_locked = false;}}
private:T& m_mutex;bool m_locked;
};
//读写锁
class RWMutex {
public:typedef ReadScopedLockImpl ReadLock;typedef WriteScopedLockImpl WriteLock;RWMutex() {pthread_rwlock_init(&m_lock, nullptr);}~RWMutex() {pthread_rwlock_destroy(&m_lock);}void rdlock() {pthread_rwlock_rdlock(&m_lock);}void wrlock() {pthread_rwlock_wrlock(&m_lock);}void unlock() {pthread_rwlock_unlock(&m_lock);}
private:pthread_rwlock_t m_lock;
};
适用于快任务,每次线程操作时间较短
若无法抢占任务时,锁进行自旋操作,不会立即挂起,而是一直等待上一个线程,可以设置等待时间
会发生死锁,如果等待的线程一直阻塞,自旋锁会一直自旋等待;在自旋锁还未释放时再次申请了一个自旋锁
class Spinlock {
public:typedef ScopedLockImpl Lock;Spinlock() {pthread_spin_init(&m_mutex, 0);}~Spinlock() {pthread_spin_destroy(&m_mutex);}void lock() {pthread_spin_lock(&m_mutex);}void unlock() {pthread_spin_unlock(&m_mutex);}
private:pthread_spinlock_t m_mutex;
};
无锁编程,容易引发临界资源的问题
封装原子操作,核心是比较并交换,如果想要插入的位置不是最后则一直向后移动,直至末尾开始插入
/*
A:当前值
V:内存值
B:新值
CAS(A, V, B){if(A == V){V = B;}else {重试或放弃}
}
ABA问题:A从5改为10 成功,B从5改为10 阻塞,C从10改为5 成功;这时候B采用CAS(5,5,10)判断成功,将5又改为了10,出现问题
解决:CAS判断时加入版本号,进行版本比较
*/
class CASLock {
public:typedef ScopedLockImpl Lock;CASLock() {m_mutex.clear();}~CASLock() {}void lock() {while(std::atomic_flag_test_and_set_explicit(&m_mutex, std::memory_order_acquire));}void unlock() {std::atomic_flag_clear_explicit(&m_mutex, std::memory_order_release);}
private:volatile std::atomic_flag m_mutex;
};
class Thread{
public:typedef std::shared_ptr ptr;Thread(std::function cb, const std::string& name);~Thread();pid_t getId() const {return m_id;}const std::string& getName() const {return m_name;}void join();static Thread* GetThis();static const std::string& GetName();static void SetName(const std::string& name);
private:Thread(const Thread&) = delete;Thread(const Thread&&) = delete;Thread& operator=(const Thread&) = delete;static void* run(void* arg);
private:pid_t m_id = -1;pthread_t m_thread = 0;std::function m_cb;std::string m_name;Semaphore m_semaphore;
};
使用自旋锁,在LogAppender、Logger、LoggerManger类中加入
多线程情况时,访问资源的函数都需要考虑加锁
std::string Logger::toYamlString();
void Logger::clearAppenders();
void Logger::setFormatter(LogFormatter::ptr val);
LogFormatter::ptr Logger::getFormatter();
void LogAppender::setFormatter(LogFormatter::ptr val);
LogFormatter::ptr LogAppender::getFormatter();
void Logger::log(LogLevel::Level level, LogEvent::ptr event);
void Logger::addAppender(LogAppender::ptr appender);
void Logger::delAppender(LogAppender::ptr appender);
void StdoutLogAppender::log(Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event);
std::string StdoutLogAppender::toYamlString();
void FileLogAppender::log(Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event);
std::string FileLogAppender::toYamlString();
bool FileLogAppender::reopen();
Logger::ptr LoggerManger::getLogger(const std::string& name);
std::string LoggerManger::toYamlString();
使用读写锁,读多写少的情况
//ConfigVar类:
std::string toString();
const T getValue();
void setValue(const T& v);
uint64_t addListener(on_change_cb cb);
void delListtener(uint64_t key);
on_change_cb getListener(uint64_t key);
void clearListener();
//Config类
void Config::Visit(std::function cb)
template
static typename ConfigVar::ptr Lookup(const std::string& name,const T& default_value, const std::string& description = "");
templatestatic typename ConfigVar::ptr Lookup(const std::string& name);
//ConfigVarBase类
ConfigVarBase::ptr Config::LookupBase(const std::string& name);
全部实现可见仓库,欢迎点赞。
上一篇:数据智仓功能介绍(一)