Async-Trampoline

 view release on metacpan or  search on metacpan

src/Async_Initialization.cpp  view on Meta::CPAN

static void Async_Cancel_clear     (Async* self);
static void Async_Error_clear      (Async* self);
static void Async_Value_clear      (Async* self);

// Polymorphic

auto Async::clear() -> void
{
    ASYNC_LOG_DEBUG("clear() " ASYNC_FORMAT "\n",
            ASYNC_FORMAT_ARGS(this));

    switch (type) {
        case Async_Type::IS_UNINITIALIZED:
            break;

        case Async_Type::CATEGORY_INITIALIZED:
            assert(0);
            break;
        case Async_Type::IS_PTR:
            Async_Ptr_clear(this);
            break;
        case Async_Type::IS_RAWTHUNK:
            Async_RawThunk_clear(this);
            break;
        case Async_Type::IS_THUNK:
            Async_Thunk_clear(this);
            break;
        case Async_Type::IS_CONCAT:
            Async_Binary_clear(*this, type);
            break;
        case Async_Type::IS_FLOW:
            Async_Flow_clear(*this);
            break;

        case Async_Type::CATEGORY_COMPLETE:
            assert(0);
            break;
        case Async_Type::IS_CANCEL:
            Async_Cancel_clear(this);
            break;

        case Async_Type::CATEGORY_RESOLVED:
            assert(0);
            break;
        case Async_Type::IS_ERROR:
            Async_Error_clear(this);
            break;
        case Async_Type::IS_VALUE:
            Async_Value_clear(this);
            break;

        default:
            assert(0);
    }
}

auto Async::set_from(Async&& other) -> void
{
    assert(type == Async_Type::IS_UNINITIALIZED);

    assert(other.blocked.size() == 0);

    switch (other.type)
    {
        case Async_Type::IS_UNINITIALIZED:
            break;

        case Async_Type::CATEGORY_INITIALIZED:
            assert(0);
            break;
        case Async_Type::IS_PTR:
            set_to_Ptr(std::move(other.as_ptr));
            Async_Ptr_clear(&other);
            break;
        case Async_Type::IS_RAWTHUNK:
            assert(0); // TODO not implemented
            break;
        case Async_Type::IS_THUNK:
            set_to_Thunk(
                    std::move(other.as_thunk.callback),
                    std::move(other.as_thunk.dependency));
            Async_Thunk_clear(&other);
            break;
        case Async_Type::IS_CONCAT:
            set_to_Binary(
                    *this,
                    other.type,
                    std::move(other.as_binary.left),
                    std::move(other.as_binary.right));
            Async_Binary_clear(other, other.type);
            break;
        case Async_Type::IS_FLOW:
            set_to_Flow(std::move(other.as_flow));
            Async_Flow_clear(other);
            break;

        case Async_Type::CATEGORY_COMPLETE:
            assert(0);
            break;
        case Async_Type::IS_CANCEL:
            set_to_Cancel();
            Async_Cancel_clear(&other);
            break;

        case Async_Type::CATEGORY_RESOLVED:
            assert(0);
            break;
        case Async_Type::IS_ERROR:
            set_to_Error(std::move(other.as_error));
            Async_Error_clear(&other);
            break;
        case Async_Type::IS_VALUE:
            set_to_Value(std::move(other.as_value));
            Async_Value_clear(&other);
            break;

        default:
            assert(0);
    }

}

auto Async::operator=(Async& other) -> Async&
{
    ASYNC_LOG_DEBUG("unify " ASYNC_FORMAT " with " ASYNC_FORMAT "\n",
            ASYNC_FORMAT_ARGS(this),
            ASYNC_FORMAT_ARGS(&other));

    // as a special case, CANCEL holds no resources and can always be copied
    if (other.has_type(Async_Type::IS_CANCEL))
    {
        clear();
        set_to_Cancel();
        return *this;
    }

    if (other.refcount > 1)
    {
        AsyncRef ref{&other};  // keep ref in case we own it
        clear();
        set_to_Ptr(std::move(ref));
        return *this;
    }

    assert(other.refcount == 1); // caller is the only owner

    // save other in case we might own it, because we clear() ourself.
    AsyncRef unref_me{};
    if (type != Async_Type::IS_UNINITIALIZED)
        unref_me = &other;

    clear();

    set_from(std::move(other));
    return *this;
}

// Ptr

void Async::set_to_Ptr(
        AsyncRef target)
{
    ASSERT_INIT(this);
    assert(target);

    target.fold();

    ASYNC_LOG_DEBUG("init %p to Ptr: target=" ASYNC_FORMAT "\n",
            this,
            ASYNC_FORMAT_ARGS(target.decay()));

    type = Async_Type::IS_PTR;
    new (&as_ptr) AsyncRef { std::move(target) };

    //  // transfer all dependencies to target
    //  Async& target_ref = ptr_follow();
    //  for (auto& depref : blocked)
    //      target_ref.add_blocked(std::move(depref));
    //  blocked.clear();
}

void
Async_Ptr_clear(
        Async*  self)
{
    assert(self);
    assert(self->type == Async_Type::IS_PTR);

    ASYNC_LOG_DEBUG("clear %p of Ptr: target=" ASYNC_FORMAT "\n",
            self,
            ASYNC_FORMAT_ARGS(self->as_ptr.decay()));

    self->type = Async_Type::IS_UNINITIALIZED;
    self->as_ptr.~AsyncRef();
}

// RawThunk

void Async::set_to_RawThunk(
        Async_RawThunk::Callback    callback,
        AsyncRef                    dependency)
{
    ASSERT_INIT(this);
    assert(callback);

    UNUSED(dependency);

    assert(0); // TODO not implemented
}

void
Async_RawThunk_clear(
        Async*  self)
{
    assert(self);
    assert(self->type == Async_Type::IS_RAWTHUNK);

    assert(0);  // TODO not implemented
}

// Thunk

void Async::set_to_Thunk(
        Async_Thunk::Callback   callback,
        AsyncRef                dependency)
{
    ASSERT_INIT(this);
    assert(callback);

    if (dependency)
        dependency.fold();

    ASYNC_LOG_DEBUG(
            "init %p to Thunk: callback=??? dependency=" ASYNC_FORMAT "\n",
            this,
            ASYNC_FORMAT_ARGS(dependency.decay()));

    type = Async_Type::IS_THUNK;
    new (&as_thunk) Async_Thunk{



( run in 1.385 second using v1.01-cache-2.11-cpan-13bb782fe5a )