今天看couchbase 回调代码的时候发现 callback 函数有一个参数是 cookie,相当于一个调用异步函数时的上下文。
http://docs.couchbase.com/developer/c-2.4/c-intro.html
我们代码里面是类似这样用的。
// 回调函数
static void get_callback(lcb_t instance,
const void* cookie,
lcb_error_t code,
const lcb_get_resp_t* resp) {
//....修改 cookie
}
// instance, install 回调函数
lcb_t cb;
lcb_set_get_callback(cb, get_callback);
// 从couchbase取数据
std::deque<int64_t> uids;
lcb_get(cb, &uids, MAX_ITEMS, pcmds);
因为取数据的线程和调用回调函数的线程是两个不同的线程,
而uids是取数据的线程所在的栈上的,回调函数怎么可以直接操作这个变量呢?
不是一直说同一个进程的多个线程共享堆,但是都有自己的栈么?
恩,是的,这个说法是没错,线程有自己的栈,但是不代表它不能访问其他的线程的栈。
深入理解计算机系统 P663 是这样说的:
“各自独立的线程栈的存储器模型不是那么整齐清楚的。这些栈被保存在虚拟地址空间的栈区域中,并且通常是被相应的线程独立访问的。
我们说通常而不是总是,是因为不同的线程栈是不对其他线程设防的。所以,如果一个线程以某种方式得到一个指向其他线程栈的指针,那么他就可以读写这个栈的任何部分”
下面是测试代码。
#include <thread>
#include <iostream>
using namespace std;
void func(int* pa) {
cout << pa << endl;
cout << *pa << endl;
*pa = 15;
}
int main() {
int a = 5;
cout << "main, &a: " << &a << endl;
thread thrd(func, &a);
thrd.join();
cout << "main, &a: " << &a << endl;
cout << "main, a: " << a << endl;
}
[root@licchen-test-dev001-bjdxt tests]# g++ -std=c++11 -lpthread thread_2.cpp
[root@licchen-test-dev001-bjdxt tests]# ./a.out
main, &a: 0x7ffff5ae9564
0x7ffff5ae9564
5
main, &a: 0x7ffff5ae9564
main, a: 15