<commit_before>/**
 * Copyright (C) 2016 <NAME> (https://github.com/eXistence/TeeTime-Cpp)
 *
 * 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.
 */
#pragma once
#include "stages/AbstractStage.h"
#include "pipes/SpscValueQueue.h"
#include "pipes/SynchedPipe.h"
#include "pipes/UnsynchedPipe.h"
#include <map>
#include <set>
#include <type_traits>
namespace teetime
{
  //forward declarations:

  template<typename TIn, typename TOut, TOut(*TFunc)(TIn)>
  class FunctionStage;

  template<typename TIn, typename TOut>
  class FunctionPtrStage;

  template<typename TIn, typename TOut>
  class FunctionObjectStage;

  template<typename TIn, typename TOut>
  class NewFunctionStage;

namespace internal
{
  template <typename T>
  struct function_traits
    : public function_traits<decltype(&T::operator())>
  {};

  template <typename ClassType, typename ReturnType, typename Arg>
  struct function_traits<ReturnType(ClassType::*)(Arg) const>
  {
    using result_type = ReturnType;
    using arg_type = Arg;
  };

  template <typename ClassType, typename ReturnType, typename Arg>
  struct function_traits<ReturnType(ClassType::*)(Arg)>
  {
    using result_type = ReturnType;
    using arg_type = Arg;
  };

  using CreatePipeCallback = void*(size_t capacity, bool synched);
  using ConnectCallback = void(AbstractOutputPort* out, AbstractInputPort* in, size_t capacity, bool synched);

  template<typename T>
  void connectPortsCallback(AbstractOutputPort* out, AbstractInputPort* in, size_t capacity, bool synched)
  {
    auto typed_out = unsafe_dynamic_cast<OutputPort<T>>(out);
    auto typed_in = unsafe_dynamic_cast<InputPort<T>>(in);

    if (synched)
    {
      typed_out->m_pipe.reset(new SynchedPipe<T, SpscValueQueue>((uint32)capacity));
    }
    else
    {
      typed_out->m_pipe.reset(new UnsynchedPipe<T>(typed_in->owner()));
    }

    typed_in->m_pipe = typed_out->m_pipe.get();
  }
}
  
  /**
   * A configuration.
   * Derive your P&F configuration from this class.
   * Create your stages in the constructor of that class and connect 
   * them by 'connectPorts' and declare at least one stage active with
   * 'declareStageActive'.
   * 
   * execute the configuration with 'executeBlocking()';
   */
  class Configuration
  {
  public:
    Configuration();
    virtual ~Configuration();

    //no copy construction, no assignment
    Configuration(const Configuration&) = delete;
    Configuration& operator=(const Configuration&) = delete;

    /**
     * execute configuration. Blocks while configuration is executing.
     */
    void executeBlocking();

  protected:
    //create arbitrary stage
    template<typename T, typename ...TArgs>
    static shared_ptr<T> createStage(TArgs... args)
    {
      auto stage = std::make_shared<T>(args...);
      return stage;
    }

    /**
     * Create a stage from a lambda. Lambda must take one argument (stage input) and must
     * return one element (stage output).
     */
    //jesus! this is just ugly as hell... but it get's the job done (most of the time)
    template<typename T>
    static auto createStageFromLambda(T lambda, const char* debugName = "lambda_stage")
      ->shared_ptr<FunctionObjectStage<typename teetime::internal::function_traits<T>::arg_type,
      typename teetime::internal::function_traits<T>::result_type>>
    {
      using TOut = typename teetime::internal::function_traits<T>::result_type;
      using TIn = typename teetime::internal::function_traits<T>::arg_type;
      return createStage<FunctionObjectStage<TIn, TOut>>(lambda, debugName);
    }

    /**
     * Create a stage from a function pointer. Function must take one argument (stage input) and must
     * return one element (stage output).
     */
    template<typename TIn, typename TOut>
    static shared_ptr<NewFunctionStage<TIn, TOut>> createStageFromFunctionPointer(TOut(*f)(TIn), const char* name = "function_pointer")
    {
      return createStage<NewFunctionStage<TIn, TOut>>(f, name);
    }

    /**
     * Create a stage from std::function. Function must take one argument (stage input) and must
     * return one element (stage output).
     */
    template<typename TIn, typename TOut>
    static shared_ptr<FunctionObjectStage<TIn, TOut>> createStageFromFunctionObject(std::function<TOut(TIn)> f, const char* name = "function_object")
    {
      return createStage<FunctionObjectStage<TIn, TOut>>(f, name);
    }
<commit_msg>fixed lambda stages: lambda can take argument by value or by rvalue reference<commit_after>/**
 * Copyright (C) 2016 <NAME> (https://github.com/eXistence/TeeTime-Cpp)
 *
 * 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.
 */
#pragma once
#include "stages/AbstractStage.h"
#include "pipes/SpscValueQueue.h"
#include "pipes/SynchedPipe.h"
#include "pipes/UnsynchedPipe.h"
#include <map>
#include <set>
#include <type_traits>
namespace teetime
{
  //forward declarations:

