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