TarsCloud_TarsCpp/servant/promise/promise_exception.h
2018-09-05 11:26:21 +08:00

200 lines
4.3 KiB
C++

/**
* Tencent is pleased to support the open source community by making Tars available.
*
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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 __TARS_PROMISE_EXCEPTION_H_
#define __TARS_PROMISE_EXCEPTION_H_
#include <string.h>
#include <exception>
#include <string>
#include <sstream>
#include "util/tc_shared_ptr.h"
#include "util/detail/tc_template_util.h"
namespace promise
{
class PromiseException : public std::exception
{
public:
PromiseException()
: _filename(NULL)
, _line(0)
, _sep(':')
{}
PromiseException(const char *filename, int line)
: _filename(filename)
, _line(line)
, _sep(':')
{}
virtual ~PromiseException() throw() {}
virtual const char *what() const throw()
{
try
{
if (!_what.unique())
_what.reset(new std::string(*_what));
if (!_what || _what->empty())
{
std::stringstream ss;
ss << name() << " thrown";
if (_filename && _line > 0)
ss << " at " << _filename << ':' << _line;
if (!_what)
_what.reset(new std::string());
const std::string& s = getErrorInfo();
if (!s.empty())
{
ss << _sep << ' ' << s;
_sep = ';';
}
ss.str().swap(*_what);
}
if (!_data.unique())
_data.reset(new std::string(*_data));
if (_data && !_data->empty())
{
*_what += _sep;
_sep = ';';
*_what += ' ';
_what->append(*_data);
_data.reset();
}
return _what->c_str();
}
catch (...)
{
}
return "";
}
private:
virtual const char *name() const
{
return "PromiseException";
}
virtual std::string getErrorInfo() const
{
return "";
}
const char *_filename;
int _line;
mutable TC_SharedPtr<std::string> _what;
mutable TC_SharedPtr<std::string> _data;
mutable char _sep;
template <typename T>
void injectErrorInfo(const T& t) const;
template <typename Exception, typename T>
friend typename tc_enable_if<tc_is_derived_from<Exception, PromiseException>, const Exception&>::type
operator<<(const Exception& e, const T& t)
{
e.injectErrorInfo(t);
return e;
}
};
template <typename T>
void PromiseException::injectErrorInfo(const T& t) const
{
std::stringstream ss;
ss << t;
if (!_data.unique())
_data.reset(new std::string(*_data));
if (!_data)
{
_data.reset(new std::string(ss.str()));
}
else
{
(*_data) += ss.str();
}
}
namespace detail
{
inline std::string errnoToString(int errorno)
{
return strerror(errorno);
}
} // namespace detail
class SyscallException : public PromiseException
{
public:
SyscallException(const char *filename, int line, int err)
: PromiseException(filename, line)
, _errno(err)
{}
int error() const { return _errno; }
protected:
virtual const char *name() const
{
return "SyscallException";
}
virtual std::string getErrorInfo() const
{
return detail::errnoToString(_errno);
}
private:
int _errno;
};
class AssertionFailureException : public PromiseException
{
public:
AssertionFailureException(const char *filename, int line)
: PromiseException(filename, line)
{
}
private:
virtual const char *name() const
{
return "AssertionFailureException";
}
};
} // namespace promise
#endif // __TARS_PROMISE_EXCEPTION_H__