blob: ea4321ee458a43ca3a70b6888e8eecb7a633eb8a [file]
// 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.
#ifndef __PROCESS_CHECK_HPP__
#define __PROCESS_CHECK_HPP__
#include <string>
#include <stout/check.hpp>
#include <stout/option.hpp>
#include <process/future.hpp>
// Provides a CHECK_PENDING macro, akin to CHECK.
// This appends the error if possible to the end of the log message, so there's
// no need to append the error message explicitly.
#define CHECK_PENDING(expression) \
CHECK_STATE(CHECK_PENDING, _check_pending, expression)
#define CHECK_READY(expression) \
CHECK_STATE(CHECK_READY, _check_ready, expression)
#define CHECK_DISCARDED(expression) \
CHECK_STATE(CHECK_DISCARDED, _check_discarded, expression)
#define CHECK_FAILED(expression) \
CHECK_STATE(CHECK_FAILED, _check_failed, expression)
#define CHECK_ABANDONED(expression) \
CHECK_STATE(CHECK_ABANDONED, _check_abandoned, expression)
// Private structs/functions used for CHECK_*.
template <typename T>
Option<Error> _check_pending(const process::Future<T>& f)
{
if (f.isReady()) {
return Error("is READY");
} else if (f.isDiscarded()) {
return Error("is DISCARDED");
} else if (f.isFailed()) {
return Error("is FAILED: " + f.failure());
} else {
CHECK(f.isPending());
return None();
}
}
template <typename T>
Option<Error> _check_ready(const process::Future<T>& f)
{
if (f.isPending()) {
return Error("is PENDING");
} else if (f.isDiscarded()) {
return Error("is DISCARDED");
} else if (f.isFailed()) {
return Error("is FAILED: " + f.failure());
} else {
CHECK(f.isReady());
return None();
}
}
template <typename T>
Option<Error> _check_discarded(const process::Future<T>& f)
{
if (f.isPending()) {
return Error("is PENDING");
} else if (f.isReady()) {
return Error("is READY");
} else if (f.isFailed()) {
return Error("is FAILED: " + f.failure());
} else {
CHECK(f.isDiscarded());
return None();
}
}
template <typename T>
Option<Error> _check_failed(const process::Future<T>& f)
{
if (f.isPending()) {
return Some("is PENDING");
} else if (f.isReady()) {
return Some("is READY");
} else if (f.isDiscarded()) {
return Some("is DISCARDED");
} else {
CHECK(f.isFailed());
return None();
}
}
template <typename T>
Option<Error> _check_abandoned(const process::Future<T>& f)
{
if (f.isReady()) {
return Some("is READY");
} else if (f.isDiscarded()) {
return Some("is DISCARDED");
} else if (f.isFailed()) {
return Some("is FAILED: " + f.failure());
} else if (!f.isAbandoned()) {
return Some("is not abandoned");
}
return None();
}
// TODO(dhamon): CHECK_NPENDING, CHECK_NREADY, etc.
#endif // __PROCESS_CHECK_HPP__