如何在c ++中实现分布式映射的API?

时间:2013-08-21 20:54:14

标签: c++ api map iterator distributed

我正在用c ++实现分布式地图并寻找一个好的API设计。 第一个和直接的选择是使它完全像std :: map。问题在于迭代器。

IMap<std::string,Person>::iterator it;
it =  map.find("sample");
if(it == map.end() ){
    //NULL
}
for(it = map.begin(); it != map.end(); it++){
    //iterate
}

在分布式上下文中(至少在我正在实现的上下文中),没有地图的开头和结尾。它不是以任何方式排序的,因此返回迭代器似乎不是一个选项。

第二个选项是按副本返回值类,如下所示:

Person emptyPerson; 
Person person = map.get("sample");
if(person == emptyPerson){
    //NULL
}

问题在于NULL检查看起来很奇怪。您可以先询问它是否可用然后获取对象,但要求是这些操作必须是原子的。

第三个选项是返回指针:

Person* person = map.get("sample");
if(person == NULL){
    //NULL
}

我不想这样做,因为它容易出错。用户需要删除我在内部创建的指针。

我正在考虑返回一个包装用户对象的类,如:

value_reference<std::map, Person>  person = map.get("sample");
if(value_reference.hasValue() ){
    Person p = value_reference;
}

那么你认为最好的方法是什么?

你知道任何与我的分布式地图的要求相似的api吗?

2 个答案:

答案 0 :(得分:1)

我会说像选项3这样的东西是最好的。您可以使用C ++ 11中引入的标准智能指针类型之一来模拟它,因此您仍然可以创建指针,但用户不必释放它。如下所示:

std::unqiue_ptr<Person> person = map.get("sample");
if(person) {
      person->makeMeASandwitch();
}

答案 1 :(得分:1)

根据您的术语“分布式地图”,我做出以下假设:

  • 数据的一个子集在本地可用,对于不需要执行某些远程提取的数据集。
  • 写入返回的对象不应自动保留在数据存储中。应该改为显式更新请求。

如果这是真的,那么迭代器不是你想要的,也不是你想要的STL容器模型。 C ++ Iterator概念要求您实现预增量(++i)运算符,如果您的数据是无序的并且分布在多个节点上,那么请求“给我下一个条目”是没有意义的。

如果你想出于互操作性原因想要模拟STL容器和迭代器,你可能会创建一个可怕的kludge:让map end()方法返回一个sentinel迭代器实例,并让你的迭代器operator++()返回同样的哨兵。实际上,每个迭代器都会指向“地图中的最后一个元素”。我强烈建议不要采取这种方法,除非有必要,我认为不会。

听起来你想要的是一个简单的CRUD模型,必须明确请求更新。在这种情况下,您的API看起来像:

template <typename TKey, typename TValue>
class IMap<TKey, TValue>
{
public:
    void create(TKey const & key, TValue const & value) = 0;
    std::unique_ptr<TValue> retrieve(TKey const & key) = 0;
    bool update(TKey const & key, TValue const & value) = 0;
    bool remove(TKey const & key) = 0;
};

在检索案例中,您只需按照建议返回空指针。 std::unique_ptr<>将确保调用者删除已分配的对象或明确取得对象的所有权。

“返回指向新分配对象的指针”的替代方法是让调用者传入引用,如果在地图中找到该值,该方法将返回true。例如,这将允许调用者直接将对象检索到数组槽或其他本地结构中,而无需中间堆分配。

bool retrieve(TKey const & key, TValue & value) = 0;

使用此方法看起来像:

Person person;

if (map.retrieve("sample", person)) {
    std::cout << "Found person: " << person << std::endl;
} else {
    std::cout << "Did not find person." << std::endl;
}

你也可以提供两个重载,默认情况下,返回指针的那个可以用另一个实现:

template <typename TKey, typename TValue>
std::unique_ptr<TValue> IMap<TKey, TValue>::retrieve(TKey const & key)
{
    TValue v;
    return std::unique_ptr<TValue>(retrieve(key, v) ? new TValue(v) : nullptr);
}