保存和恢复内存位置列表的清洁机制



我有一个内存位置列表,我需要作为一个组访问,偶尔单独访问。我想提供一个单一的规范点。目前的设计是混乱的,我想知道是否有人有一个好的(理想的c++)方法来解决这个问题。

我有一个巨大的潜在内存位置列表,每个产品将(在设计时)选择大约100个,或多或少平均分成两组。

在代码的某一点上,我们将所有的内存位置复制到缓冲区,然后偶尔从原始位置和存储缓冲区中读取它们。经过一定的时间长度(和~50,000行代码之后),我们将恢复保存的数据回内存。

当前代码(sort)

我们当前正在做的事情如下:

#define BLOCK_LIST_LOCATIONS1 = 0x1400, 0x1450
#define BLOCK_LIST_LOCATIONS2 = BLOCK_LIST_LOCATIONS1, 0x1000, 0x1002, 0x2040, 0xFFFF
union {
    struct {
        struct {          // Must be kept in sync with BLOCK_LIST_LOCATIONS1
            uint16_t Mem1400;
            uint16_t Mem1450;
        } List1;
        uint16_t Mem1000;       // Must be kept in sync with BLOCK_LIST_LOCATIONS2
        uint16_t Mem1002;
        uint16_t Mem2040;
    } BlockList;
    uint16_t BlockArray[sizeof(BlockList)/sizeof(uint16_t)];
 } MemoryBlock;
uint32_t BASE_PTR = 0x30300000;

// block.cpp
uint16_t BlockMemoryLocationsArray[] = { BLOCK_LIST_LOCATIONS2 };
void SaveAwayMemory() {
    for (int i = 0; BlockMemoryLocationsArray[i] < 0xFFFF; i++) {
       MemoryBlock.BlockArray[i] = *(BASE_PTR + BlockMemoryLocationsArrary[i]);
    }
}
void RestoreFromMemory(bool skipList1) {
    int startingLocation = 0;
    if (skipList1) startingLocation += sizeof(BlockList::List1) / sizeof(uint16_t);
    for (int i = startingLocation; BlockMemoryLocationsArray[i] < 0xFFFF; i++) {
       *(BASE_PTR + BlockMemoryLocationsArrary[i]) = MemoryBlock.BlockArray[i];
    }
}

这带来了许多问题,因为保持多个列表同步是一件痛苦的事情,这里的错误往往是相当严重的内存损坏问题。

一些奇怪的限制:我们没有堆,我们在使用armcc的嵌入式平台上操作。

是否有一个相对干净的替代实现给我

  • 访问每个单独保存的away值
  • 易于批量保存/恢复
  • 只能指定一次位置

高级代码使用

SaveAwayMemory();
// Literally thousands of lines of processing... including things like the following
Write1550(MemoryBlock.BlockList.List1.Mem1450 | 0x0020);
if (Read1000() != MemoryBlock.BlockList.Mem1000) // freak out if this changed
RestoreFromMemory(true);

这是我在餐巾纸背面画的。

template <int ... Values>
struct Bimap;
template <>
struct Bimap<>
{
    static const int Size = 0; 
};
template <int Value0, int ... Values>
struct Bimap<Value0, Values...>
{
    static const int Val = Value0;
    using Next = Bimap<Values...>;
    static const int Size = 1 + Next::Size;
};
template<typename A, int I>
struct Get;
template<typename A>
struct Get<A, 0>
{
    static const int Val = A::Val;
};
template<typename A, int I>
struct Get
{
    static const int Val = Get<typename A::Next, I-1>::Val;
};
template<typename A, int Val>
struct Find;
template<int Value0, int... Values>
struct Find<Bimap<Value0, Values...>, Value0>
{
    static const int Idx = 0;
};
template<int ValueToFind, int Value0, int... Values>
struct Find<Bimap<Value0, Values...>, ValueToFind>
{
    static const int Idx = 1 + Find<Bimap<Values...>, ValueToFind>::Idx;
};

这有什么关系呢?如果你有

using MyLocations = Bimap<0x1000, 0x1100, 0x1400, 0x1500>;
然后

Get<MyLocations, 3>::Val == 0x1500

Find<MyLocations, 0x1500>::Idx = 3

现在可以声明

uint16_t MyBlocks[MyLocations::Size];
使用

MyBlocks[Find<MyLocations, 0x1500>::Idx] = 
  MyBlocks[Find<MyLocations, 0x1400>::Idx] | 0x777;

大致相当于前者

MemoryBlock.BlockList.Mem1500 = MemoryBlock.BlockList.Mem1400 | 0x777;

我希望你能根据你的具体需要调整一下。

我几乎肯定Boost已经有类似的东西了,但是我懒得去找

最新更新