Program Listing for File exception.h
↰ Return to documentation for file (core/include/utils/exception.h
)
//==================================================================================
// BSD 2-Clause License
//
// Copyright (c) 2014-2022, NJIT, Duality Technologies Inc. and other contributors
//
// All rights reserved.
//
// Author TPOC: contact@openfhe.org
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==================================================================================
/*
framework for exceptions in OpenFHE
*/
#ifndef SRC_CORE_LIB_UTILS_EXCEPTION_H_
#define SRC_CORE_LIB_UTILS_EXCEPTION_H_
#include "utils/get-call-stack.h"
#include <exception>
#include <iostream>
#include <mutex>
#include <stdexcept>
#include <string>
#include <vector>
namespace lbcrypto {
// Exceptions thrown inside of a critical region, or inside of an omp thread,
// must be caught in the same thread where thrown, or Bad Things Happen
//
// This class is used to catch and rethrow exceptions from threads/critical
// regions (thank you stack overflow)
class ThreadException {
std::exception_ptr Ptr;
std::mutex Lock;
public:
ThreadException() : Ptr(nullptr) {}
~ThreadException() {}
void Rethrow() {
if (this->Ptr)
std::rethrow_exception(this->Ptr);
}
void CaptureException() {
std::unique_lock<std::mutex> guard(this->Lock);
this->Ptr = std::current_exception();
}
template <typename Function, typename... Parameters>
void Run(Function f, Parameters... params) {
try {
f(params...);
}
catch (...) {
CaptureException();
}
}
};
// how to use ThreadException
// To use this, declare an instance of the object before the critical
// region/thread, catch exceptions in thread with CaptureException, then after
// the region call object.Rethrow()
// #pragma omp parallel for
// for (unsigned i = 0; i < rv.size(); i++) try {
// rv.polys[i] = (polys[i].*f)();
// } catch (...) {
// e.CaptureException();
// }
// e.Rethrow();
//
// // use of Run looks like:
// ThreadException e;
// #pragma omp parallel for
// for (int i = 0; i < n; i++) {
// e.Run([=] {
// // code that might throw
// // ...
// });
// }
// e.Rethrow();
class openfhe_error : public std::runtime_error {
std::string filename;
int linenum;
std::string message;
public:
openfhe_error(const std::string& file, int line, const std::string& what)
: std::runtime_error(what), filename(file), linenum(line) {
message = filename + ":" + std::to_string(linenum) + " " + what;
}
const char* what() const throw() {
return message.c_str();
}
const std::string& GetFilename() const {
return filename;
}
int GetLinenum() const {
return linenum;
}
};
class config_error : public openfhe_error {
public:
config_error(const std::string& file, int line, const std::string& what) : openfhe_error(file, line, what) {}
};
class math_error : public openfhe_error {
public:
math_error(const std::string& file, int line, const std::string& what) : openfhe_error(file, line, what) {}
};
class not_implemented_error : public openfhe_error {
public:
not_implemented_error(const std::string& file, int line, const std::string& what)
: openfhe_error(file, line, what) {}
};
class not_available_error : public openfhe_error {
public:
not_available_error(const std::string& file, int line, const std::string& what) : openfhe_error(file, line, what) {}
};
class type_error : public openfhe_error {
public:
type_error(const std::string& file, int line, const std::string& what) : openfhe_error(file, line, what) {}
};
// use this error when serializing openfhe objects
class serialize_error : public openfhe_error {
public:
serialize_error(const std::string& file, int line, const std::string& what) : openfhe_error(file, line, what) {}
};
// use this error when deserializing openfhe objects
class deserialize_error : public openfhe_error {
public:
deserialize_error(const std::string& file, int line, const std::string& what) : openfhe_error(file, line, what) {}
};
class OpenFHEException : public std::exception {
std::string m_errorDescription;
std::string m_fileName;
std::string m_funcName;
size_t m_lineNumber;
std::string m_errorMessage;
std::vector<std::string> m_callStack;
public:
OpenFHEException(const std::string errorDescription, const std::string fileName = __builtin_FILE(),
const std::string funcName = __builtin_FUNCTION(), size_t lineNumber = __builtin_LINE())
: m_errorDescription(errorDescription), m_fileName(fileName), m_funcName(funcName), m_lineNumber(lineNumber) {
m_errorMessage =
m_fileName + ":l." + std::to_string(m_lineNumber) + ":" + m_funcName + "(): " + m_errorDescription;
m_callStack = get_call_stack();
}
OpenFHEException(const OpenFHEException& ex) = default;
const char* what() const noexcept {
return m_errorMessage.c_str();
}
std::vector<std::string> getCallStackAsVector() {
return m_callStack;
}
// getCallStackAsString() was added to be used by JSON logger. the implementtion will follow
std::string getCallStackAsString() {
return std::string();
}
};
// ATTN:
// 1. OPENFHE_THROW is to be overloaded for the period of transition to OpenFHEException only.
// 2. After that openfhe_error, all classes derived from it and OPENFHE_THROW_OLD must be removed
// 3. All the macros below should be removed except OPENFHE_THROW_NEW. OPENFHE_THROW_NEW should
// be renamed to OPENFHE_THROW
// #define OPENFHE_THROW(expr) throw lbcrypto::OpenFHEException(expr)
#define OPENFHE_THROW_OLD(exc, expr) throw exc(__FILE__, __LINE__, (expr))
#define OPENFHE_THROW_NEW(expr) throw lbcrypto::OpenFHEException(expr)
#define GET_CORRECT_MACRO(_1, _2, NAME, ...) NAME
#define OPENFHE_THROW(...) GET_CORRECT_MACRO(__VA_ARGS__, OPENFHE_THROW_OLD, OPENFHE_THROW_NEW)(__VA_ARGS__)
} // namespace lbcrypto
#endif /* SRC_CORE_LIB_UTILS_EXCEPTION_H_ */