Click here to Skip to main content
15,888,984 members
Articles / Programming Languages / C++

Undo and Redo the "Easy" Way

Rate me:
Please Sign up or sign in to vote.
4.95/5 (42 votes)
20 Jun 2004CPOL22 min read 290K   8.6K   114  
This article introduces a simple approach to in-memory transactions that can be used to implement Undo and Redo. The technique uses SEH and Virtual Memory and requires only STL and Win32.
#ifndef MEM_MANAGER_H_INCLUDED
#define MEM_MANAGER_H_INCLUDED

#include "Utilities\Result.h"

namespace Mm
{
	// types
	typedef unsigned long TXNID;
	typedef unsigned long SPACEID;

	// setup
	bool InstallExceptionFilter();
	bool RemoveExceptionFilter();
	int ExceptionFilter(void* e);

	// space (heap) managment
	Result	InitSpaceZero(); // read the documentation

	SPACEID CreateSpace(size_t initial_size);
	Result	Destroy(SPACEID sid);
	Result 	Clear(SPACEID sid);

	Result ClearAll();

	// transactions
	Result OpenTransaction(SPACEID sid);
	Result CancelTransaction(SPACEID sid);
	Result CommitTransaction(SPACEID sid);

	TXNID  GetLastTransactionId(SPACEID sid);
	TXNID  GetNextTransactionId(SPACEID sid);
	TXNID  GetOpenTransactionId(SPACEID sid);

	Result Undo(SPACEID sid);
	Result Redo(SPACEID sid);

	Result TruncateUndo(SPACEID sid);
	Result TruncateRedo(SPACEID sid);

	// allocation
	void* Allocate(size_t size, SPACEID sid);
	void* Allocate(void* hint, size_t size); // does space lookup, slower, used by Mm::Allocator
	
	void  Deallocate(void* p); // does space lookup, slower
	void  Deallocate(void* p, SPACEID sid);
	void  Deallocate(void* p, size_t size); // used by Mm::Allocator
	
	void* Reallocate(void* p, size_t size); // don't pass null p
	void* Reallocate(void* p, size_t size, SPACEID sid); // null p pkay

	// debug
	size_t FreeSpace(SPACEID sid);
	size_t FreeCount(SPACEID sid);

//	void DumpStats(std::ostream& o);

	class AutoTransaction {
	private:
		AutoTransaction(const AutoTransaction& );
		operator=(const AutoTransaction&);

	public:
		AutoTransaction(SPACEID s) : sid(s), txnid(NULL), cancel(false) 
		{ 
			if (Mm::GetOpenTransactionId(sid) == NULL && !Mm::OpenTransaction(sid).IsError()) 
				txnid = Mm::GetOpenTransactionId(sid); 
		}
		
		~AutoTransaction()
		{
			if (txnid == NULL) return;
			if (txnid != Mm::GetOpenTransactionId(sid)) throw;

			if (cancel) Mm::CancelTransaction(sid);
			else Mm::CommitTransaction(sid);
		}

		Mm::SPACEID sid;
		Mm::TXNID txnid;
		bool cancel;
	};
};

#endif //

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
A compiler warns of bogasity, ignore it at your peril. Unless you've done the compiler's job yourself, don't criticize it.

Comments and Discussions