async_simple/coro/LazyLocalBase.h (65 lines of code) (raw):
/*
* Copyright (c) 2024, Alibaba Group Holding Limited;
*
* 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 ASYNC_SIMPLE_CORO_LAZYLOCALBASE_H
#define ASYNC_SIMPLE_CORO_LAZYLOCALBASE_H
#ifndef ASYNC_SIMPLE_USE_MODULES
#include <cassert>
#include <cstdint>
#include <memory>
#include <type_traits>
#include <utility>
#include "async_simple/Common.h"
#include "async_simple/Signal.h"
#endif // ASYNC_SIMPLE_USE_MODULES
namespace async_simple::coro {
class LazyLocalBase;
namespace detail {
void moveSlotFromContinuation(LazyLocalBase* nowLocal, LazyLocalBase* preLocal);
}
// User can derived user-defined class from Lazy Local variable to implement
// user-define lazy local value by implement static function T::classof(const
// LazyLocalBase*).
// For example:
// struct mylocal : public LazyLocalBase {
// inline static char tag; // support a not-null unique address for type
// checking
// // init LazyLocalBase by unique address
// mylocal(std::string sv) : LazyLocalBase(&tag), name(std::move(sv)) {}
// // derived class support implement T::classof(LazyLocalBase*), which
// check if this object is-a derived class of T static bool
// classof(const LazyLocalBase*) {
// return base->getTypeTag() == &tag;
// }
// std::string name;
// };
class LazyLocalBase {
protected:
LazyLocalBase(char* typeinfo, Signal* signal = nullptr,
SignalType type = SignalType::All)
: _typeinfo(typeinfo) {
assert(typeinfo != nullptr);
};
public:
LazyLocalBase(LazyLocalBase&&) = default;
const char* getTypeTag() const noexcept { return _typeinfo; }
Slot* getSlot() const noexcept { return _slot.get(); }
void forbidSignal() noexcept { _slot = nullptr; }
virtual ~LazyLocalBase(){};
LazyLocalBase(Signal* signal, SignalType type = SignalType::All)
: _typeinfo(nullptr), _slot(std::make_unique<Slot>(signal, type)) {}
friend void detail::moveSlotFromContinuation(LazyLocalBase* nowLocal,
LazyLocalBase* preLocal);
protected:
char* _typeinfo;
std::unique_ptr<Slot> _slot;
};
template <typename T>
const T* dynamicCast(const LazyLocalBase* base) noexcept {
assert(base != nullptr);
if constexpr (std::is_same_v<T, LazyLocalBase>) {
return base;
} else {
if (T::classof(base)) {
return static_cast<T*>(base);
} else {
return nullptr;
}
}
}
template <typename T>
T* dynamicCast(LazyLocalBase* base) noexcept {
assert(base != nullptr);
if constexpr (std::is_same_v<T, LazyLocalBase>) {
return base;
} else {
if (T::classof(base)) {
return static_cast<T*>(base);
} else {
return nullptr;
}
}
}
// namespace async_simple::coro
} // namespace async_simple::coro
#endif