[devel] Q: AptPkg.pm и два репозитария

Sergei Epiphanov serpiph на nikiet.ru
Пт Янв 21 15:16:57 UTC 2011


В сообщении от 21 января 2011 17:33:03 автор Paul Wolneykien написал:
>   Большое спасибо, Сергей. Я сейчас пытаюсь сделать и так и этак,
> посмотрим, что получится. Однако пока я не уверен в том, что
> переназначение глобальной переменной это хорошая идея:

При помощи local переменная лишь временно подменяется (на момент выполнения 
функции).
 
>   1. я точно не знаю, как правильно создать новый экземпляр конфигурации
> и как правильно его проинициализировать; и по идее не должен этого
> знать, т.к. это внутренние «потроха» модуля; в документации написано,
> что если просто загрузить модуль через use, то $_config будет
> проинициализирована автоматически; хотелось бы использовать этот
> механизм автонастройки для каждого экземпляра модуля;

А что мешает при инициализации своего модуля скопировать (deep copy) текущее 
значение $_config (которое к этому времени уже будет проинициализировано)?

>   2. что будет в многопоточной программе? я же не знаю, кто ещё
> использует этот самый $Module::_config ? паранойя, кончено, т.к. у меня
> нет параллельных сегментов программы, но хотелось бы иметь решение,
> которое давало бы надёжную изоляцию.

Вот здесь уже сложнее, надо изучать. Но другие подмены мне неизвестны, так как 
все описания хранятся в общем хеше (равно как и описание модуля). И для 
временных подмен значений разработчики перла советуют именно local. Тем более, 
что local - это лексическая подмена, то есть на момент выполнения этого куска 
программы. Можно в допмодуле организовать семафоры или мьютексы, тем самым не 
допуская параллельных вызовов основного модуля.

Оптимальное решение, но трудоёмкое: самому переписать модуль так, чтобы он не 
имел ссылок на глобальные переменные (создав контекст вызова). В своё время я 
на своей работе при написании интерфейсного модуля на перл уходил от 
глобальных переменных, но там пришлось переписать ещё библиотеки, которые тупо 
лезли в глобальные переменные, благо были исходники. А проверить ссылки на 
$Module::_config достаточно внутри самого модуля: маловероятно, что кто-то ещё 
будет ковырять внутренности.

Можно как-то так:

package Module;

$_config="0";

sub printc(){
    print "config=$_config";
    return;
}

1;
package Module1;
use Module;

sub AUTOLOAD{
    {
#lock mutex here
        local $Module::_config = $_[0];
        my $program = $AUTOLOAD;
        $program =~ s/.*:://;
        @l = &{"Module::$program"}(@_[1..$#_]);
        $_[0] = $Module::_config;
#release mutex here
    }
    return @l;
}

1;
package MAIN;
use Module1;

$cnf="2";
Module1::printc($cnf);

С этим уже можно пробовать делать неограниченное количество контекстов.

-- 
С уважением, Епифанов Сергей


Подробная информация о списке рассылки Devel