Multithreading CGAL 2D正则化布尔集操作库是否线程安全?

Multithreading CGAL 2D正则化布尔集操作库是否线程安全?,multithreading,concurrency,cgal,Multithreading,Concurrency,Cgal,我目前正在使用标题中提到的库,请参阅 该库提供多边形和多边形集的类型,这些类型在内部表示为所谓的排列 我的问题是:这个库在多大程度上是线程安全的,也就是说,适合在其对象上进行并行计算 可以有几个级别来保证线程安全: 1) 如果我从图书馆拿了一件物品 Polygon_set_2 S; 我也许能执行 Polygon_2 P; S.join(P); 及 在两个不同的并发执行单元/线程中并行执行,不会造成任何伤害,并获得正确的结果,就好像我按顺序完成了所有操作一样。这将是线程安全性/可能的并行性的

我目前正在使用标题中提到的库,请参阅

该库提供多边形和多边形集的类型,这些类型在内部表示为所谓的排列

我的问题是:这个库在多大程度上是线程安全的,也就是说,适合在其对象上进行并行计算

可以有几个级别来保证线程安全:

1) 如果我从图书馆拿了一件物品

Polygon_set_2 S;
我也许能执行

Polygon_2 P;
S.join(P);

在两个不同的并发执行单元/线程中并行执行,不会造成任何伤害,并获得正确的结果,就好像我按顺序完成了所有操作一样。这将是线程安全性/可能的并行性的最高级别

2) 事实上,对我来说,一个小得多的学位就足够了。在这种情况下,S和P将是类C的成员,因此两个类实例具有不同的S和P实例。然后,我想并行计算(比如)
S.join(P)
类C的实例列表,比如,通过std::async调用C的合适成员函数

为了完整起见,我在这里插入了我的项目中的一些实际代码,这使这些简洁的描述更加生动

// the following typedefs are more or less standard from the
// CGAL library examples.


typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2                                   Point_2;
typedef Kernel::Circle_2                                  Circle_2;
typedef Kernel::Line_2                                    Line_2;
typedef CGAL::Gps_circle_segment_traits_2<Kernel>         Traits_2;

typedef CGAL::General_polygon_set_2<Traits_2>             Polygon_set_2;
typedef Traits_2::General_polygon_2                       Polygon_2;
typedef Traits_2::General_polygon_with_holes_2            Polygon_with_holes_2;
typedef Traits_2::Curve_2                                 Curve_2;
typedef Traits_2::X_monotone_curve_2                      X_monotone_curve_2;
typedef Traits_2::Point_2                                 Point_2t;
typedef Traits_2::CoordNT                                 coordnt;
typedef CGAL::Arrangement_2<Traits_2>                     Arrangement_2;
typedef Arrangement_2::Face_handle                        Face_handle;

// the following type is not copied from the CGAL library example code but
// introduced by me
typedef std::vector<Polygon_with_holes_2> pwh_vec_t;


// the following is an excerpt of my full GerberLayer class,
// that retains only data members which are used in the join()
// member function. These data is therefore local to the class instance.

class GerberLayer
{
public:

    GerberLayer();
    ~GerberLayer();

    void join();

    pwh_vec_t raw_poly_lis;
    pwh_vec_t joined_poly_lis;

    Polygon_set_2 Saux;

    annotate_vec_t annotate_lis;

    polar_vec_t polar_lis;


};

//
// it is not necessary to understand the working of the function
// I deleted all debug and timing output etc. It is just to "showcase" some typical
// operations from the CGAL reg set boolean ops for polygons library from
// Efi Fogel et.al.
//
void GerberLayer::join()
{

    Saux.clear();

    auto it_annbase = annotate_lis.begin();

    annotate_vec_t::iterator itann = annotate_lis.begin();

    bool first_block = true;

    int cnt = 0;

    while (itann != annotate_lis.end()) {

        gpolarity akt_polar = itann->polar;

        auto itnext = std::find_if(itann, annotate_lis.end(),
                [=](auto a) {return a.polar != akt_polar;});

        Polygon_set_2 Sblock;

        if (first_block) {
            if (akt_polar == Dark) {

                Saux.join(raw_poly_lis.begin() + (itann - it_annbase),
                            raw_poly_lis.begin() + (itnext - it_annbase));
            }
            first_block = false;
        } else {
            if (akt_polar == Dark) {

                Saux.join(raw_poly_lis.begin() + (itann - it_annbase),
                                raw_poly_lis.begin() + (itnext - it_annbase));

            } else {


                Polygon_set_2 Saux1;

                Saux1.join(raw_poly_lis.begin() + (itann - it_annbase),
                                raw_poly_lis.begin() + (itnext - it_annbase));


                Saux.complement();

                pwh_vec_t auxlis;

                Saux1.polygons_with_holes(std::back_inserter(auxlis));

                Saux.join(auxlis.begin(), auxlis.end());

                Saux.complement();

            }
        }

        itann = itnext;
    }

    ende:
    joined_poly_lis.clear();

    annotate_lis.clear();

    Saux.polygons_with_holes (std::back_inserter (joined_poly_lis));

}



