Транзакции и блокировки
В действительности транзакция представляет собой нечто иное, чем коллекцию указателей образов, в которой имеется несколько функций для перебора. Одна из трудностей состоит в том, что одна транзакция может обновлять любое число объектов, относящихся к различным типам. Следовательно, класс транзакции должен быть расписан так, чтобы он мог работать с любыми типами - похоже, речь идет об абстрактном базовом классе.
// В файле Transaction.h
class Lock {
friend class Transaction;
protected:
Transaction* transaction; // Транзакция, которой принадлежит this
Lock() : transaction(NULL) {}
void RegisterLock(Transaction* t)
{
if (transaction != NULL) {
// Конфликт - уже имеется другой владелец
cerr << "Lock::RegisterLock - already locked" << endl;
}
else {
t->AddLock(this);
transaction = t;
}
}
virtual ~Lock() {}
virtual void Rollback() = 0;
virtual void Commit() = 0;
};
class Transaction {
friend class Lock; // Чтобы предоставить доступ к AddLock()
private:
SafeSet<Lock>* locks;
void AddLock(Lock*); // Включить блокировку в транзакцию
public:
~Transaction();
void Commit(); // Закрепить все образы
void Rollback(); // Отменить все образы
bool OwnsLock(Lock*); // Истина, если блокировка
// принадлежит транзакции
};
Класс Transaction поддерживает коллекцию блокировок с помощью гипотетического шаблона
Collection. Функция RegisterLock() включена в базовый класс Lock и потому может обратиться к
закрытой функции AddLock() класса Transaction. Дружба не наследуется, поэтому объявление
другом класса Lock не делает друзьями его производные классы. Реализации выглядят довольно просто.
void Transaction::AddLock(Lock* lock)
{
*locks += lock; // Использует перегрузку += для коллекции
}
void Transaction::Commit()
{
SafeSetIterator<Lock>* iter = locks->Iterator();
while (iter->More())
iter->Next()->Commit();
delete iter;
}
void Transaction::Rollback()
{
SafeSetIterator<Lock>* iter = locks->Iterator();
while (iter->More())
iter->Next()->Rollback();
delete iter;
}
bool Transaction::OwnsLock(Lock* lock)
{
return *locks >= lock;
}
Предполагается, что шаблон Collection содержит функцию DeleteAll() для удаления всех
объектов; что перегруженный оператор += (операторная функция operator+=(Type*)) включает
элемент в коллекцию; что перегруженный оператор >= определяет принадлежность к коллекции, а функция Iterator() возвращает вложенный итератор. Это обобщенные условия; используйте те, которые действуют в вашем случае.