Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Многопоточное програмирование.doc
Скачиваний:
3
Добавлен:
14.11.2019
Размер:
332.8 Кб
Скачать

4.4. Mtcnvsrc.Exe: конвертация исходного кода

Программа предназначена для рекурсивной конвертации файлов исходного кода в DOS/UNIX формат и/или удаления пробелов в конце строки.

Параметры командной строки: mtcnvsrc [-nt2] [d|u][e] mask[,mask2...]

[-ntN]

количество потоков, 2 по умолчанию

[d]

конвертировать в DOS формат

[e]

удалять пробелы в конце строки

[u]

конвертировать в UNIX формат

mask[,mask2...]

маски для поиска файлов, могут содержать * и ? символы

Примеры использования: mtcnvsrc.exe ue *.h,*.hpp,*.c,*.cpp mtcnvsrc.exe -nt4 e *.?pp

Как можно видеть, прямым назначением программы является исправление ошибок, найденных mtcksrc. При этом, автоматически исправляется только то, что не требует человеческого вмешательства.

Ну а если говорить о сложности, то данная программа скорее является небольшим подготовительным этапом перед следующей, чем усложнением предыдущей. Единственный момент, на который можно обратить внимание -- это аргумент потока в виде более общей структуры Arg. На этот раз аргументы хранятся в векторе vector<sh_ptr<Arg> >, но это не приводит к описанным выше проблемам, т.к. в процессе их создания копируются и перераспределяются элементы sh_ptr<Arg>, а не сами тяжеловесные Arg структуры.

4.5. Mtdirdiff.Exe: сравнение директорий

Программа предназначена для рекурсивного сравнения директорий.

Параметры командной строки: mtdirdiff [-nt2] old_dir new_dir diff_dir

[-ntN]

количество потоков, 2 по умолчанию

old_dir

директория со старыми файлами

new_dir

директория с новыми файлами

diff_dir

директория для копирования изменений в виде add, del и mod поддиректорий

Примеры использования: mtdirdiff.exe src\mtprog.sav src\mtprog src\mtprog.diff

А здесь мы уже имеем дело с небольшой, но достаточно нетривиальной многопоточной программой, в процессе создания которой решалось несколько неочевидных задач проектирования.

  1. Прежде всего отмечу, что это первая программа, многопоточная работа которой разбита на несколько этапов, т.е. функция thread_pool::exec() вызывается неоднократно:

  2. sh_thread_pool tp=(clp.numThr>1) ? new_thread_pool(mp, clp.numThr-1) :

  3. new_thread_pool(mp);

  4. MainTask mt(clp.oldDir, clp.newDir, clp.diffDir);

  5. sh_data_queue dq=new_data_queue(mp);

  6. dq_vec dqv(1, dq.get());

  7. MsgIO mio(mp, *dq);

  8. {

  9. FindFilesMsg m1(&mt.oldDir), m2(&mt.newDir);

  10. mio.write(m1);

  11. mio.write(m2);

  12. }

  13. tp->exec(mt, dqv);

  14. {

  15. CompareMsg m1(true), m2(false);

  16. mio.write(m1);

  17. mio.write(m2);

  18. }

  19. mt.argno=0;

tp->exec(mt, dqv);

И, как следствие, устройство функции proc_arg() немного усложнено:

void* MainTask::proc_arg()

{

assert(argno<=int(args.size()));

if (argno==int(args.size())) args.push_back(newArg(gmp));

return args[argno++].get();

}

Необходимость разбиения на этапы возникает из желания эффективным и естественным образом организовать сканирование и последующее сравнение old_dir и new_dir директорий:

    1. Сначала не более двух рабочих потоков производят поиск файлов и директорий с занесением результатов в объекты mt.oldDir и mt.newDir соответственно. Дополнительное количество потоков не используется в силу того, что заведение отдельных объектов DirCont для каждого из них с последующим объединением содержимого заметно усложнит структуру программы, вряд ли существенно ускорив ее выполнение.

Кстати сказать, проверка данной гипотезы является неплохим упражнением для самостоятельного изучения MT программирования -- возьметесь?! Вот и мне тоже лень...

    1. Затем стартует сравнение просканированных директорий, причем потокам не нужно синхронизировать свой доступ к hash_vec-рам с именам, т.к. их содержимое уже никем не изменяется.

Как можно видеть, без разбиения на этапы потокам пришлось бы синхронизировать свой доступ к hash_vec-рам, что неприемлемо с точки зрения правильного MT дизайна.