/** * Copyright 2019 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "minddata/dataset/util/service.h" #include namespace mindspore { namespace dataset { Status Service::ServiceStart() { do { UniqueLock lck(&state_lock_); // No-op if it is already up or some other thread is // in the process of bring it up. if (state_ == STATE::kRunning || state_ == STATE::kStartInProg) { return Status::OK(); } // If a stop is in progress, we line up after it // is done. if (state_ == STATE::kStopInProg) { std::this_thread::yield(); } else { state_ = STATE::kStartInProg; // At this point, we will let go of the lock. This allow others to proceed. lck.Unlock(); // Call the real implementation from the derived class. Status rc = DoServiceStart(); // If we hit any error, change the state back into the initial state. // It is possible that the user may want to drive a clean up by calling // ServiceStop but if it will end up in a loop because of the state is still // kStartInProg. if (rc.IsError()) { lck.Lock(); state_ = STATE::kStopped; lck.Unlock(); return rc; } // Lock again to change state. lck.Lock(); state_ = STATE::kRunning; return Status::OK(); } } while (true); } Status Service::ServiceStop() noexcept { do { UniqueLock lck(&state_lock_); // No-op if it is already stopped or some other thread is // in the process of shutting it down if (state_ == STATE::kStopped || state_ == STATE::kStopInProg) { return Status::OK(); } // If a start is in progress, we line up after it // is done. if (state_ == STATE::kStartInProg) { std::this_thread::yield(); } else { state_ = STATE::kStopInProg; // At this point, we will let go of the lock. This allows others to proceed. lck.Unlock(); RETURN_IF_NOT_OK(DoServiceStop()); // Lock again to change state. lck.Lock(); state_ = STATE::kStopped; return Status::OK(); } } while (true); } } // namespace dataset } // namespace mindspore