1、协程局部存储键值
需要一种数据结构来存储key值(用来判断协程局部存储空间的使用情况,used或者unsed):
1 2 3 4
| typedef struct co_specific { uint32_t used; void (*destructor)(void*); } specific_t;
|
有一个全局的指针co_specific
指向一个specific_t
数组。
graph LR
key1[key1] --- key2[key2]
key2[key2] --- key3[key3]
key3[key3] --- key4[key4]
co_specific_num
变量用来记录specific_t
数组的长度。
2、协程自身有一块内存用来存放data
1 2 3 4 5 6
| typedef struct co_struct { void **specific; int spec_num; } co_t;
|
specific
数组里面存放了一些指针,这些指针指向协程私有的数据。
specific_t
和specific
数组是有所对应的:
graph LR
key1[key1] -.-> data1_ptr[data1_ptr]
key2[key2] -.-> data2_ptr[data2_ptr]
key3[key3] -.-> data3_ptr[data3_ptr]
key4[key4] -.-> data4_ptr[data4_ptr]
key1[key1] --- key2[key2]
key2[key2] --- key3[key3]
key3[key3] --- key4[key4]
data1_ptr[data1_ptr] --- data2_ptr[data2_ptr]
data2_ptr[data2_ptr] --- data3_ptr[data3_ptr]
data3_ptr[data3_ptr] --- data4_ptr[data4_ptr]
data1_ptr[data1_ptr] --> data1[data1]
data2_ptr[data2_ptr] --> data2[data2]
data3_ptr[data3_ptr] --> data3[data3]
data4_ptr[data4_ptr] --> data4[data4]
3、算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int co_key_create(void (*destructor)(void*)) { specific_t *specific = co_specific; specific_t *specific_end = specific + co_specific_num; int old_num = co_specific_num; while(specific < specific_end) { if(!specific->used) { specific->used = 1; specific->destructor = destructor; return specific - co_specific; } specific++; } co_specific_num += 16; co_specific = realloc(co_specific, co_specific_num * sizeof(specific_t)); memset(co_specific + old_num, 0, 16 * sizeof(specific_t)); co_specific[old_num].used = 1; co_specific[old_num].destructor = destructor; return old_num; }
|
1 2 3 4 5 6 7 8 9 10 11
| int co_key_delete(int key) { if(unlikely(key < 0) || co_specific_num <= key || !co_specific[key].used) { return EINVAL; } co_specific[key].used = 0; co_specific[key].destructor = NULL; return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| int co_setspecific(int key, const void *value) { if(unlikely(key < 0) || co_specific_num <= key || !co_specific[key].used) { return EINVAL; } if(current->spec_num <= key) { current->specific = realloc(current->specific, co_specific_num*sizeof(void *)); memset(current->specific + current->spec_num, 0, (co_specific_num-current->spec_num)*sizeof(void *)); current->spec_num = co_specific_num; } current->specific[key] = (void *)value; return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12
| void *co_getspecific(int key) { if(unlikely(key < 0) || co_specific_num <= key || !co_specific[key].used) { return NULL; } if(current->spec_num <= key) return NULL; else return current->specific[key]; }
|
代码来自这里。