Path: blob/21.2-virgl/src/gallium/frontends/clover/util/lazy.hpp
4572 views
//1// Copyright 2013 Francisco Jerez2//3// Permission is hereby granted, free of charge, to any person obtaining a4// copy of this software and associated documentation files (the "Software"),5// to deal in the Software without restriction, including without limitation6// the rights to use, copy, modify, merge, publish, distribute, sublicense,7// and/or sell copies of the Software, and to permit persons to whom the8// Software is furnished to do so, subject to the following conditions:9//10// The above copyright notice and this permission notice shall be included in11// all copies or substantial portions of the Software.12//13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19// OTHER DEALINGS IN THE SOFTWARE.20//2122#ifndef CLOVER_UTIL_LAZY_HPP23#define CLOVER_UTIL_LAZY_HPP2425#include <type_traits>26#include <stdexcept>27#include <memory>2829namespace clover {30namespace detail {31template<typename T>32class basic_lazy {33public:34virtual35~basic_lazy() {36}3738virtual basic_lazy *39clone() const = 0;4041virtual42operator T() const = 0;43};4445template<typename T, typename F>46class deferred_lazy : public basic_lazy<T> {47public:48template<typename G>49deferred_lazy(G &&f) : f(new F(std::forward<G>(f))) {50}5152virtual basic_lazy<T> *53clone() const {54return new deferred_lazy(*this);55}5657operator T() const {58if (f) {59x = (*f)();60f = {};61}6263return x;64}6566private:67mutable std::shared_ptr<F> f;68mutable T x;69};7071template<typename T>72class strict_lazy : public basic_lazy<T> {73public:74template<typename S>75strict_lazy(S &&x) : x(std::forward<S>(x)) {76}7778virtual basic_lazy<T> *79clone() const {80return new strict_lazy(*this);81}8283operator T() const {84return x;85}8687private:88T x;89};90}9192///93/// Object that represents a value of type \a T that is calculated94/// lazily as soon as it is required.95///96template<typename T>97class lazy {98public:99class undefined_error : std::logic_error {100public:101undefined_error() : std::logic_error("") {102}103};104105///106/// Initialize to some fixed value \a x which isn't calculated107/// lazily.108///109lazy(T x) : obj(new detail::strict_lazy<T>(x)) {110}111112///113/// Initialize by providing a functor \a f that will calculate114/// the value on-demand.115///116template<typename F>117lazy(F &&f) : obj(new detail::deferred_lazy<118T, typename std::remove_reference<F>::type119>(std::forward<F>(f))) {120}121122///123/// Initialize to undefined.124///125lazy() : lazy([]() {126throw undefined_error();127return T();128}) {129}130131lazy(const lazy &other) : obj(obj->clone()) {132}133134lazy(lazy &&other) : obj(NULL) {135std::swap(obj, other.obj);136}137138~lazy() {139delete obj;140}141142lazy &143operator=(lazy other) {144std::swap(obj, other.obj);145return *this;146}147148///149/// Evaluate the value.150///151operator T() const {152return *obj;153}154155private:156detail::basic_lazy<T> *obj;157};158}159160#endif161162163