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