【问题标题】:boost::multi_index_container - equal_range valuesboost::multi_index_container - equal_range 值
【发布时间】:2013-12-06 21:11:21
【问题描述】:

我一直在尝试使用带有映射的 boost 进程间库以及现在共享内存中的 multi_index_container 的一些解决方案。使用 multi_index_container,除了迭代从 equal_range 返回的值之外,还有其他方法吗?我希望从我的 non_unique 索引(站名,例如 ST0012345)中检索结果子集,然后查找/获取我需要的实际测量类型(例如温度)。

我需要检索测量点的唯一 pointID 值(例如 ST0012345SMD10000456.VoltsA = pointID - 45789)以将测量值插入数据 Historian。我喜欢 multi_index_container 的想法,因为我们的消息有效负载包含大约 100 到 200 个针对数组中的一个站的测量值,所以我想我可以对包含 500,000 多个项目的共享内存容器进行一次调用,然后从一个使用长的唯一字符串名称的列表要小得多。

从我所做的阅读看来,我可能只能遍历从 multi_index_container 返回的较小列表,而不是进行获取/查找。

如果是这种情况,我最好还是坚持我原来的共享内存映射解决方案(我正在使用),正如我所说,它包含 500,000 多个长字符串来匹配以检索我们数据所需的 pointID历史学家。每秒处理 200 个点的数据速率很高(我发现我的数据映射查找在测试环境中每秒可以达到 2000 次查找)。

另外,如果我确实使用了地图,那么在共享内存中拥有多个地图有什么害处吗?悉尼车站地图(约 300,000 点),纽卡斯尔车站地图(约 200,000 点)。

下面是我的程序的代码,它从创建 multi_index_container 的单独进程中检索项目。

using namespace boost::interprocess;
using namespace System;

namespace bmi = boost::multi_index;

typedef managed_shared_memory::allocator<char>::type              char_allocator;
typedef basic_string<char, std::char_traits<char>, char_allocator>shm_string;

struct tag
{
    shm_string name;
    shm_string stn;
    shm_string mtype;
    int         id;
    tag( const char *name_
      , const char_allocator &a
      , const char *stn_
      , const char_allocator &b
      , const char *mtype_
      , const char_allocator &d
      , int id_)
      : name(name_, a),
        stn(stn_, b),
        mtype(mtype_, d),
        id(id_)
    {}
};

struct name{};
struct stn{};
struct mtype{};
struct id{};

typedef bmi::multi_index_container<
  tag,
  bmi::indexed_by<
    bmi::ordered_unique
      <bmi::tag<name>,  BOOST_MULTI_INDEX_MEMBER(tag,shm_string,name)>,
    bmi::ordered_non_unique<
      bmi::tag<stn>,BOOST_MULTI_INDEX_MEMBER(tag,shm_string,stn)> >,
  managed_shared_memory::allocator<tag>::type
> tag_set;


typedef tag_set::iterator iterator;


int main(array<System::String ^> ^args)
{
   try{

      managed_shared_memory segment(open_only,"MySharedMemory");

      offset_ptr<tag_set> es = segment.find<tag_set>("My MultiIndex Container").first;

      char_allocator alloc_inst(segment.get_allocator<char>());
      shm_string  key_object(alloc_inst);
      key_object = "ST0012345SMD10000456";

      std::pair<tag_set::index<stn>::type::iterator, tag_set::index<stn>::type::iterator> values = es->get<stn>().equal_range(key_object);
      while(values.first != values.second) { 
          std::cout << values.first->name << " -- " <<"  ("<<values.first->stn<<","<<values.first->mtype<<")\n"; 
          ++values.first; 
      }


      char_allocator alloc_inst2(segment.get_allocator<char>());
      shm_string  key_object2(alloc_inst2);
      key_object2 = "ST0012345SMD10000456.VoltsA";

      ///// is there any way something like the following can be done rather than the above iterator ?????
      iterator it = values->get<name>(key_object2);  <-------  ????????????????????????
   }
   catch(const std::exception &exc){
       std::cerr << "Exception caught: " << exc.what();
      throw;
   }
   Sleep(3000);
   return 0;

}

【问题讨论】:

  • 那么,问题是什么?
  • 从 equal_range 返回的值,有没有办法使用唯一键查找或获取这些值,或者我只能遍历这些值?
  • 你当然可以在你得到的一对迭代器上应用任何standard algorithm
  • 谢谢伊戈尔,所以标准算法的“查找”(根据您提供的链接)只是迭代范围内的元素,所以我不妨坚持迭代标准: :pair 从 boost equal_range 返回。

标签: c++ boost boost-multi-index equal-range


【解决方案1】:

考虑在站点名称和温度上使用复合键(您可以使用该索引单独基于站点名称或在涉及两个键的操作中进行查找)。

【讨论】:

  • 嗨 Joaquin,此查找需要每秒处理 200 次查找。对于 500,000 条记录,我最好坚持使用简单的共享内存映射 并在每次查找时找到确切的测量点,或者继续使用您建议的复合键或非唯一键的多索引路径它检索一个范围值,然后我对其进行迭代以找到确切的测量点。同样作为另一种解决方案,是否可以在共享内存中构建许多映射,例如segment.construct("map1"), segment.construct("map2"), .... (mapN) ?
  • 好吧,我想说您必须进行概要分析才能知道哪个是您的最佳选择。不过,在不到 5 毫秒的时间内查询一个 500 kelement 的容器在我看来并不是非常紧凑(我已经在 Intel Core i5-2520M @2.50GHz 上使用一组 700 个 kints 进行了简单的测试,查询花费了大约 7 us) .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多