merge changes from the defunct ubot
This commit is contained in:
parent
1904b22977
commit
cf501b75b7
90 changed files with 11977 additions and 3907 deletions
182
ext/crlib/cr-lambda.h
Normal file
182
ext/crlib/cr-lambda.h
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
//
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-alloc.h>
|
||||
#include <crlib/cr-uniqueptr.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
template <typename> class Lambda;
|
||||
template <typename R, typename ...Args> class Lambda <R (Args...)> {
|
||||
private:
|
||||
enum : uint32 {
|
||||
LamdaSmallBufferLength = sizeof (void *) * 16
|
||||
};
|
||||
|
||||
private:
|
||||
class LambdaFunctorWrapper {
|
||||
public:
|
||||
LambdaFunctorWrapper () = default;
|
||||
virtual ~LambdaFunctorWrapper () = default;
|
||||
|
||||
public:
|
||||
virtual void move (uint8 *to) = 0;
|
||||
virtual void small (uint8 *to) const = 0;
|
||||
|
||||
virtual R invoke (Args &&...) = 0;
|
||||
virtual UniquePtr <LambdaFunctorWrapper> clone () const = 0;
|
||||
|
||||
public:
|
||||
void operator delete (void *ptr) {
|
||||
alloc.deallocate (ptr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class LambdaFunctor : public LambdaFunctorWrapper {
|
||||
private:
|
||||
T callable_;
|
||||
|
||||
public:
|
||||
LambdaFunctor (const T &callable) : LambdaFunctorWrapper (), callable_ (callable)
|
||||
{ }
|
||||
|
||||
LambdaFunctor (T &&callable) : LambdaFunctorWrapper (), callable_ (cr::move (callable))
|
||||
{ }
|
||||
|
||||
~LambdaFunctor () override = default;
|
||||
|
||||
public:
|
||||
void move (uint8 *to) override {
|
||||
new (to) LambdaFunctor <T> (cr::move (callable_));
|
||||
}
|
||||
|
||||
void small (uint8 *to) const override {
|
||||
new (to) LambdaFunctor <T> (callable_);
|
||||
}
|
||||
|
||||
R invoke (Args &&... args) override {
|
||||
return callable_ (cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
UniquePtr <LambdaFunctorWrapper> clone () const override {
|
||||
return makeUnique <LambdaFunctor <T>> (callable_);
|
||||
}
|
||||
};
|
||||
|
||||
union {
|
||||
UniquePtr <LambdaFunctorWrapper> functor_;
|
||||
uint8 small_[LamdaSmallBufferLength];
|
||||
};
|
||||
|
||||
bool ssoObject_ = false;
|
||||
|
||||
private:
|
||||
void destroy () {
|
||||
if (ssoObject_) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (small_)->~LambdaFunctorWrapper ();
|
||||
}
|
||||
else {
|
||||
functor_.reset ();
|
||||
}
|
||||
}
|
||||
|
||||
void swap (Lambda &rhs) noexcept {
|
||||
cr::swap (rhs, *this);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Lambda () noexcept : Lambda (nullptr)
|
||||
{ }
|
||||
|
||||
Lambda (decltype (nullptr)) noexcept : functor_ (nullptr), ssoObject_ (false)
|
||||
{ }
|
||||
|
||||
Lambda (const Lambda &rhs) {
|
||||
if (rhs.ssoObject_) {
|
||||
reinterpret_cast <const LambdaFunctorWrapper *> (rhs.small_)->small (small_);
|
||||
}
|
||||
else {
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (rhs.functor_->clone ());
|
||||
}
|
||||
ssoObject_ = rhs.ssoObject_;
|
||||
}
|
||||
|
||||
Lambda (Lambda &&rhs) noexcept {
|
||||
if (rhs.ssoObject_) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (rhs.small_)->move (small_);
|
||||
new (rhs.small_) UniquePtr <LambdaFunctorWrapper> (nullptr);
|
||||
}
|
||||
else {
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (cr::move (rhs.functor_));
|
||||
}
|
||||
ssoObject_ = rhs.ssoObject_;
|
||||
rhs.ssoObject_ = false;
|
||||
}
|
||||
|
||||
template <typename F> Lambda (F function) {
|
||||
if (cr::fix (sizeof (function) > LamdaSmallBufferLength)) {
|
||||
ssoObject_ = false;
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (makeUnique <LambdaFunctor <F>> (cr::move (function)));
|
||||
}
|
||||
else {
|
||||
ssoObject_ = true;
|
||||
new (small_) LambdaFunctor <F> (cr::move (function));
|
||||
}
|
||||
}
|
||||
|
||||
~Lambda () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
public:
|
||||
Lambda &operator = (const Lambda &rhs) {
|
||||
destroy ();
|
||||
|
||||
Lambda tmp (rhs);
|
||||
swap (tmp);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Lambda &operator = (Lambda &&rhs) noexcept {
|
||||
destroy ();
|
||||
|
||||
if (rhs.ssoObject_) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (rhs.small_)->move (small_);
|
||||
new (rhs.small_) UniquePtr <LambdaFunctorWrapper> (nullptr);
|
||||
}
|
||||
else {
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (cr::move (rhs.functor_));
|
||||
}
|
||||
|
||||
ssoObject_ = rhs.ssoObject_;
|
||||
rhs.ssoObject_ = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool () const noexcept {
|
||||
return ssoObject_ || !!functor_;
|
||||
}
|
||||
|
||||
public:
|
||||
R operator () (Args ...args) {
|
||||
return ssoObject_ ? reinterpret_cast <LambdaFunctorWrapper *> (small_)->invoke (cr::forward <Args> (args)...) : functor_->invoke (cr::forward <Args> (args)...);
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
Loading…
Add table
Add a link
Reference in a new issue