-
Notifications
You must be signed in to change notification settings - Fork 0
APTXASZC edited this page Jun 21, 2023
·
10 revisions
##2023
2023-3-15
// 1. sprintf(char* tar,const char* src);
// 将src的内容复制到tar中
char buf[256];
sprintf(buf,"hello world %d",618);
fputs(buf);
2023-5-26 弱回调 $核心思路:bind对象成员方法以及该成员的weak_ptr,使用该方法时上升weak_ptr来判断对象是否销毁
class stock // 股票类,里面有股票的名字和价值
{
public:
stock(const string& s):name(s),value(5) {}
string name;
double value;
};
class stockFactory :public enable_shared_from_this<stockFactory> // 股票工厂类,继承了enable_shared_from_this来让this指针是shared,这样使用bind时能让this的引用计数+1进而使得factory不会在stock之前销毁(因为stock销毁时要保证在factory的hashtable中删除以避免内存泄漏,因此stock析构时不可避免的要调用factory中的方法)
{
public:
shared_ptr<stock> get(string const key)
{
shared_ptr<stock> p;
lock_guard<mutex> lk(mut);
weak_ptr<stock>& wk = stocks[key];
p = wk.lock();
if (!p)
{ // 弱回调技术 : 区别于前述的factory延寿方法,有时需要 对象还活着时,调用其成员函数,否则忽视 这样的语义,也就是不延长对象的生命并且要让程序完好的执行
p.reset(new stock(key), bind(&stockFactory::weakDeleteCallback, weak_ptr<stockFactory>(shared_from_this()), placeholders::_1)); // 这里用weak_ptr来强转shared的this指针以保证bind时this指针生命周期不变,并且在之后通过上升来判断factory是否销毁以分别操作
wk = p;
// bind将函数托管给functional,其生命周期比较长
}
return p;
}
private:
static void weakDeleteCallback(const weak_ptr<stockFactory>& wkf,stock* st)
{
shared_ptr<stockFactory> t(wkf.lock());
if (t)
{
t->removeStock(st);
}
delete st;
}
void removeStock(stock* s)
{
if (s)
{
lock_guard<mutex> lk(mut);
stocks.erase(s->name);
}
}
mutable mutex mut;
unordered_map<string, weak_ptr<stock>> stocks;
};
class beCall
{
public:
void hlwd(const weak_ptr<beCall>& s)
{
shared_ptr<beCall> t = s.lock();
if (t)
{
cout << "beCall还没被销毁" << endl;
}
else
{
cout << "beCall已经被销毁" << endl;
}
return;
}
};
int main() {
shared_ptr<beCall> p(new beCall);
auto f = bind(&(beCall::hlwd),cref(p), weak_ptr<beCall>(p));
p.reset();
f();
return 0;
}
这里mutable是为了让const对象也能调用内部互斥
2023-5-30
condition_variable.notify_one() // prepare线程完成prepare后可以调用该方法通知process线程
condition_variable.wait(lock,func) // func成立则继续向下执行,否则unlock and sleep,sleep时被notify则醒来lock再check func
double strtod(const char* s,char** str_end);
// 将s转化为double类型并返回
// s指向字符串的首地址,执行完后*str_end指向转换完的字符最后一位的下一位,如果里面没有数字(或者称为可转化对象),则end不会移动,在s=end赋值后执行strtod,判断s==end就可以跳出了
printf("'%.*s' -> ", (int)(end-p), p); // 打印s并且保留字符'.'后面end-p位
template<typename T>
class safe_queue {
private:
struct node { // 节点的核心 : 数据以及next指针
shared_ptr<T> data;
unique_ptr<node> next;
};
unique_ptr<node> head;
node* tail;
mutex head_mut;
mutex tail_mut;
condition_variable cv;
public:
safe_queue():head(new node),tail(head.get()){} // 初始化一下,保证一开始整个queue是空的
safe_queue(const safe_queue&) = delete;
safe_queue& operator=(const safe_queue&) = delete;
node* get_tail() // 即使是拿tail,也要保证线程安全
{
lock_guard<mutex> lk(tail_mut);
return tail;
}
unique_lock<mutex> wait_for_data() // 这里等待队列非空
{
unique_lock<mutex> lk(head_mut);
cv.wait(lk, [] {return head.get() != get_tail(); });
return move(lk); // 将锁交给调用者
}
unique_ptr<node> pop_head() // 辅助函数弹首操作
{
unique_ptr<node> old_head = move(head);
head = move(head->next);
return old_head;
}
unique_ptr<node> wait_pop_head()
{
unique_lock<mutex> lk(wait_for_data());
return pop_head();
}
unique_ptr<node> wait_pop_head(T& val)
{
unique_lock<mutex> lk(wait_for_data());
val = move(*head->data);
return pop_head();
}
void push(T val) // 推入数据,同时通知wait_for_data
{
shared_ptr<T> dt = make_shared<T>(move(val));
unique_ptr<node> p(new node);
{
lock_guard<mutex> lk(tail_mut);
const node* new_tail = p.get();
tail->data = dt;
tail->next = move(p);
tail = new_tail;
}
cv.notify_one();
}
shared_ptr<T> wait_and_pop()
{
const unique_ptr<node> old_head = wait_pop_head();
return old_head->data;
}
void wait_and_pop(T& val)
{
const unique_ptr<node> old_head = wait_pop_head();
val = *(old_head->data);
}
};