A simple(incomplete) undo system.

I'm curious about the overhead. The idea is to wrap any system changes using the Add function. This function stores both the forward and backward state changes using delegates.

By using forward, we call the action passed to set the data and backward will call the action to set the original data.

Delegates are used to avoid having to save the actual data manually, but I'm wondering if there is a lot of overhead and how the GC will be trashed by this, is there a better way or a better mechanism to use?



module undo;
import std.variant;


auto apply(T)(T t, Variant[] values) {
    import std.traits : ParameterTypeTuple;
    import std.conv : emplace;
    alias Types = ParameterTypeTuple!T;
    assert(values.length == Types.length);
    Types args = void;
foreach(i, ref arg; args) { emplace!(typeof(arg))(&arg, values[i].get!typeof(arg))); }

        return { t(args); };
}

class Undo
{
        UndoNode Root;
        UndoNode CurrentNode;


        void Add(T, S, A...)(T t, S s, A a)
        {
                pragma(msg, T, " ------ ", S);
                pragma(msg, A);


                UndoNode n = new UndoNode();
                n.Parent = CurrentNode;
                if (CurrentNode !is null)
                        n.ParentBranch = CurrentNode.ParentBranch;
                foreach(_; a)
                        n.Action.Data ~= Variant(_);
                if (CurrentNode !is null)
                        CurrentNode.Children ~= n;
                CurrentNode = n;

                //t();          
                n.Action.cmd = { t(); };
                n.Action.inv = apply!S(s, n.Action.Data);

        }

        void Forward()
        {       
                CurrentNode.Action.cmd();
        }

        void Backward()
        {               
                CurrentNode.Action.inv();
        }       

        this()
        {
                CurrentNode = Root;
        }
}

struct UndoAction
{
        Variant[] Data;
        void delegate() cmd;
        void delegate() inv;
}


class UndoNode
{
        UndoNode Parent;
        UndoNode ParentBranch;
        UndoNode[] Children;
        UndoAction Action;
}




test code


import std.stdio;
import mUndo;


class Data
{
        int x = 0;
}






__gshared Undo GlobalUndo = new Undo();

int main(string[] argv)
{

        __gshared Data data = new Data();
        data.x = -1;
        auto globalUndo = GlobalUndo;


        globalUndo.Add(
                                   {
                                        auto oldx = data.x;
                                        data.x = 4;
                                        return oldx;
                                   },
                                   (int d){
                                        auto oldx = data.x;
                                        data.x = d;
                                        return oldx;
                                   }, data.x);

        writeln(data.x);
        globalUndo.Forward();
        writeln(data.x);
        globalUndo.Backward();
        writeln(data.x);

    writeln("------");
        getchar();
    return 0;
}


  • Undo? Mr. Jonse via Digitalmars-d-learn
    • Re: Undo? Mr. Jonse via Digitalmars-d-learn
      • Re: Undo? Jesse Phillips via Digitalmars-d-learn
    • Re: Undo? bitwise via Digitalmars-d-learn

Reply via email to