1 /**
2 * Copyright 2019 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "minddata/dataset/util/service.h"
17 #include <thread>
18
19 namespace mindspore {
20 namespace dataset {
ServiceStart()21 Status Service::ServiceStart() {
22 do {
23 UniqueLock lck(&state_lock_);
24 // No-op if it is already up or some other thread is
25 // in the process of bring it up.
26 if (state_ == STATE::kRunning || state_ == STATE::kStartInProg) {
27 return Status::OK();
28 }
29 // If a stop is in progress, we line up after it
30 // is done.
31 if (state_ == STATE::kStopInProg) {
32 std::this_thread::yield();
33 } else {
34 state_ = STATE::kStartInProg;
35 // At this point, we will let go of the lock. This allow others to proceed.
36 lck.Unlock();
37 // Call the real implementation from the derived class.
38 Status rc = DoServiceStart();
39 // If we hit any error, change the state back into the initial state.
40 // It is possible that the user may want to drive a clean up by calling
41 // ServiceStop but if it will end up in a loop because of the state is still
42 // kStartInProg.
43 if (rc.IsError()) {
44 lck.Lock();
45 state_ = STATE::kStopped;
46 lck.Unlock();
47 return rc;
48 }
49 // Lock again to change state.
50 lck.Lock();
51 state_ = STATE::kRunning;
52 return Status::OK();
53 }
54 } while (true);
55 }
56
ServiceStop()57 Status Service::ServiceStop() noexcept {
58 do {
59 UniqueLock lck(&state_lock_);
60 // No-op if it is already stopped or some other thread is
61 // in the process of shutting it down
62 if (state_ == STATE::kStopped || state_ == STATE::kStopInProg) {
63 return Status::OK();
64 }
65 // If a start is in progress, we line up after it
66 // is done.
67 if (state_ == STATE::kStartInProg) {
68 std::this_thread::yield();
69 } else {
70 state_ = STATE::kStopInProg;
71 // At this point, we will let go of the lock. This allows others to proceed.
72 lck.Unlock();
73 RETURN_IF_NOT_OK(DoServiceStop());
74 // Lock again to change state.
75 lck.Lock();
76 state_ = STATE::kStopped;
77 return Status::OK();
78 }
79 } while (true);
80 }
81 } // namespace dataset
82 } // namespace mindspore
83