Подход, который иногда может быть полезен, если нужен метод «сброса», который может вызвать неизвестное количество функций или модулей, состоит в том, чтобы иметь глобальный счетчик для того, сколько раз был вызван этот метод сброса, и затем иметь каждую функцию или модуль включает код как:
extern unsigned long global_reset_count;
void do_something(int whatever)
{
static ... this, that, the other, etc. ...;
static unsigned long my_reset_count;
if (my_reset_count != global_reset_count)
{
my_reset_count = global_reset_count;
... initialize this, that, the other, etc ...
}
}
В некоторых контекстах с многопоточностью, если инициализация статических переменных может зависеть от некоторых глобальных переменных, можно заменить «if» на «while»; в таком случае; в этом случае могут также потребоваться барьеры памяти, хотя точные требования будут варьироваться в зависимости от операционной среды.
Кроме того, альтернативный шаблон, который может быть полезен во встроенных системах, мог бы иметь глобальную переменную modules_initialized
, которая устанавливается равной 0 с помощью метода глобального сброса, а затем каждый модуль должен начинаться с чего-то вроде:
if (!atomic_bit_test_and_set32(&modules_initialized, FOOBOZZ_MODULE_ID))
{
... Initialize module FOOBOZZ ...
}
Это потребует, чтобы не было более 32 идентификаторов модулей, и потребовало бы, чтобы они были как-то уникально распределены, но некоторые системы могут справиться с этим довольно хорошо. Например, компоновщик может позволить определить «секцию данных» из адреса 0-31 адресного пространства, независимого от любого другого; если каждый модуль объявляет однобайтовую переменную в этом адресном пространстве, компоновщик может сгенерировать соответствующие адреса для этих переменных.