xref: /haiku/src/apps/haikudepot/process/AbstractProcess.cpp (revision d8ffdea39e122821c22bb610e965a2823bbd4480)
1 /*
2  * Copyright 2018-2021, Andrew Lindesay <apl@lindesay.co.nz>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 #include "AbstractProcess.h"
6 
7 #include <unistd.h>
8 #include <errno.h>
9 #include <string.h>
10 
11 #include <AutoDeleter.h>
12 #include <AutoLocker.h>
13 #include <Locker.h>
14 
15 #include "HaikuDepotConstants.h"
16 #include "Logger.h"
17 
18 
19 AbstractProcess::AbstractProcess()
20 	:
21 	fLock(),
22 	fListener(NULL),
23 	fWasStopped(false),
24 	fProcessState(PROCESS_INITIAL),
25 	fErrorStatus(B_OK)
26 {
27 }
28 
29 
30 AbstractProcess::~AbstractProcess()
31 {
32 }
33 
34 
35 void
36 AbstractProcess::SetListener(AbstractProcessListener* listener)
37 {
38 	AutoLocker<BLocker> locker(&fLock);
39 	fListener = BReference<AbstractProcessListener>(listener);
40 }
41 
42 
43 status_t
44 AbstractProcess::Run()
45 {
46 	{
47 		AutoLocker<BLocker> locker(&fLock);
48 
49 		if (ProcessState() != PROCESS_INITIAL) {
50 			HDINFO("cannot start process as it is not idle");
51 			return B_NOT_ALLOWED;
52 		}
53 
54 		if (fWasStopped) {
55 			HDINFO("cannot start process as it was stopped");
56 			return B_CANCELED;
57 		}
58 
59 		fProcessState = PROCESS_RUNNING;
60 	}
61 
62 	status_t runResult = RunInternal();
63 
64 	if (runResult != B_OK)
65 		HDERROR("[%s] an error has arisen; %s", Name(), strerror(runResult));
66 
67 	BReference<AbstractProcessListener> listener;
68 
69 	{
70 		AutoLocker<BLocker> locker(&fLock);
71 		fProcessState = PROCESS_COMPLETE;
72 		fErrorStatus = runResult;
73 		listener = fListener;
74 	}
75 
76 	// this process may be part of a larger bulk-load process and
77 	// if so, the process orchestration needs to know when this
78 	// process has completed.
79 	if (listener.IsSet())
80 		listener->ProcessChanged();
81 
82 	return runResult;
83 }
84 
85 
86 bool
87 AbstractProcess::WasStopped()
88 {
89 	AutoLocker<BLocker> locker(&fLock);
90 	return fWasStopped;
91 }
92 
93 
94 status_t
95 AbstractProcess::ErrorStatus()
96 {
97 	AutoLocker<BLocker> locker(&fLock);
98 	return fErrorStatus;
99 }
100 
101 
102 /*! This method will stop the process.  The actual process may carry on to
103     perform some tidy-ups on its thread so this does not stop the thread or
104     change the state of the process; just indicates to the running thread that
105     it should stop.  If it has not yet been started then it will be put into
106     finished state.
107 */
108 
109 status_t
110 AbstractProcess::Stop()
111 {
112 	status_t result = B_CANCELED;
113     BReference<AbstractProcessListener> listener = NULL;
114 
115 	{
116 		AutoLocker<BLocker> locker(&fLock);
117 
118 		if (!fWasStopped) {
119 			fWasStopped = true;
120 			result = StopInternal();
121 
122 			if (fProcessState == PROCESS_INITIAL) {
123 				listener = fListener;
124 				fProcessState = PROCESS_COMPLETE;
125 			}
126 		}
127 	}
128 
129 	if (listener.IsSet())
130 		listener->ProcessChanged();
131 
132 	return result;
133 }
134 
135 
136 status_t
137 AbstractProcess::StopInternal()
138 {
139 	return B_NOT_ALLOWED;
140 }
141 
142 
143 bool
144 AbstractProcess::IsRunning()
145 {
146 	return ProcessState() == PROCESS_RUNNING;
147 }
148 
149 
150 process_state
151 AbstractProcess::ProcessState()
152 {
153 	AutoLocker<BLocker> locker(&fLock);
154 	return fProcessState;
155 }
156 
157 
158 float
159 AbstractProcess::Progress()
160 {
161 	return kProgressIndeterminate;
162 }
163 
164 
165 void
166 AbstractProcess::_NotifyChanged()
167 {
168     BReference<AbstractProcessListener> listener = NULL;
169 	{
170 		AutoLocker<BLocker> locker(&fLock);
171 		listener = fListener;
172 	}
173 	if (listener.IsSet())
174 		listener->ProcessChanged();
175 }
176