如何创建,一旦评估当地的静态变量静态方法?
-
21-09-2019 - |
题
我有与具有局部静态变量静态方法的类。我想该变量进行计算/评估一次(一日一次我调用函数)和任何后续调用,它不再被评估。怎么做?这里是我的类:
template<
typename T1 = int, unsigned N1 = 1,
typename T2 = int, unsigned N2 = 0,
typename T3 = int, unsigned N3 = 0,
typename T4 = int, unsigned N4 = 0,
typename T5 = int, unsigned N5 = 0,
typename T6 = int, unsigned N6 = 0,
typename T7 = int, unsigned N7 = 0,
typename T8 = int, unsigned N8 = 0,
typename T9 = int, unsigned N9 = 0,
typename T10 = int, unsigned N10 = 0,
typename T11 = int, unsigned N11 = 0,
typename T12 = int, unsigned N12 = 0,
typename T13 = int, unsigned N13 = 0,
typename T14 = int, unsigned N14 = 0,
typename T15 = int, unsigned N15 = 0,
typename T16 = int, unsigned N16 = 0>
struct GroupAlloc
{
static const uint32_t sizeClass;
static uint32_t getSize()
{
static uint32_t totalSize = 0;
totalSize += sizeof(T1)*N1;
totalSize += sizeof(T2)*N2;
totalSize += sizeof(T3)*N3;
totalSize += sizeof(T4)*N4;
totalSize += sizeof(T5)*N5;
totalSize += sizeof(T6)*N6;
totalSize += sizeof(T7)*N7;
totalSize += sizeof(T8)*N8;
totalSize += sizeof(T9)*N9;
totalSize += sizeof(T10)*N10;
totalSize += sizeof(T11)*N11;
totalSize += sizeof(T12)*N12;
totalSize += sizeof(T13)*N13;
totalSize += sizeof(T14)*N14;
totalSize += sizeof(T15)*N15;
totalSize += sizeof(T16)*N16;
totalSize = 8*((totalSize + 7)/8);
return totalSize;
}
};
编辑:
感谢所有为您及时的帮助。 +1给大家。我选择了泰勒麦克亨利的答案,因为它不需要任何比较,纯静态的功能评价。我需要这个代码分配器所以避免再次“如果”应该会更好。再次感谢!
编辑:
GF的回答竟然是最好的之一,因为它在编译时通过分配交易和保存来自线程安全的头痛和明确的初始化程序。不过,我尊重以前的最佳答案。我将在这里给予信贷,而不是改变刻度线。谢谢大家的帮助!
解决方案
请另一个静态函数,它的计算,并使用该用于可变,e.g的初始化。
static uint32_t computeSize()
{
uint32_t init_totalSize;
// Lots of code
return init_totalSize;
}
static uint32_t getSize()
{
static uint32_t totalSize = computeSize();
return totalSize;
}
保证静态变量被正好一次初始化(第一次被用于包含它们的功能)。
编辑:但是,这是的不的线程安全的。 此页解释了为什么非常详细。
要使它线程安全的,它不足以包裹在临界段totalSize
(调用computeSize
)的初始化,因为静态变量初始化为“编译器魔术”,并且它可以是该变量以经历在通话过程中初始化随时getSize
在使用之前,即使是函数的第一个语句之前。你需要做的是阻止多于一个的线程甚至在同一时间,可以用间接的另一个层面,e.g完成调用getSize
。
static uint32_t computeSize()
{
uint32_t init_totalSize;
// Lots of code
return init_totalSize;
}
static uint32_t real_getSize()
{
static uint32_t totalSize = computeSize();
return totalSize;
}
static uint32_t getSize()
{
uint32_t totalSize;
/* --- Enter Critical Section (acquire lock) -- */
totalSize = real_getSize();
/* --- Exit Critical Section (release lock) -- */
return totalSize;
}
此防止两个线程甚至在进入包含在同一时间的静态变量的函数,并确保其初始化将临界段内发生。
其他提示
移动计算插入到辅助函数:
static uint32_t totalSize = calculateTotalSize();
在辅助函数将当totalSize
被初始化仅调用。
有一个有点晚了,但是为什么你在这里做一个(潜在的)运行时计算呢?使用编译时间常数,你可从来没有任何线程问题:
template<
typename T1, unsigned N1,
typename T2, unsigned N2,
/* ... */
>
struct totalSize {
static const uint32_t sum =
sizeof(T1)*N1
+ sizeof(T2)*N2
/* ... */
;
static const uint32_t value =
8*((sum + 7)/8);
};
uint32_t GroupAlloc::getSize() {
return totalSize<T1,N1,T2,N2,/*...*/>::value;
}
是这样的:
static uint32_t getSize()
{
static uint32_t totalSize = 0;
static bool computed = 0;
if(computed)
return totalSize;
computed = 1;
// ... go on with your computation
会做的伎俩。请注意,这不是线程安全的。
static uint32_t totalSize = 0; // initialisation performed once only
if ( totalSize == 0 ) {
totalSize += sizeof(T1)*N1;
totalSize += sizeof(T2)*N2;
totalSize += sizeof(T3)*N3;
totalSize += sizeof(T4)*N4;
// etc
}
不隶属于 StackOverflow