Все остальное - дело техники. Сразу поясняю код: класс 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) {