CleanerSlave SourceΒΆ

//  This file is part of KLayoutPhotonicPCells, an extension for Photonic Layouts in KLayout.
//  Copyright (c) 2018, Sebastian Goeldi
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Affero General Public License as
//    published by the Free Software Foundation, either version 3 of the
//    License, or (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the GNU Affero General Public License
//    along with this program.  If not, see <https://www.gnu.org/licenses/>.

#include "CleanerSlave.h"


namespace drclean
{
CleanerSlave::CleanerSlave()
{
    segment = new bi::managed_shared_memory(bi::open_only, "DRCleanEngine");
    
    std::cout<< "Initializing" << std::endl;

    alloc_inst = new ShmemAllocatorInt(segment->get_segment_manager());
    alloc_vec = new ShmemAllocatorIVec(segment->get_segment_manager());
    alloc_pvec = new ShmemAllocatorPVec(segment->get_segment_manager());
    alloc_poly = new ShmemAllocatorPair(segment->get_segment_manager());

    input = segment->find<ShIVector>("input").first;
    outList = segment->find<ShIVector>("outList").first;

    mux_inp = new bi::named_mutex(bi::open_only, "mux_inp");
    mux_out = new bi::named_mutex(bi::open_only, "mux_out");

    pool = new boost::asio::thread_pool(boost::thread::hardware_concurrency());

    if (input)
    {
        initialized = true;
    }
}

CleanerSlave::CleanerSlave(int nthreads)
{
    segment = new bi::managed_shared_memory(bi::open_only, "DRCleanEngine");
    
    std::cout<< "Initializing" << std::endl;

    alloc_inst = new ShmemAllocatorInt(segment->get_segment_manager());
    alloc_vec = new ShmemAllocatorIVec(segment->get_segment_manager());
    alloc_pvec = new ShmemAllocatorPVec(segment->get_segment_manager());
    alloc_poly = new ShmemAllocatorPair(segment->get_segment_manager());

    input = segment->find<ShIVector>("input").first;
    outList = segment->find<ShIVector>("outList").first;

    mux_inp = new bi::named_mutex(bi::open_only, "mux_inp");
    mux_out = new bi::named_mutex(bi::open_only, "mux_out");
    
    int n = nthreads;
    
    if(n < 1)
    {
        n = 1;
    } else if (n >  boost::thread::hardware_concurrency()) {
        n = boost::thread::hardware_concurrency();
    }

    pool = new boost::asio::thread_pool(n);

    if (input)
    {
        initialized = true;
    }
}

CleanerSlave::~CleanerSlave()
{
    join_threads();
    delete alloc_inst;
    delete pool;
}

void CleanerSlave::clean()
{
    std::vector<int> *inp = new std::vector<int>();
    mux_inp->lock();
    if(!input->empty())
    {
        bi::vector<int, ShmemAllocatorInt>::iterator it;
        for(it = input->begin(); it != input->end(); it++)
        {
            inp->push_back(*it);
        }
        input->clear();
        mux_inp->unlock();
    }
    else
    {
        mux_inp->unlock();
        delete inp;

        std::this_thread::sleep_for(std::chrono::milliseconds(30));
        return;
    }

    boost::asio::post(*pool,boost::bind(&CleanerSlave::threaded_DrcSl,this,inp));
//        threaded_DrcSl(inp); //For single thread calculation
}

void CleanerSlave::threaded_DrcSl(std::vector<int> *inp)
{
    int layer;
    int datatype;

    DrcSl sl;
    std::vector<int>::iterator iter = inp->begin();

    if(iter!=inp->end())
    {
        layer = *(iter++);
        datatype = *(iter++);
        sl.initialize_list(*(iter),*(iter+1),*(iter+2),*(iter+3),*(iter+4),*(iter+5));
        // The first six datapoints are size (x1,x2,y1,y2) and layer, datatype information.
        int count = 6;
        iter+=6;
        while(iter!=inp->end())
        {
            count +=4;
            sl.add_data(*(iter),*(iter+1),*(iter+2),*(iter+3));
            iter+=4;
        }
    }
    else
    {
        delete inp;
        return;
    }

    delete inp;
    sl.sortlist();
    sl.clean();
    std::string layername = std::to_string(layer) + "/" + std::to_string(datatype);

    std::vector<std::vector<pi>> polys = sl.get_polygons();

    ShPVVector* polygons = segment->construct<ShPVVector>(layername.data())(*alloc_pvec);

    for(auto p: polys)
    {
        ShPVector* poly = segment->construct<ShPVector>(bi::anonymous_instance) (*alloc_poly);
        for(auto pit: p)
        {
            poly->push_back(pit);
        }
        polygons->push_back(boost::move(*poly));
    }
    mux_out->lock();
    outList->push_back(layer);
    outList->push_back(datatype);
    mux_out->unlock();

}

void CleanerSlave::join_threads()
{
    pool->join();
}

};