mirror of
https://github.com/google/googletest.git
synced 2025-12-08 01:36:50 +08:00
100 lines
3.4 KiB
C++
100 lines
3.4 KiB
C++
#ifndef COROUTINES_INCLUDE_CORO_COTEST_CORO_COMMON_H_
|
|
#define COROUTINES_INCLUDE_CORO_COTEST_CORO_COMMON_H_
|
|
|
|
#include <exception>
|
|
#include <functional>
|
|
#include <iostream>
|
|
|
|
#include "cotest/internal/cotest-util-logging.h"
|
|
|
|
namespace coro_impl {
|
|
|
|
class Payload {
|
|
public:
|
|
Payload() = default;
|
|
Payload(const Payload &) = delete;
|
|
Payload(Payload &&) = delete;
|
|
Payload &operator=(const Payload &) = delete;
|
|
Payload &operator=(Payload &&) = delete;
|
|
virtual ~Payload() = default;
|
|
virtual std::string DebugString() const = 0;
|
|
};
|
|
|
|
template <typename PAY, typename ORIG>
|
|
const PAY &PeekPayload(const std::unique_ptr<ORIG> &p) {
|
|
return *static_cast<PAY *>(p.get());
|
|
}
|
|
|
|
template <typename PAY, typename ORIG>
|
|
std::unique_ptr<PAY> SpecialisePayload(std::unique_ptr<ORIG> &&p) {
|
|
return std::unique_ptr<PAY>(static_cast<PAY *>(p.release()));
|
|
}
|
|
|
|
template <typename PAY, typename... Args>
|
|
std::unique_ptr<PAY> MakePayload(Args &&... args) {
|
|
return std::make_unique<PAY>(std::forward<Args>(args)...);
|
|
}
|
|
|
|
class ExteriorInterface {
|
|
public:
|
|
ExteriorInterface() = default;
|
|
ExteriorInterface(const ExteriorInterface &i) = delete;
|
|
ExteriorInterface(ExteriorInterface &&i) = delete;
|
|
ExteriorInterface &operator=(const ExteriorInterface &) = delete;
|
|
ExteriorInterface &operator=(ExteriorInterface &&) = delete;
|
|
virtual ~ExteriorInterface() = default;
|
|
|
|
virtual std::unique_ptr<Payload> Iterate(std::unique_ptr<Payload> &&to_coro) = 0;
|
|
virtual std::unique_ptr<Payload> ThrowIn(std::exception_ptr in_ex) = 0;
|
|
virtual void Cancel() = 0;
|
|
virtual bool IsCoroutineExited() const = 0;
|
|
virtual void SetName(std::string name_) = 0;
|
|
virtual std::string GetName() const = 0;
|
|
};
|
|
|
|
class InteriorInterface {
|
|
public:
|
|
InteriorInterface() = default;
|
|
InteriorInterface(const InteriorInterface &i) = delete;
|
|
InteriorInterface(InteriorInterface &&i) = delete;
|
|
InteriorInterface &operator=(const InteriorInterface &) = delete;
|
|
InteriorInterface &operator=(InteriorInterface &&) = delete;
|
|
virtual ~InteriorInterface() = default;
|
|
|
|
virtual std::unique_ptr<Payload> Yield(std::unique_ptr<Payload> &&from_coro) = 0;
|
|
|
|
// Find out which coro is currently running. Any of the instances of
|
|
// the same concrete type as the one called on, or NULL.
|
|
virtual InteriorInterface *GetActive() = 0;
|
|
};
|
|
|
|
using BodyFunction = std::function<void()>;
|
|
|
|
class CancellationException : public std::exception {};
|
|
|
|
// std::exception_ptr lets us be flexible with exception objects without
|
|
// having to worry about slicing. The object is stored in the compiler's
|
|
// special place and should be considered const - it *cannot* be accessed
|
|
// through the exception_ptr - all you can do is pass it around and
|
|
// throw it using std::rethrow_exception(). Note that exception_ptr is
|
|
// nullable (use = nullptr) but you shouldn't rethrow a null one. The
|
|
// exception object could be copied, so don't use identity semantics.
|
|
template <class ETYPE, class... Args>
|
|
std::exception_ptr MakeException(Args &&... args) try {
|
|
throw ETYPE(args...);
|
|
COTEST_ASSERT(false); // wut
|
|
} catch (ETYPE &) // Don't catch exceptions thrown in ETYPE's constructor
|
|
{
|
|
return std::current_exception();
|
|
}
|
|
|
|
inline std::ostream &operator<<(std::ostream &os, const Payload *payload) {
|
|
if (payload) os << payload->DebugString();
|
|
os << PtrToString(payload);
|
|
return os;
|
|
}
|
|
|
|
} // namespace coro_impl
|
|
|
|
#endif
|