oneTBB
oneTBB copied to clipboard
How to reset a graph like if it was constructed for the first time
Suppose I am doing something like:
class graph_manager
{
graph_manager() = default;
public:
static tbb::task_group_context& context()
{
static tbb::task_group_context ctx;
return ctx;
};
static tbb::flow::graph& g()
{
static tbb::flow::graph grph(context());
return grph;
};
static void reset_graph()
{
};
};
This is kind of Singleton pattern. The goal is that the reset_graph function, to really reset everything, meaning construct a new graph with a new context, something like (which is not possible because graph nor the context can not be assigned/moved):
static void reset_graph()
{
tbb::task_group_context& ct = context();
tbb::flow::graph& gh = g();
ct = tbb::task_group_context();
gh = tbb::flow::graph();
};
Could you please help? (I can do this with pointers? I would prefer references, but if you any solution please that would be welcomed).
@Veronizlada,
I would recommend you to consider using graph::reset function. It also calls reset() method on the graph context.
You can pass one or several reset_flags to this member function to customize the reset.
Please find more information here and here.
Please also let us know if this approach is not applicable for your use case.
@kboyarinov
Thanks very much, but reading the descriptions, they don't clearly state that the graph nor the context will go back to there initial state, meaning construction state i.e. no nodes no edges no predefined or copied bodies. I really need to go bac to the initial state of the graph and the context. If this helps I give my specific case: User will be constructing the graph, and then they might decide to start a new session, hence I want my graph/context to be in there initial state, otherwise it will be a mess if they construct new nodes on top of old nodes. Could you please confirm if the function graph::reset will achieve this with one of the flags i.e. graph and context in there initial state. Thans very much.
@Veronizlada
Could you please explain in more details, what do you mean with "start a new session"? As I see in your example, the graph_manager class owns the graph and task_group_context objects, but who owns the nodes? I am asking because the all of the nodes are constructed with the graph arguments and holds the reference to this object and the graph::reset() method does not discard that reference. It means that graph::reset() method can reset the body of each node (rf_reset_bodies) and clear edges of the graph (rf_clear_edges). But in terms of the nodes, they will refer to the previous graph until the destruction.
As for the graph context, it is not mentioned in the spec, but I see it in the codebase that task_group_context::reset() method is called regardless of the passed reset_flags. I think we can consider adding this information in the documentation.
@kboyarinov I see what you mean and I thought about it, the nodes will be destroyed when the session ends. A session is an instance giving the user the possibiliy to add nodes based on some spec. The user does not own the nodes, I do, hence I manage them.
Now the user will be constructing the graph by adding some specs (details about the nodes), the user can also make edges too using labels (std::string), but this is just implementatoin details. The idea is there is a session as defined above, I own the nodes and I own the graph, now the user might one to clean the mess he/she did and wants to:
- Remove all the nodes from the graph (having the exact graph they have in when the session started).
- The nodes, I will delete them first once the user wants to reset (so we won't end up with nodes refering to deleted graph).
So my question is about 1, I just want my graph to go to its initial state. I can solve this by using a pointer and I can just deleted the old graph and construct a new one, I was just thinking if there a more cleaner way without hacking by going through a pointer.
Thanks very much!
@Veronizlada, in this case I think you can just call the reset() without arguments after destroying all of the nodes in the end of the session. Current implementation of graph class holds the pointer to the task_group_context instance, pointer to task_arena, the list of node pointers and some other misc stuff. If all of the nodes are destroyed, the stored node list is empty and the call to graph::reset() resets the context and re-initializes the arena. So you can use the same static graph object for the next session with different nodes and edges.
Please correct me if this solution does not work for you.
@kboyarinov Thanks very much. "If all of the nodes are destroyed, the stored node list is empty" [btw, destroyed I mean here deleting them as my starting point are pointer to nodes, and I dereference them to get the node itself and play with them around], not sure how this works but I will take your word for it :) The list of the nodes I beleive will be a list of nullptrs? I Will do some digging to understand the details as clearly I don't know how everything works other than the interface (the latter is very intuitive, but in some cases like these, I am not sure :) ). If I understand correctly: When constructing a node with a graph, two things happen: a. The node itself as an instance will hold a reference to the graph. b. The node reference will be added to a list of nodes in the graph -> hence in the task_group_context hence in the task_arena.
I likely misunderstood as this design is impossible, as you can't destroy the node (the graph) without having problems with the graph (the node) as they are holding each other reference. I am 100% wrong somewhere.
@Veronizlada When I said that graph itself owns the list of the nodes, I mean that it holds the list of pointers to nodes that is organized in the list. Each node holds a reference to the graph. Hence, you can have a graph without actually having any nodes associated with this graph. When the node is created, the graph argument is necessarily provided as an argument - the node will hold this reference until the destruction. When the node is created, the pointer to it is added to the graph list, when the destruction happens - it would be removed from that list. So you can have the graph without having the nodes, but you cannot have nodes without the graph.
The fact that the node belongs to the graph means that any tasks generated by this node will be proceeded using the task_arena and task_group_context associated with the graph.
If I understood your design correctly, you want to have graph and task_group_context to be created once and then used for each user requested sessions. Nodes for the graph are created in the beginning on the session and destroying at the end of it. Am I correct?
If so, you can just create the node for the user requested session, associate it with the statically created graph and then just reset the graph after the session ends. Also, is it implied that the user may have several opened sessions simultaneously?
If I understood some of your design aspects wrong, please correct me:)
@kboyarinov Yes, my design is as what you desribed. Thanks very much!! I think I got my answer.
About: "Also, is it implied that the user may have several opened sessions simultaneously?" For now, NO but I would like to have this at some point however I think it's too much at this stage! I beleive if I do this, I won't be using static at all, which I am thinking about since now.
Thanks very much again!!
@Veronizlada, happy to hear that:) I will close this issue for now. If you have any further questions, feel free to re-open this issue or create an other one. Thank you very much!
OK! Thanks very much :)