erikzenker / ClangActiveObjectGenerator

Clang active object generator is a clang plugin for C++ code which generates an active object from a pure virtual class. An active object is a design pattern which decouples method execution from method invocation for objects that each reside in their own thread of control.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Clang Active Object Generator

Clang active object generator is a clang plugin for C++ code which generates an active object from a pure virtual class. An active object is a design pattern which decouples method execution from method invocation for objects that each reside in their own thread of control.

active object

Usage

  1. Install the clang active object generator (see Build Plugin)

  2. You need a header file with a pure virtual class inside e.g.: IPureVirtualClass.hpp.

    #pragma once
    
    class IPureVirtualClass {
    public:
        virtual ~IPureVirtualClass() = default;
        virtual void foo(int a) = 0;
    };
  3. Call the generator script with the header file name and the interface name. The script will print a generated interface implementation using the active object pattern to standard out.

    clang-active-object-generator.sh IPureVirtualClass.hpp IPureVirtualClass \
        > IPureVirtualClassActiveObject.hpp
    
  4. The generator script will create an active object header file for you e.g.:

    #pragma once
    /*
     * This file was generated by the ClangActiveObjectGenerator
     */
    
    #include "IPureVirtualClass.hpp"
    #include <boost/asio/io_service.hpp>
    #include <memory>
    
    class IPureVirtualClassActiveObject : public IPureVirtualClass {
    public:
      IPureVirtualClassActiveObject(const std::shared_ptr<IPureVirtualClass>& impl, boost::asio::io_service& ioService)
          : m_impl(impl)
          , m_ioService(ioService)
      {
      }
    
    public: // IPureVirtualClass
        void foo(int a) override {
            m_ioService.post(
                [this, a](){
                    m_impl.lock()->foo(a);
                });
        }
    
    
    private:
       std::weak_ptr<IPureVirtualClass> m_impl;
       boost::asio::io_service& m_ioService;
    };
    
    #ifndef MAKE_ACTIVE_OBJECT
    #define MAKE_ACTIVE_OBJECT
    template <class TInterface, class TExecutor>
    class MakeActiveObject {};
    
    template <class TInterface, class TExecutor>
    std::unique_ptr<TInterface>
    make_active_object(const std::shared_ptr<TInterface>& impl, const std::shared_ptr<TExecutor>& executor)
    {
        return MakeActiveObject<TInterface, TExecutor>{}(impl, executor);
    }
    #endif
    
    template <class TExecutor>
    class MakeActiveObject<ICalculator, TExecutor> {
    public:
        std::unique_ptr<IPureVirtualClass> operator()(const std::shared_ptr<IPureVirtualClass>& impl, const std::shared_ptr<TExecutor>& executor){
                return std::make_unique<IPureVirtualClassActiveObject<TExecutor>>(impl, executor);
        }
    };
  5. Finally, include the generated active object header into your sources and call methods on the active object

    #include "IPureVirtualClass.hpp"             // <-- original interface header
    #include "IPureVirtualClassActiveObject.hpp" // <-- generated active object header
    
    #include <boost/asio.hpp>
    #include <thread>
    #include <iostream>
    
    class Impl : public IPureVirtualClass {
        void foo(int a){
            std::cout << a << std::endl;
        }
    }
    
    int main()
    {
        // Thread loop in which the active object method calls will be executed
        auto ioService = std::make_shared<boost::asio::io_service>();
     
        // The implementation of the interface
        auto impl = std::make_shared<Impl>();
        
        // Generates the active object 
        auto implActiveObject = make_active_object<IPureVirtualClass>(impl, ioService);
        
        // Puts the method call into the thread loop
        implActiveObject->foo(42);
    
        // Executes the method call (prints 42)
        std::thread t0([ioService]() { ioService->run(); });
        t0.join();
    
        return 0;
    }

Build Plugin

mkdir build; cd build
cmake ..
cmake --build . --target install

Build Example

Build the plugin in advance

mkdir build; cd build
cmake ..
cmake --build . --target clang_active_object_generator_example
./example/clang_active_object_generator_example

Dependencies

  • C++14
  • llvm 6.0.1-4
  • clang 6.0.1-2

License

MIT

Author

Written by Erik Zenker (erikzenker (at) hotmail.com)

About

Clang active object generator is a clang plugin for C++ code which generates an active object from a pure virtual class. An active object is a design pattern which decouples method execution from method invocation for objects that each reside in their own thread of control.


Languages

Language:C++ 50.2%Language:CMake 40.2%Language:HTML 5.5%Language:Shell 4.1%