我正面临以下问题。我有a map
的受保护数据结构<ID , Object>
。只有一个映射数据结构,并且多个线程可能想使用set
从映射中get
和ID
的值。 Object
可以嵌套,如下面的示例代码所示。
#include <iostream>
#include <map>
#include <algorithm>
#include <mutex>
using namespace std;
struct C {
int r;
char s;
};
struct B {
int p;
char q;
C c;
};
struct A {
int x;
int y;
B b;
char z;
};
/*
A
L__ x
|
L__ y
|
L__ B
L__p
|
L__q
|
L__C
L__r
|
L__s
*/
/* the follwing is the
data structure to store objects of of type A
corresponding to an ID (int)
*/
map<int,A> Map;
mutex m;
/* Follwing are the desired
api's to set and get values from the Map
Locks are also required to handle concurrency
*/
void getValueFromMap(int id,/* what to pass ?? */) {
m.lock();
/* code to get the value of the specified varible */
m.unlock();
}
void setValueInMap(int id,/* what to pass ?? */) {
m.lock();
/* code to set the new value to the specified variable */
m.unlock();
}
int main() {
/* lets suppose Map has some A type objects already */
int id = 4;
/* assume I want to change the information (value of p) of id = 4*/
/* instead of doing the following */
m.lock();
Map[id].b.p = 12; /*update to some value */
m.unlock();
/* what I need the follwing */
setValueInMap(4,/* what_to_change , what_is_the_new_value etc .. */);
/*similarly */
/*if I want get the value of s */
int s;
m.lock();
getValueFromMap(id,/* what_to_get,placeholder (for example &s) */);
m.unlock();
}
我想使用函数对api
的{{1}}和setValueInMap
的值进行set
个调用(例如,get
具有固定数量的参数)呼叫和所有互斥工作将仅在这些map
呼叫内发生。尽管我仅展示了一个通用集合函数来设置api
的所有类型的成员变量,但不必如此(更多api函数调用没有问题)。
如何实施?
谢谢!
答案 0 :(得分:5)
如何使通用函数作用于地图:
std::map<int, A> Map;
std::mutex m;
template <typename F>
auto ActOnMap(F&& f) -> decltype(f(Map)) {
std::lock_guard<std::mutex> locker(m);
return f(Map);
}
(注意:您可能应该创建一个用于构造该类的类,并隐藏对map
和mutex
的直接访问。)
然后:
/* lets suppose Map has some A type objects already */
int id = 4;
/* assume I want to change the information (value of p) of id = 4*/
ActOnMap([id](std::map<int, A>&m){ m[id].b.p = 12;});
/*similarly */
/*if I want get the value of s */
int s = ActOnMap([id](std::map<int, A>&m){ return m[id].b.c.s;});
答案 1 :(得分:3)
主要问题是如何将所谓的“占位符”编码到C ++类型系统中。要选择:
普通索引(0 -> A.x
,3 -> B.q
等)和一些硬编码的switch语句(非常脆弱,不建议使用)。
相同,但是带有枚举而不是索引。没有比上面更好的了。
成员变量指针。这将变得非常尴尬,尤其是由于nested structure。
功能。您可以为每个(嵌套的)成员编写访问函数,并将函数指针传递给这些成员(或函子,例如lambda)。像这样:
void setBp(A& a, int value) { a.b.p = value; }
// etc.
template<typename T, typename SetterFunc>
setValueInMap(int key, SetterFunc setterFunc, T value) {
m.lock();
setterFunc(Map[id], value);
m.unlock();
}
// Usage
setValueInMap(4, setBp, 12);
请注意,这些方法都不是非常漂亮的。完全没有我会考虑更改底层设计,嵌套结构确实是此问题的根源。
答案 2 :(得分:1)
也许您可以选择RapidJson方法或基于if的方法(不太优雅):
(...)
void* getValueFromMap(int id, char structure, string item_name) {
m.lock();
if(structure == 'C') {
if(item_name.compare("r") == 0) {
return (void*) Map[id].B.C.r;
} else if(...
} else if(...
m.unlock();
}
void setValueInMap(int id, char structure, string item_name, void* item) {
m.lock();
if(structure == 'C') {
if(item_name.compare("r") == 0) {
Map[id].B.C.r = (int) item;
} else if(...
} else if(...
m.unlock();
}
int main() {
int r;
r = (int) getValueFromMap(4,'C',"r");
setValueInMap(5,'C',"r",(void*) r);
}
免责声明::我没有编译这段代码,所以它可能有错误。
答案 3 :(得分:1)
您可以轻松生成用于访问嵌套成员的lambda或函数的一种方法是编写函数或脚本以使用脚本语言生成它们。
# Ruby
def dig_lambda(*members)
dig = "Map[id].#{members.join '.'}"
puts "[&]() -> decltype(#{dig}) {return #{dig};}"
end
# prints [&]() -> decltype(Map[id].b.c.r) {return Map[id].b.c.r;}
dig_lambda %w[b c r]