[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/versionzero/cpp.react/master/include/react/Domain.h [Back]  [Original]

//          Copyright Sebastian Jeckel 2014.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#ifndef REACT_DOMAIN_H_INCLUDED
#define REACT_DOMAIN_H_INCLUDED

#pragma once

#include "react/detail/Defs.h"

#include 
#include 

#include "react/detail/DomainBase.h"
#include "react/detail/ReactiveInput.h"

#include "react/detail/graph/ContinuationNodes.h"

#ifdef REACT_ENABLE_LOGGING
    #include "react/logging/EventLog.h"
    #include "react/logging/EventRecords.h"
#endif //REACT_ENABLE_LOGGING

/*****************************************/ REACT_BEGIN /*****************************************/

///////////////////////////////////////////////////////////////////////////////////////////////////
/// Forward declarations
///////////////////////////////////////////////////////////////////////////////////////////////////
template 
class Signal;

template 
class VarSignal;

template 
class TempSignal;

template 
class Events;

template 
class EventSource;

template 
class TempEvents;

enum class Token;

template 
class Observer;

template 
class ScopedObserver;

template 
class Reactor;

template 
class SignalPack;

///////////////////////////////////////////////////////////////////////////////////////////////////
/// Common types & constants
///////////////////////////////////////////////////////////////////////////////////////////////////
using REACT_IMPL::TransactionFlagsT;

// ETransactionFlags
using REACT_IMPL::ETransactionFlags;
using REACT_IMPL::allow_merging;

#ifdef REACT_ENABLE_LOGGING
    using REACT_IMPL::EventLog;
#endif //REACT_ENABLE_LOGGING

// Domain modes
using REACT_IMPL::EDomainMode;
using REACT_IMPL::sequential;
using REACT_IMPL::sequential_concurrent;
using REACT_IMPL::parallel;
using REACT_IMPL::parallel_concurrent;

// Expose enum type so aliases for engines can be declared, but don't
// expose the actual enum values as they are reserved for internal use.
using REACT_IMPL::EPropagationMode;

using REACT_IMPL::WeightHint;

///////////////////////////////////////////////////////////////////////////////////////////////////
/// TransactionStatus
///////////////////////////////////////////////////////////////////////////////////////////////////
class TransactionStatus
{
    using StateT = REACT_IMPL::SharedWaitingState;
    using PtrT = REACT_IMPL::WaitingStatePtrT;

public:
    // Default ctor
    inline TransactionStatus() :
        statePtr_( StateT::Create() )
    {}

    // Move ctor
    inline TransactionStatus(TransactionStatus&& other) :
        statePtr_( std::move(other.statePtr_) )
    {
        other.statePtr_ = StateT::Create();
    }

    // Move assignment
    inline TransactionStatus& operator=(TransactionStatus&& other)
    {
        if (this != &other)
        {
            statePtr_ = std::move(other.statePtr_);
            other.statePtr_ = StateT::Create();
        }
        return *this;
    }

    // Deleted copy ctor & assignment
    TransactionStatus(const TransactionStatus&) = delete;
    TransactionStatus& operator=(const TransactionStatus&) = delete;

    inline void Wait()
    {
        assert(statePtr_.Get() != nullptr);
        statePtr_->Wait();
    }

private:
    PtrT statePtr_;

    template 
    friend void AsyncTransaction(TransactionStatus& status, F&& func);

    template 
    friend void AsyncTransaction(TransactionFlagsT flags, TransactionStatus& status, F&& func);
};

///////////////////////////////////////////////////////////////////////////////////////////////////
/// Continuation
///////////////////////////////////////////////////////////////////////////////////////////////////
template
<
    typename D,
    typename D2 = D
>
class Continuation : public REACT_IMPL::ContinuationBase
{
private:
    using NodePtrT  = REACT_IMPL::NodeBasePtrT;

public:
    using SourceDomainT = D;
    using TargetDomainT = D2;

    // Default ctor
    Continuation() = default;

    // Move ctor
    Continuation(Continuation&& other) :
        Continuation::ContinuationBase( std::move(other) )
    {}

    // Node ctor
    explicit Continuation(NodePtrT&& nodePtr) :
        Continuation::ContinuationBase( std::move(nodePtr) )
    {}

    // Move assignment
    Continuation& operator=(Continuation&& other)
    {
        Continuation::ContinuationBase::operator=( std::move(other) );
        return *this;
    }

    // Deleted copy ctor & assignment
    Continuation(const Continuation&) = delete;
    Continuation& operator=(const Continuation&) = delete;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
/// MakeContinuation - Signals
///////////////////////////////////////////////////////////////////////////////////////////////////
template
<
    typename D,
    typename DOut = D,
    typename S,
    typename FIn
>
auto MakeContinuation(TransactionFlagsT flags, const Signal& trigger, FIn&& func)
    -> Continuation
{
    static_assert(DOut::is_concurrent,
        "MakeContinuation: Target domain does not support concurrent input.");

    using REACT_IMPL::SignalContinuationNode;
    using F = typename std::decay::type;

    return Continuation(
        std::make_shared(
            flags, GetNodePtr(trigger), std::forward(func)));
}

template
<
    typename D,
    typename DOut = D,
    typename S,
    typename FIn
>
auto MakeContinuation(const Signal& trigger, FIn&& func)
    -> Continuation
{
    return MakeContinuation(0, trigger, std::forward(func));
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/// MakeContinuation - Events
///////////////////////////////////////////////////////////////////////////////////////////////////
template
<
    typename D,
    typename DOut = D,
    typename E,
    typename FIn
>
auto MakeContinuation(TransactionFlagsT flags, const Events& trigger, FIn&& func)
    -> Continuation
{
    static_assert(DOut::is_concurrent,
        "MakeContinuation: Target domain does not support concurrent input.");

    using REACT_IMPL::EventContinuationNode;
    using REACT_IMPL::AddContinuationRangeWrapper;
    using REACT_IMPL::IsCallableWith;
    using REACT_IMPL::EventRange;

    using F = typename std::decay::type;

    using WrapperT =
        typename std::conditional<
            IsCallableWith::value,
            F,
            typename std::conditional<
                IsCallableWith::value,
                AddContinuationRangeWrapper,
                void
            >::type
        >::type;

    static_assert(! std::is_same::value,
        "MakeContinuation: Passed function does not match any of the supported signatures.");

    return Continuation(
        std::make_shared(
            flags, GetNodePtr(trigger), std::forward(func)));
}

template
<
    typename D,
    typename DOut = D,
    typename E,
    typename FIn
>
auto MakeContinuation(const Events& trigger, FIn&& func)
    -> Continuation
{
    return MakeContinuation(0, trigger, std::forward(func));
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/// MakeContinuation - Synced
///////////////////////////////////////////////////////////////////////////////////////////////////
template
<
    typename D,
    typename DOut = D,
    typename E,
    typename FIn,
    typename ... TDepValues
>
auto MakeContinuation(TransactionFlagsT flags, const Events& trigger,
                      const SignalPack& depPack, FIn&& func)
    -> Continuation
{
    static_assert(DOut::is_concurrent,
        "MakeContinuation: Target domain does not support concurrent input.");

    using REACT_IMPL::SyncedContinuationNode;
    using REACT_IMPL::AddContinuationRangeWrapper;
    using REACT_IMPL::IsCallableWith;
    using REACT_IMPL::EventRange;

    using F = typename std::decay::type;

    using WrapperT =
        typename std::conditional<
            IsCallableWith::value,
            F,
            typename std::conditional<
                IsCallableWith::value,
                AddContinuationRangeWrapper,
                void
            >::type
        >::type;

    static_assert(! std::is_same::value,
        "MakeContinuation: Passed function does not match any of the supported signatures.");

    struct NodeBuilder_
    {
        NodeBuilder_(TransactionFlagsT flags, const Events& trigger, FIn&& func) :
            MyFlags( flags ),
            MyTrigger( trigger ),
            MyFunc( std::forward(func) )
        {}

        auto operator()(const Signal& ... deps)
            -> Continuation
        {
            return Continuation(
                std::make_shared(
                    MyFlags,
                    GetNodePtr(MyTrigger),
                    std::forward(MyFunc), GetNodePtr(deps) ...));
        }

        TransactionFlagsT   MyFlags;
        const Events&  MyTrigger;
        FIn                 MyFunc;
    };

    return REACT_IMPL::apply(
        NodeBuilder_( flags, trigger, std::forward(func) ),
        depPack.Data);
}

template
<
    typename D,
    typename DOut = D,
    typename E,
    typename FIn,
    typename ... TDepValues
>
auto MakeContinuation(const Events& trigger,
                      const SignalPack& depPack, FIn&& func)
    -> Continuation
{
    return MakeContinuation(0, trigger, depPack, std::forward(func));
}

///////////////////////////////////////////////////////////////////////////////////////////////
/// DoTransaction
///////////////////////////////////////////////////////////////////////////////////////////////
template 
void DoTransaction(F&& func)
{
    using REACT_IMPL::DomainSpecificInputManager;
    DomainSpecificInputManager::Instance().DoTransaction(0, std::forward(func));
}

template 
void DoTransaction(TransactionFlagsT flags, F&& func)
{
    using REACT_IMPL::DomainSpecificInputManager;
    DomainSpecificInputManager::Instance().DoTransaction(flags, std::forward(func));
}

///////////////////////////////////////////////////////////////////////////////////////////////
/// AsyncTransaction
///////////////////////////////////////////////////////////////////////////////////////////////
template 
void AsyncTransaction(F&& func)
{
    static_assert(D::is_concurrent,
        "AsyncTransaction: Domain does not support concurrent input.");

    using REACT_IMPL::DomainSpecificInputManager;
    DomainSpecificInputManager::Instance()
        .AsyncTransaction(0, nullptr, std::forward(func));
}

template 
void AsyncTransaction(TransactionFlagsT flags, F&& func)
{
    static_assert(D::is_concurrent,
        "AsyncTransaction: Domain does not support concurrent input.");

    using REACT_IMPL::DomainSpecificInputManager;
    DomainSpecificInputManager::Instance()
        .AsyncTransaction(flags, nullptr, std::forward(func));
}

template 
void AsyncTransaction(TransactionStatus& status, F&& func)
{
    static_assert(D::is_concurrent,
        "AsyncTransaction: Domain does not support concurrent input.");

    using REACT_IMPL::DomainSpecificInputManager;

    DomainSpecificInputManager::Instance()
        .AsyncTransaction(0, status.statePtr_, std::forward(func));
}

template 
void AsyncTransaction(TransactionFlagsT flags, TransactionStatus& status, F&& func)
{
    static_assert(D::is_concurrent,
        "AsyncTransaction: Domain does not support concurrent input.");

    using REACT_IMPL::DomainSpecificInputManager;
    DomainSpecificInputManager::Instance()
        .AsyncTransaction(flags, status.statePtr_, std::forward(func));
}

/******************************************/ REACT_END /******************************************/

///////////////////////////////////////////////////////////////////////////////////////////////////
/// Domain definition macro
///////////////////////////////////////////////////////////////////////////////////////////////////
#define REACTIVE_DOMAIN(name, ...)                                                          \
    struct name :                                                                           \
        public REACT_IMPL::DomainBase> {};    \
    REACT_IMPL::DomainInitializer name ## _initializer_;

///////////////////////////////////////////////////////////////////////////////////////////////////
/// Define type aliases for given domain
///////////////////////////////////////////////////////////////////////////////////////////////////
#define USING_REACTIVE_DOMAIN(name)                                                         \
    template                                                                    \
    using SignalT = Signal;                                                         \
                                                                                            \
    template                                                                    \
    using VarSignalT = VarSignal;                                                   \
                                                                                            \
    template                                                            \
    using EventsT = Events;                                                         \
                                                                                            \
    template                                                            \
    using EventSourceT = EventSource;                                               \
                                                                                            \
    using ObserverT = Observer;                                                       \
                                                                                            \
    using ScopedObserverT = ScopedObserver;                                           \
                                                                                            \
    using ReactorT = Reactor;

#endif // REACT_DOMAIN_H_INCLUDED

Web Proxy Viewer  |  New URL  |  Original Page