Программист-прагматик. Путь от подмастерья к мастеру

СодержаниеГлава 4 Прагматическая паранойя 25 Балансировка ресурсов Объекты и исключения → Часть 2

Глава 64

Часть 2

void readCustomer(FILE *cFile, Customer *cRec) {

fread(cRec, sizeof(*cRec), 1, cFile);

void writeCustomer(FILE *cFile, Customer *cRec) {

rewind(cFile);

fwrite(cRec, sizeof(*cRec), 1, http://www.oz-sport.ru cFile);

void updateCustomer(const char *fName, double newBalance) {

FILE *cFile;

Customer cRec;

cFile = fopen(fName, "r+"); // -

readCustomer(cFile, cRec); //

if (newBalance = 0. 0) {  //

  cRec. balance = newBalance; //

  writeCustomer(cFile, cRec); //

 Fclose(cFile);   // -

Теперь всю ответственность за файл несет подпрограмма updateCustomer. Она открывает файл и (заканчивая то, что уже начала) закрывает его перед выходом. Подпрограмма осуществляет балансировку использования файла: открытие и закрытие происходят на одном и том же месте, и очевидно, что каждой процедуре открытия будет соответствовать процедура закрытия. Реорганизация также позволяет избавиться от уродливой глобальной переменной.

Базовая схема распределения ресурсов может быть распространена на подпрограммы, которым одновременно необходимо более одного ресурса. Поэтому есть еще два предложения:

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

2.  При распределении одного и того же набора ресурсов в различных местах программы необходимо осуществлять эту операцию в одном и том же порядке. Это уменьшает вероятность взаимоблокировки. (Если процесс А требует resource1 и собирается затребовать resource2, тогда как процесс В затребовал resource2 и пытается заполучить resource1, то два процесса окажутся в состоянии вечного ожидания. )

Неважно, какой тип ресурсов используется,  – транзакции, память, файлы, потоки, окна, к ним применима общая схема: кто бы ни назначал ресурс, он обязан нести ответственность за его освобождение. Однако эта концепция может получить дальнейшее развитие при работе с рядом языков программирования.

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

Если вы программируете на объектно-ориентированном языке, то упаковка ресурсов в классы может принести пользу. Всякий раз, когда вам необходим конкретный тип ресурса, вы создаете экземпляр объекта указанного класса. Если объект выходит из области действия или повторно запрашивается сборщиком мусора, то деструктор объекта освобождает инкапсулированный ресурс.

Этот подход обладает определенными преимуществами при работе с языками программирования типа С++, где исключения могут входить в противоречие с освобождением ресурсов.

Навигация

Hosted by uCoz