xref: /haiku/src/apps/haikudepot/process/AbstractProcessNode.cpp (revision b8a45b3a2df2379b4301bf3bd5949b9a105be4ba)
1 /*
2  * Copyright 2021-2022, Andrew Lindesay <apl@lindesay.co.nz>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "AbstractProcessNode.h"
8 
9 #include <unistd.h>
10 
11 #include "AbstractProcess.h"
12 #include "Logger.h"
13 
14 
15 #define SPIN_DELAY_MI 500 * 1000
16 	// half of a second
17 
18 #define TIMEOUT_UNTIL_STARTED_SECS 10
19 #define TIMEOUT_UNTIL_STOPPED_SECS 10
20 
21 
22 AbstractProcessNode::AbstractProcessNode(AbstractProcess* process)
23 	:
24 	fLock(),
25 	fListener(NULL),
26 	fProcess(process)
27 {
28 }
29 
30 
31 AbstractProcessNode::~AbstractProcessNode()
32 {
33 	delete fProcess;
34 }
35 
36 
37 AbstractProcess*
38 AbstractProcessNode::Process() const
39 {
40 	return fProcess;
41 }
42 
43 
44 bool
45 AbstractProcessNode::IsRunning()
46 {
47 	return Process()->ProcessState() == PROCESS_RUNNING;
48 }
49 
50 
51 void
52 AbstractProcessNode::SetListener(ProcessListener* listener)
53 {
54 	if (fListener != listener) {
55 		AutoLocker<BLocker> locker(&fLock);
56 		fListener = listener;
57 	}
58 }
59 
60 
61 /*! This method will spin-lock the thread until the process is in one of the
62     states defined by the mask.
63  */
64 
65 status_t
66 AbstractProcessNode::_SpinUntilProcessState(
67 	uint32 desiredStatesMask, int32 timeoutSeconds)
68 {
69 	bigtime_t start = system_time();
70 	while (true) {
71 		if ((Process()->ProcessState() & desiredStatesMask) != 0)
72 			return B_OK;
73 
74 		usleep(SPIN_DELAY_MI);
75 
76 		int32 secondElapsed = static_cast<int32>(
77 			(system_time() - start) / (1000 * 1000));
78 
79 		if (timeoutSeconds > 0 && secondElapsed > timeoutSeconds) {
80 			HDERROR("[Node<%s>] timeout waiting for process state after %"
81 				B_PRIi32 " seconds", Process()->Name(), secondElapsed);
82 			return B_ERROR;
83 		}
84 	}
85 }
86 
87 
88 void
89 AbstractProcessNode::AddPredecessor(AbstractProcessNode *node)
90 {
91 	fPredecessorNodes.AddItem(node);
92 	node->_AddSuccessor(this);
93 }
94 
95 
96 int32
97 AbstractProcessNode::CountPredecessors() const
98 {
99 	return fPredecessorNodes.CountItems();
100 }
101 
102 
103 AbstractProcessNode*
104 AbstractProcessNode::PredecessorAt(int32 index) const
105 {
106 	return fPredecessorNodes.ItemAt(index);
107 }
108 
109 
110 bool
111 AbstractProcessNode::AllPredecessorsComplete() const
112 {
113 	for (int32 i = 0; i < CountPredecessors(); i++) {
114 		if (PredecessorAt(i)->Process()->ProcessState() != PROCESS_COMPLETE)
115 			return false;
116 	}
117 
118 	return true;
119 }
120 
121 
122 void
123 AbstractProcessNode::_AddSuccessor(AbstractProcessNode* node)
124 {
125 	fSuccessorNodes.AddItem(node);
126 }
127 
128 
129 int32
130 AbstractProcessNode::CountSuccessors() const
131 {
132 	return fSuccessorNodes.CountItems();
133 }
134 
135 
136 AbstractProcessNode*
137 AbstractProcessNode::SuccessorAt(int32 index) const
138 {
139 	return fSuccessorNodes.ItemAt(index);
140 }
141 
142 
143 BString
144 AbstractProcessNode::LogReport()
145 {
146 	return Process()->LogReport();
147 }