Все остальное - дело техники. Сразу поясняю код: класс CLockable (базовый) содержит указатель на транзакцию, к которой принадлежит в данный момент, а так же чистые виртуальные функции rollback и commit, назначение которых очевидно. Класс CTransaction представляет собой транзакцию, и содержит в себе список задействованных объектов - затем чтобы роллбачить или коммитить их все вместе, да чтоб на ходу можно проверить - принадлежит ли объект некоей транзакции или нет. Функция addLock() добавляет объект к транзакции, то есть распространяет свое действие на него, тем самым блокируя изменения со стороны других клиентов. После использования объекты автоматически разрегистрируются.
Хочу еще раз напомнить о принципе, который в этом Шаге формулируется первый раз: если существует определенная, законченная логика взаимодействия объектов или систем - она выносится на отдельный уровень. Поддержка транзакций очевидно является законченной бизнес-логикой, и, следовательно, должна быть вынесена на специальный уровень. Пусть классы реализуют свою функциональность, не заботясь о свопе, многозадачности-поточности, транзакциях, доступе, приоритетах, авторизациях, синхронизации, сборке мусора (garbage collection) или уплотнении памяти - это не его проблемы. Это - другие уровни, которыми занимаются другие классы, или даже системы. В современном компьютерном мире этот принцип сегодня доминирует, именно на него работают новомодные COM+ с MTS, IBM-websphera, JavaBeans, и множество иных. То, что грамотная корпоративная система должна работать в минимум четырех уровнях, уже является прописной истиной: данные, бизнес-логика сервера, бизнес-логика клиента, клиент.
Понимаете теперь, в чем преимущество смарт-указателей? Они позволяют с легкостью создавать новые уровни бизнес-логик без привлечения дополнительных средств и схем, а едиными только средствами языка. Попробуйте сделать что-либо подобное на языке, который не поддерживает указателей и перегрузки операторов (да шаблоны еще)! Вот код.
>#include "ampstack.h"
>// Абстрактный базовый класс
>class CLockable {
> friend class CTransaction;
>protected:
> // текущая транзакция, если есть
> CTransaction* m_trans;
>public:
> CLockable (): m_trans (NULL) {}
> // регистрируемся в какой-то транзакции
> int regObj (CTransaction* _pt);
> // и разрегистрируемся
> void unregObj();
> virtual ~CLockable() {}
> virtual void rollback () =0;
> virtual void commit() =0;
>};
>// Класс транзакции
>class CTransaction {
> friend class CLockable;
>private:
> // коллекция зарегистрированных объектов
> ampstack‹CLockable› m_locks;
> // добавить объект к транзакции
> void addLock (CLockable*);
>public:
> virtual ~CTransaction ();
>// закрепить или отменить все изменения во всех
>// зарегистрированных объектах.
> void commit();
> void rollback();
>// проверить, зарегистрирован ли объект в этой транзакции
> int allready_locked(CLockable*);
>};
>// зарегистрироваться в транзакции
>inline int CLockable::regObj (CTransaction* _pt) {
> if (m_trans!= NULL) return 0;
> else {
> _pt-›addLock(this);
> m_trans = _pt;
> return 1;
> }
>}
>// разрегистрироваться
>inline void CLockable::unregObj() {
> m_trans = NULL;
>}
>// добавление объекта к транзакции.
>inline void CTransaction::addLock(CLockable* _lc) {
> // а именно, воткнуть указатель на него в стек.
> m_locks.push (_lc);
>}
>// закрепление всех объектов
>void CTransaction::commit() {
> // создаем итератор
> ampIter‹CLockable› it(&(this-›m_locks));
> // пробежались по всем, закрепились.
> it.goStart();
> while (!it.isLast()) it.moveNext()-›commit();
> // Всех выкинуть из стека, разрегистрировать.
> while (!m_locks.isEmpty()) m_locks.pop()-›unregObj();
>}
>// отмена всех объектов
>void CTransaction::rollback() {
> // создали итератор
> ampIter‹CLockable› it(&(this-›m_locks));
> // пробежались по всем, отменились.
> it.goStart();
> while (!it.isLast()) it.moveNext()-›rollback();
> // Всех выкинуть из коллекции и разрегистрировать
> while (!m_locks.isEmpty()) m_locks.pop()-›unregObj();
>}
>// проверка, зарегистрирован ли объект.
>int CTransaction::allready_locked(CLockable* _lc) {
> // создали итератор
> ampIter‹CLockable› it(&(this-›m_locks));