  template<typename TIn, typename TOut, TOut(*TFunc)(TIn)>
  class FunctionStage;

  template<typename TIn, typename TOut>
  class FunctionPtrStage;

  template<typename TIn, typename TOut>
  class FunctionObjectStage;

  template<typename TIn, typename TOut>
  class NewFunctionStage;

namespace internal
{
  template <typename T>
  struct function_traits
    : public function_traits<decltype(&T::operator())>
  {};

  template <typename ClassType, typename ReturnType, typename Arg>
  struct function_traits<ReturnType(ClassType::*)(Arg) const>
  {
    using result_type = ReturnType;
    using arg_type = Arg;
  };

  template <typename ClassType, typename ReturnType, typename Arg>
  struct function_traits<ReturnType(ClassType::*)(Arg)>
  {
    using result_type = ReturnType;
    using arg_type = Arg;
  };

  using CreatePipeCallback = void*(size_t capacity, bool synched);
  using ConnectCallback = void(AbstractOutputPort* out, AbstractInputPort* in, size_t capacity, bool synched);

  template<typename T>
  void connectPortsCallback(AbstractOutputPort* out, AbstractInputPort* in, size_t capacity, bool synched)
  {
    auto typed_out = unsafe_dynamic_cast<OutputPort<T>>(out);
    auto typed_in = unsafe_dynamic_cast<InputPort<T>>(in);

    if (synched)
    {
      typed_out->m_pipe.reset(new SynchedPipe<T, SpscValueQueue>((uint32)capacity));
    }
    else
    {
      typed_out->m_pipe.reset(new UnsynchedPipe<T>(typed_in->owner()));
    }

    typed_in->m_pipe = typed_out->m_pipe.get();
  }
}
  
  /**
   * A configuration.
   * Derive your P&F configuration from this class.
   * Create your stages in the constructor of that class and connect 
   * them by 'connectPorts' and declare at least one stage active with
   * 'declareStageActive'.
   * 
   * execute the configuration with 'executeBlocking()';
   */
  class Configuration
  {
  public:
    Configuration();
    virtual ~Configuration();

    //no copy construction, no assignment
    Configuration(const Configuration&) = delete;
    Configuration& operator=(const Configuration&) = delete;

    /**
     * execute configuration. Blocks while configuration is executing.
     */
    void executeBlocking();

  protected:
    //create arbitrary stage
    template<typename T, typename ...TArgs>
    static shared_ptr<T> createStage(TArgs... args)
    {
      auto stage = std::make_shared<T>(args...);
      return stage;
    }

    /**
     * Create a stage from a lambda. Lambda must take one argument (stage input) and must
     * return one element (stage output).
     */
    //jesus! this is just ugly as hell... but it get's the job done (most of the time)
    template<typename T>
    static auto createStageFromLambda(T lambda, const char* debugName = "lambda_stage")
      ->shared_ptr<FunctionObjectStage<typename std::remove_reference<typename teetime::internal::function_traits<T>::arg_type>::type,
      typename teetime::internal::function_traits<T>::result_type>>
    {
      using TOut = typename teetime::internal::function_traits<T>::result_type;
      using TIn = typename std::remove_reference<typename teetime::internal::function_traits<T>::arg_type>::type;
      return createStage<FunctionObjectStage<TIn, TOut>>(lambda, debugName);
    }

    /**
     * Create a stage from a function pointer. Function must take one argument (stage input) and must
     * return one element (stage output).
     */
    template<typename TIn, typename TOut>
    static shared_ptr<NewFunctionStage<TIn, TOut>> createStageFromFunctionPointer(TOut(*f)(TIn), const char* name = "function_pointer")
    {
      return createStage<NewFunctionStage<TIn, TOut>>(f, name);
    }

    /**
     * Create a stage from std::function. Function must take one argument (stage input) and must
     * return one element (stage output).
     */
    template<typename TIn, typename TOut>
    static shared_ptr<FunctionObjectStage<TIn, TOut>> createStageFromFunctionObject(std::function<TOut(TIn)> f, const char* name = "function_object")
    {
      return createStage<FunctionObjectStage<TIn, TOut>>(f, name);
    }

{'fraction_non_alphanumeric': 0.10562675210252302, 'fraction_numerical': 0.002002402883460152, 'mean_word_length': 3.9328395061728396, 'pattern_counts': {'":': 0, '<': 93, '<?xml version=': 0, '>': 105, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1532460', 'n_tokens_mistral': 2971, 'n_tokens_neox': 2874, 'n_words': 872}