我有一个内存位置列表,我需要作为一个组访问,偶尔单独访问。我想提供一个单一的规范点。目前的设计是混乱的,我想知道是否有人有一个好的(理想的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已经有类似的东西了,但是我懒得去找