xref: /haiku/src/apps/haikudepot/process/ProcessCoordinator.h (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
1 /*
2  * Copyright 2018-2022, Andrew Lindesay <apl@lindesay.co.nz>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 #ifndef PROCESS_COORDINATOR_H
6 #define PROCESS_COORDINATOR_H
7 
8 #include "ProcessCoordinator.h"
9 
10 #include <ObjectList.h>
11 
12 #include "AbstractProcess.h"
13 #include "AbstractProcessNode.h"
14 #include "ProcessListener.h"
15 
16 
17 class ProcessCoordinator;
18 
19 
20 /*! This class carries the state of the current process coordinator so that
21     it can be dealt with atomically without having call back to the coordinator.
22 */
23 
24 class ProcessCoordinatorState : public BArchivable {
25 public:
26 								ProcessCoordinatorState(BMessage* from);
27 								ProcessCoordinatorState(
28 									const ProcessCoordinator*
29 										processCoordinator,
30 									float progress, const BString& message,
31 									bool isRunning, status_t errorStatus);
32 	virtual						~ProcessCoordinatorState();
33 
34 	const	BString				ProcessCoordinatorIdentifier() const;
35 			float				Progress() const;
36 			BString				Message() const;
37 			bool				IsRunning() const;
38 			status_t			ErrorStatus() const;
39 
40 			status_t			Archive(BMessage* into, bool deep = true) const;
41 private:
42 			BString				fProcessCoordinatorIdentifier;
43 			float				fProgress;
44 			BString				fMessage;
45 			bool				fIsRunning;
46 			status_t			fErrorStatus;
47 };
48 
49 
50 /*! Clients are able to subclass from this 'interface' in order to accept
51     call-backs when a coordinator has exited; either through failure,
52     stopping or completion.
53 */
54 
55 class ProcessCoordinatorListener {
56 public:
57 
58 /*! Signals to the listener that the coordinator has changed in some way -
59 	for example, a process has started or stopped or even that the whole
60 	coordinator has finished.
61 */
62 
63 	virtual void				CoordinatorChanged(
64 									ProcessCoordinatorState&
65 									processCoordinatorState) = 0;
66 
67 };
68 
69 
70 /*!	Classes implementing this 'interface' are able to consume process
71 	coordinators.  This may be in order to run them.
72 */
73 
74 class ProcessCoordinatorConsumer {
75 public:
76 	virtual	void				Consume(ProcessCoordinator *item) = 0;
77 };
78 
79 
80 /*! It is possible to create a number of ProcessNodes (themselves associated
81     with AbstractProcess-s) that may have dependencies (predecessors and
82     successors) and then an instance of this class is able to coordinate the
83     list of ProcessNode-s so that they are all completed in the correct order.
84 */
85 
86 class ProcessCoordinator : public ProcessListener {
87 public:
88 								ProcessCoordinator(
89 									const char* name,
90 									BMessage* message = NULL);
91 	virtual						~ProcessCoordinator();
92 
93 	const	BString&			Identifier() const;
94 
95 			void				SetListener(
96 									ProcessCoordinatorListener *listener);
97 
98 			void				AddNode(AbstractProcessNode* nodes);
99 
100 			void				ProcessChanged();
101 				// ProcessListener
102 
103 			bool				IsRunning();
104 
105 			void				Start();
106 			void				RequestStop();
107 
108 			status_t			ErrorStatus();
109 
110 			float				Progress();
111 
112 			BString				LogReport();
113 
114 	const	BString&			Name() const;
115 			BMessage*			Message() const;
116 
117 private:
118 			void				_CoordinateAndCallListener();
119 			ProcessCoordinatorState
120 								_Coordinate();
121 			ProcessCoordinatorState
122 								_CreateStatus();
123 			BString				_CreateStatusMessage();
124 			int32				_CountNodesCompleted();
125 			void				_StopSuccessorNodesToErroredOrStoppedNodes();
126 			void				_StopSuccessorNodes(AbstractProcessNode* node);
127 
128 private:
129 			BString				fName;
130 			BLocker				fLock;
131 			bool				fCoordinateAndCallListenerRerun;
132 			BLocker				fCoordinateAndCallListenerRerunLock;
133 			BObjectList<AbstractProcessNode>
134 								fNodes;
135 			ProcessCoordinatorListener*
136 								fListener;
137 			BMessage*			fMessage;
138 			bool				fWasStopped;
139 			BString				fIdentifier;
140 };
141 
142 
143 #endif // PROCESS_COORDINATOR_H
144