Skip to content

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.

Notifications You must be signed in to change notification settings

erikzenker/ClangActiveObjectGenerator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published