• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 线程安全map
2
3## 概述
4
5### 简介
6提供了一个线程安全的map实现。SafeMap在STL map基础上封装互斥锁,以确保对map的操作安全。
7
8## 涉及功能
9### class SafeMap
10#### 接口说明
11
12
13|返回类型           |名称           |
14| -------------- | -------------- |
15| | **SafeMap**() |
16| | **SafeMap**(const SafeMap& rhs) |
17| | **~SafeMap**() |
18| void | **Clear**()<br>删除map中存储的所有键值对。  |
19| void | **EnsureInsert**(const K& key, const V& value)<br>在map中插入元素。  |
20| void | **Erase**(const K& key)<br>删除map中键为key的键值对。  |
21| bool | **Find**(const K& key, V& value)<br>在map中查找元素。  |
22| bool | **FindOldAndSetNew**(const K& key, V& oldValue, const V& newValue)<br>在map中查找元素并将key对应的`oldValue`替换为`newValue`。  |
23| bool | **Insert**(const K& key, const V& value)<br>在map中插入新元素。  |
24| bool | **IsEmpty**()<br>判断map是否为空。  |
25| void | **Iterate**(const SafeMapCallBack& callback)<br>遍历map中的元素。  |
26| SafeMap& | **operator=**(const SafeMap& rhs) |
27| V | **ReadVal**(const K& key) <br> 线程安全地读map内元素|
28| void | **ChangeValueByLambda**(const K& key, LambdaCallback callback) <br> 线程安全地操作safemap内元素,操作行为需要自定义|
29| int | **Size**()<br>获取map的size大小。  |
30
31## 使用示例
32
331. 示例代码(伪代码)
34
35```c++
36#include <thread>
37#include <iostream>
38#include <functional>
39#include "../include/safe_map.h"
40
41using namespace OHOS;
42using namespace std;
43
44constexpr int THREAD_NUM = 5;
45thread threads[THREAD_NUM * 2];
46SafeMap<int, string> sm;
47
48bool InsertHandler(const int& key, const string& value)
49{
50    if (sm.Insert(key,value)) {
51        cout << "Insert key: " << key << endl;
52        return true;
53    } else {
54        return false;
55    }
56}
57
58bool FindHandler(const int& key, string& value)
59{
60    if (sm.Find(key,value)) {
61        cout << "Find key: " << key << " with value: " << value << endl;
62        return true;
63    } else {
64        return false;
65    }
66}
67
68
69int main()
70{
71    for (int i = 0; i < THREAD_NUM; i++) {
72        string name = "Thread" + to_string(i);
73        threads[i] = thread(&InsertHandler, i, name);
74    }
75
76    for (int i = 0; i < THREAD_NUM; i++) {
77        string out;
78        threads[i + THREAD_NUM] = thread(&FindHandler, i, ref(out));
79    }
80
81    this_thread::sleep_for(chrono::milliseconds(300));
82
83    for (int i = 0; i < 2 * THREAD_NUM; i++) {
84        threads[i].join();
85    }
86
87
88    if (sm.Size() == THREAD_NUM) {
89        cout << "Insert to SafeMap success!" << endl;
90    }
91}
92```
93
942. 测试用例编译运行方法
95
96- 测试用例代码参见base/test/unittest/common/utils_safe_map_test.cpp
97
98- 使用开发者自测试框架,使用方法参见:[开发自测试执行框架-测试用例执行](https://gitee.com/openharmony/testfwk_developer_test#%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%E6%89%A7%E8%A1%8C)
99
100- 使用以下具体命令以运行`safe_map.h`对应测试用例
101
102```bash
103run -t UT -tp utils -ts UtilsSafeMapTest
104```
105
1063. 接口使用变更
107
108- operator[]接口被废弃:该接口返回类型为引用,可以使用于读写场景,但在写场景情况下,该接口无法进行线程安全防护,因写行为本身基于引用由调用方触发,而非接口内部行为,接口内部持锁无法控制,因此失去线程安全的意义。
109
110```cpp
111SafeMap<int, string> sm;
112// Thread 1:
113sm[1] = "abc";
114
115// Thread 2:
116sm[2] = "def";
117```
118
119- 提供专用的线程安全读接口:ReadVal,该接口只具有safemap的读取能力,但保证线程安全
120
121```cpp
122SafeMap<string, int> sm;
123// Thread 1:
124sm.Insert("A", 1);
125int val = sm.ReadVal("A");
126```
127
128- 针对之前利用operator[]返回引用进行的特殊元素操作行为,提供了接口ChangeValueByLambda进行替换,调用者自定义元素操作函数,可保证在线程安全的情况下操作safemap元素。
129
130```cpp
131SafeMap<string, std::set<int>> sm;
132int val = 1;
133auto fn = [&](std::set<int> &value) -> void { // 自定义callback
134    value.emplace(val);
135}
136sm.ChangeValueByLambda("A", fn);
137```