Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lucik_op.doc
Скачиваний:
0
Добавлен:
23.12.2019
Размер:
2.88 Mб
Скачать

Классы поддерживающие транзакции

Концепция smart-указателей позволяет просто решать задачу поддержки транзакций.

  • Если транзакция началась, то все изменения в ней либо вносятся вместе, либо не вносятся вообще;

  • если клиент начал и не завершил транзакцию, то другие клиенты не видят его изменений;

  • две транзакции не могут одновременно менять одни и те же данные.

Если требуется закрепить или отменить выполненные изменения, то необходимо хранить состояние объекта на заданный момент - начало транзакции, и в момент принятия решения или уничтожать предыдущее состояние (закрепление) или возвращаться к нему (отмена). Для этого может быть использован smart-указатель. Основой его являются два указателя - один на текущий объект, а второй - на объект, представляющий его предыдущее состояние, и три функции - старт, закрепление, отмена.

#include <iostream.h>

template <class T1>

class Cls

{ T1 x;

public:

Cls() : x(0){}

f(int X) {x=X;}

T1 Show()

{return xl;}

};

// smart-pointer с поддержкой отмены.

template <class T2>

class Tran

{ T2* that; // текущее значение объекта класса Cls

T2* prev; // предыдущее значение объекта класса Cls

public:

Tran():prev(NULL), that(new T2){}; // конструктор

Tran(const Tran & obj): // конструктор копирования

that(new T2(*(obj.that))), prev(NULL) {};

~Tran(){delete that; delete prev;}; // деструктор

Tran& operator=(const Tran & obj); // перегрузка присваивания

void Show(); // отображение значений (предыдущего и

// текущего) объекта класса Cls

void BeginTrans(); // начало транзакции

void Commit(); // закрепление

void DeleteTrans(); // отмена транзакции

T2* operator->(); // реализация указателя

};

template <class T2>

Tran<T2>& Tran<T2>::operator=(const Tran<T2> & obj)

{ if (this != &obj) // проверка на случай obj=obj

{ delete that; // удаление текущего значения объекта

that = new T2(*(obj.that)); // создание и копирование

}

return *this;

}

template <class T2>

T2* Tran<T2>::operator->() {return that;}

template <class T2>

void Tran<T2>::Show()

{ cout<<"состояния объекта"<<endl;

if (prev) cout<<"prev = "<<prev->get()<<endl;

cout<<"that = "<<that->get()<<endl;

}

template <class T2>

void Tran<T2>::BeginTrans()

{ delete prev; // удаление предыдущего значения

prev = that; // текущее становится предыдущим

that = new T2(*prev); // новое значение текущего значения

}

template <class T2>

void Tran<T2>::Commit ()

{ delete prev; // удаление предыдущего значения

prev = NULL; // предыдущего состояния нет

}

template <class T2>

void Tran<T2>::DeleteTrans()

{ if (prev != NULL)

{ delete that; // удаление текущего значения

that = prev; // предыдущее становится текущим

prev = NULL; // предыдущего состояния нет

}

}

int main (void)

{ Tran<Cls<int> > tr;

tr->f(5);

tr.Show();

tr.BeginTrans();

tr.Show();

tr->f(7);

tr.Show();

tr.DeleteTrans();

tr.Show();

tr.BeginTrans();

tr.Show();

tr->f(7);

tr.Commit();

tr.Show();

return 0;

}

Результат работы программы:

состояния объекта

that = 5

состояния объекта

prev = 5

that = 5

состояния объекта

prev = 5

that = 7

состояния объекта

that = 5

состояния объекта

prev = 5

that = 5

состояния объекта

that = 7

Следует отметить, что перегрузка операции присваивания (=) понадобится в случае, например, если описаны два объекта.

Tran<Cls<int> > tr,ts;

. . .

ts=tr; // требуется перегрузка операции =

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]