int join_wrapper(GerberLayer* p_layer)
{
    p_layer->join();
    return 0;
}

// here the parallelism (of the "embarassing kind") occurs:
// for every GerberLayer a dedicated task is started, which calls
// the above GerberLayer::join() function

void Window::do_unify()
{
    std::vector<std::future<int>> fivec;

    for(int i = 0; i < gerber_layer_manager.num_layers(); ++i) {
        GerberLayer* p_layer = gerber_layer_manager.at(i);

        fivec.push_back(std::async(join_wrapper, p_layer));

    }

    int sz = wait_for_all(fivec); // written by me, not shown

}
//以下typedef或多或少是
//CGAL库示例。
typedef CGAL::精确谓词\u精确构造\u内核;
typedef内核::Point_2 Point_2;
typedef内核::Circle_2 Circle_2;
typedef内核::Line_2 Line_2;
typedef CGAL::Gps_圆_段_特征_2特征_2;
typedef CGAL::General_polygon_set_2 polygon_set_2;
typedef Traits_2::General_polygon_2 polygon_2;
typedef Traits_2::一般多边形带孔多边形带孔多边形;
typedef Traits_2::Curve_2 Curve_2;
typedef特征_2::X_单调_曲线_2 X_单调_曲线_2;
typedef Traits_2::Point_2 Point_2t;
typedef-Traits_2::CoordNT-CoordNT;
typedef CGAL::排列2排列2;
typedef排列_2::面_柄面_柄;
//以下类型不是从CGAL库示例代码复制的,而是
//我介绍的
typedef std::vector pwh_vec_t;
//以下是我整个GerberLayer课程的摘录,
//仅保留联接()中使用的数据成员的
//成员函数。因此,这些数据是类实例的本地数据。
GerberLayer类
{
公众:
GerberLayer();
~GerberLayer();
void join();
原始塑料;
普华永道加入保利集团;
多边形集合2;
注释(vec)t注释(lis);;
极坐标向量极坐标;
};
//
//无需了解函数的工作原理
//我删除了所有调试和定时输出等。这只是为了“展示”一些典型的
//来自CGAL reg集合的多边形布尔运算库的操作来自
//Efi Fogel等人。
//
void GerberLayer::join()
{
Saux.clear();
auto it_annbase=注释_lis.begin();
annotate_vec_t::迭代器Itan=annotate_lis.begin();
bool first_block=true;
int-cnt=0;
while(Itan!=注释_lis.end()){
G极性akt_polar=Itan->polar;
auto itnext=std::find_if(Itan,annotate_lis.end(),
[=](自动a){返回a.polar!=akt_polar;});
多边形集合2块;
如果(第一块){
如果(akt_polar==暗){
Saux.join(raw_poly_lis.begin()+(itann-it_annbase),
原始poly_lis.begin()+(itnext-it_annbase));
}
第一块=假;
}否则{
如果(akt_polar==暗){
Saux.join(raw_poly_lis.begin()+(itann-it_annbase),
原始poly_lis.begin()+(itnext-it_annbase));
}否则{
多边形集合2;
Saux1.join(raw_poly_lis.begin()+(itann-it_annbase),
原始poly_lis.begin()+(itnext-it_annbase));
Saux.complement();
公共交通工具;
带孔的多边形(标准::背面插入器(auxlis));
join(auxlis.begin(),auxlis.end());
Saux.complement();
}
}
Itan=itnext;
}
恩德:
已连接的多边形透明();
注释_lis.clear();
带孔的Saux.polygons_(标准:背面插入器(连接的poly_lis));
}
int join_包装(GerberLayer*p_层)
{
p_层->连接();
返回0;
}
//这里出现了平行性(即“禁运类型”):
//对于每个GerberLayer,都会启动一个专用任务,该任务调用
//上面的GerberLayer::join()函数
void Window::do_unified()
{
std::向量fivec;
对于(int i=0;i
有人可能会认为,2)必须是可能的,因为游戏中只有多边形和排列的“不同”实例。但是:可以想象,由于库使用任意精度点(
Point_2t
,在我上面的代码中),出于某种实现原因或其他原因,所有点都被插入到类Point_2t的静态列表中,因此相同的点在该列表中只表示一次。因此,不会有“点2t的独立实例”,因此也不会有“多边形2”或“多边形集2”,人们可以告别线程安全

我试图通过谷歌搜索来解决这个问题(我必须承认,不是通过分析库代码),并希望得到一个权威的答案(希望是肯定的,因为这个原始的并行性)
// the following typedefs are more or less standard from the
// CGAL library examples.


typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2                                   Point_2;
typedef Kernel::Circle_2                                  Circle_2;
typedef Kernel::Line_2                                    Line_2;
typedef CGAL::Gps_circle_segment_traits_2<Kernel>         Traits_2;

typedef CGAL::General_polygon_set_2<Traits_2>             Polygon_set_2;
typedef Traits_2::General_polygon_2                       Polygon_2;
typedef Traits_2::General_polygon_with_holes_2            Polygon_with_holes_2;
typedef Traits_2::Curve_2                                 Curve_2;
typedef Traits_2::X_monotone_curve_2                      X_monotone_curve_2;
typedef Traits_2::Point_2                                 Point_2t;
typedef Traits_2::CoordNT                                 coordnt;
typedef CGAL::Arrangement_2<Traits_2>                     Arrangement_2;
typedef Arrangement_2::Face_handle                        Face_handle;

// the following type is not copied from the CGAL library example code but
// introduced by me
typedef std::vector<Polygon_with_holes_2> pwh_vec_t;


// the following is an excerpt of my full GerberLayer class,
// that retains only data members which are used in the join()
// member function. These data is therefore local to the class instance.

class GerberLayer
{
public:

    GerberLayer();
    ~GerberLayer();

    void join();

    pwh_vec_t raw_poly_lis;
    pwh_vec_t joined_poly_lis;

    Polygon_set_2 Saux;

    annotate_vec_t annotate_lis;

    polar_vec_t polar_lis;


};

//
// it is not necessary to understand the working of the function
// I deleted all debug and timing output etc. It is just to "showcase" some typical
// operations from the CGAL reg set boolean ops for polygons library from
// Efi Fogel et.al.
//
void GerberLayer::join()
{

    Saux.clear();

    auto it_annbase = annotate_lis.begin();

    annotate_vec_t::iterator itann = annotate_lis.begin();

    bool first_block = true;

    int cnt = 0;

    while (itann != annotate_lis.end()) {

        gpolarity akt_polar = itann->polar;

        auto itnext = std::find_if(itann, annotate_lis.end(),
                [=](auto a) {return a.polar != akt_polar;});

        Polygon_set_2 Sblock;

        if (first_block) {
            if (akt_polar == Dark) {

                Saux.join(raw_poly_lis.begin() + (itann - it_annbase),
                            raw_poly_lis.begin() + (itnext - it_annbase));
            }
            first_block = false;
        } else {
            if (akt_polar == Dark) {

                Saux.join(raw_poly_lis.begin() + (itann - it_annbase),
                                raw_poly_lis.begin() + (itnext - it_annbase));

            } else {


                Polygon_set_2 Saux1;

                Saux1.join(raw_poly_lis.begin() + (itann - it_annbase),
                                raw_poly_lis.begin() + (itnext - it_annbase));


                Saux.complement();

                pwh_vec_t auxlis;

                Saux1.polygons_with_holes(std::back_inserter(auxlis));

                Saux.join(auxlis.begin(), auxlis.end());

                Saux.complement();

            }
        }

        itann = itnext;
    }

    ende:
    joined_poly_lis.clear();

    annotate_lis.clear();

    Saux.polygons_with_holes (std::back_inserter (joined_poly_lis));

}



int join_wrapper(GerberLayer* p_layer)
{
    p_layer->join();
    return 0;
}

// here the parallelism (of the "embarassing kind") occurs:
// for every GerberLayer a dedicated task is started, which calls
// the above GerberLayer::join() function

void Window::do_unify()
{
    std::vector<std::future<int>> fivec;

    for(int i = 0; i < gerber_layer_manager.num_layers(); ++i) {
        GerberLayer* p_layer = gerber_layer_manager.at(i);

        fivec.push_back(std::async(join_wrapper, p_layer));

    }

    int sz = wait_for_all(fivec); // written by me, not shown

}