1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2018 Intel Corporation
#ifndef OPENCV_GAPI_COMPILER_TRANSACTIONS_HPP
#define OPENCV_GAPI_COMPILER_TRANSACTIONS_HPP
#include <algorithm> // find_if
#include <functional>
#include <list>
#include <ade/graph.hpp>
#include "opencv2/gapi/own/assert.hpp"
enum class Direction: int {Invalid, In, Out};
////////////////////////////////////////////////////////////////////////////
////
// TODO: Probably it can be moved to ADE
namespace Change
{
struct Base
{
virtual void commit (ade::Graph & ) {};
virtual void rollback(ade::Graph & ) {};
virtual ~Base() = default;
};
class NodeCreated final: public Base
{
ade::NodeHandle m_node;
public:
explicit NodeCreated(const ade::NodeHandle &nh) : m_node(nh) {}
virtual void rollback(ade::Graph &g) override { g.erase(m_node); }
};
// NB: Drops all metadata stored in the EdgeHandle,
// which is not restored even in the rollback
// FIXME: either add a way for users to preserve meta manually
// or extend ADE to manipulate with meta such way
class DropLink final: public Base
{
ade::NodeHandle m_node;
Direction m_dir;
ade::NodeHandle m_sibling;
public:
DropLink(ade::Graph &g,
const ade::NodeHandle &node,
const ade::EdgeHandle &edge)
: m_node(node), m_dir(node == edge->srcNode()
? Direction::Out
: Direction::In)
{
m_sibling = (m_dir == Direction::In
? edge->srcNode()
: edge->dstNode());
g.erase(edge);
}
virtual void rollback(ade::Graph &g) override
{
switch(m_dir)
{
case Direction::In: g.link(m_sibling, m_node); break;
case Direction::Out: g.link(m_node, m_sibling); break;
default: GAPI_Assert(false);
}
}
};
class NewLink final: public Base
{
ade::EdgeHandle m_edge;
public:
NewLink(ade::Graph &g,
const ade::NodeHandle &prod,
const ade::NodeHandle &cons)
: m_edge(g.link(prod, cons))
{
}
virtual void rollback(ade::Graph &g) override
{
g.erase(m_edge);
}
};
class DropNode final: public Base
{
ade::NodeHandle m_node;
public:
explicit DropNode(const ade::NodeHandle &nh)
: m_node(nh)
{
// According to the semantic, node should be disconnected
// manually before it is dropped
GAPI_Assert(m_node->inEdges().size() == 0);
GAPI_Assert(m_node->outEdges().size() == 0);
}
virtual void commit(ade::Graph &g) override
{
g.erase(m_node);
}
};
class List
{
std::list< std::unique_ptr<Base> > m_changes;
public:
template<typename T, typename ...Args>
void enqueue(Args&&... args)
{
std::unique_ptr<Base> p(new T(args...));
m_changes.push_back(std::move(p));
}
void commit(ade::Graph &g)
{
// Commit changes in the forward order
for (auto& ch : m_changes) ch->commit(g);
}
void rollback(ade::Graph &g)
{
// Rollback changes in the reverse order
for (auto it = m_changes.rbegin(); it != m_changes.rend(); ++it)
{
(*it)->rollback(g);
}
}
};
} // namespace Change
////////////////////////////////////////////////////////////////////////////
#endif // OPENCV_GAPI_COMPILER_TRANSACTIONS_HPP