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));
it.goStart;
while (!it.isLast) if (it.moveNext == _lc) return 1;
return 0;
}
Шаг 29 - Единственный экземпляр класса - Одиночка или Singleton.
Как гарантировать единичность экземпляра некоего класса?
Предположим, что Вы проектируете программную систему, в которой некое устройство должно быть исключительно в одном экземпляре. Какие у нас варианты?
1. Создать класс устройства, объявить его экземпляр в специальном файле globals.cpp, и обязать программистов использовать строго его (именно так я делал на заре карьеры; наш шеф под роспись давал нам "Меморандум о писании программ", там много было интересного).
2. Создать класс устройства, объявить в нем устройство статическим членом.
3. Реализовать в классе устройства подсчет экземпляров, ограничить максимальное количество единицей.
4. Создать "закрытый" класс устройства, создать смарт-указатель на него так, чтобы смарт следил за одиночеством класса устройства.
Первый вариант сразу на помойку. Второй более интересен, но есть несколько неприятных проблем, связанных со статическими и глобальными данными. Правила C/C++ не определяют порядок конструирования таких объектов, если они находятся в разных файлах. То есть, у Вас прога уже вовсю дышит, работает - а находятся такие объекты, которые даже еще не инициализировались! Получается, что глобальные и статические объекты не должны рассчитывать друг на друга. С другой стороны, если объявить статический член, его нужно инициализировать - а данные могут быть еще не готовы.
Третий вариант кажется подходящим, но только кажется. Мы получим ошибку создания во время исполнения. Вот радость то, конструируем объект, а он нам исключения выбрасывает, мы об этом уже говорили в Шаге 12.