Line data Source code
1 : /*
2 : * segregate.cpp
3 : *
4 : * Created on: 14 Jun 2016
5 : * Author: Leonidas Georgopoulos
6 : */
7 :
8 : #include "dbe/segregate.hpp"
9 : #include "dbe/dbcontroller.hpp"
10 :
11 : #include <boost/graph/connected_components.hpp>
12 : #include <boost/graph/filtered_graph.hpp>
13 :
14 : #include <array>
15 : #include <future>
16 :
17 : #define GTOOL_MAX_THREADS 10
18 :
19 : namespace dbe
20 : {
21 : namespace tool
22 : {
23 : namespace graph
24 : {
25 :
26 0 : segregated_graph_write::segregated_graph_write ( std::string const & oprfx,
27 : size_t const minc,
28 0 : size_t const maxc )
29 : :
30 0 : this_dest_prefix ( oprfx ),
31 0 : this_min_component_size ( minc ),
32 0 : this_max_component_size ( maxc )
33 : {
34 0 : }
35 :
36 0 : int segregated_graph_write::operator () ( gtool const & tool ) const
37 : {
38 0 : typedef long unsigned int t_int;
39 0 : gtool::t_graph const & G = tool.getgraph();
40 0 : std::vector<t_int> compindices ( boost::num_vertices ( G ) );
41 0 : t_int total_connected = boost::connected_components ( G, &compindices[0] );
42 :
43 0 : std::vector<gtool::t_graph> components ( total_connected );
44 0 : std::vector<gtool::t_registry> component_registries ( total_connected );
45 :
46 : // Build the components as seperate graphs
47 0 : for ( t_int vector_i = 0; vector_i != compindices.size(); ++vector_i )
48 : {
49 0 : t_int component_j = compindices[vector_i];
50 0 : std::string oname = boost::get ( >ool::vertex_label::uid, G ) [vector_i];
51 0 : std::string cname = boost::get ( >ool::vertex_label::cname, G ) [vector_i];
52 0 : gtool::add_object_and_friends (
53 0 : components[component_j],
54 0 : dbe::inner::dbcontroller::get (
55 : { oname, cname } ),
56 0 : component_registries[component_j] );
57 0 : }
58 :
59 : // from the graphs built output only those that are within the range specified
60 :
61 0 : int max_punits = GTOOL_MAX_THREADS;
62 :
63 0 : std::vector<std::future<void>> punits;
64 :
65 0 : unsigned long long int c = 0;
66 :
67 0 : for ( auto const & g : components )
68 : {
69 0 : size_t const component_size = g.vertex_set().size();
70 :
71 0 : if ( component_size > this_min_component_size
72 0 : and component_size < this_max_component_size )
73 : {
74 0 : if ( --max_punits )
75 : {
76 0 : std::string output_file
77 0 : { this_dest_prefix + std::string ( "_" ) + std::to_string ( ++c ) + std::string ( ".dot" ) };
78 :
79 0 : try
80 : {
81 0 : punits.push_back ( std::async ( std::launch::async, graph::write, g, output_file ) );
82 : }
83 0 : catch ( std::system_error const & e )
84 : {
85 0 : if ( e.code() == std::errc::resource_unavailable_try_again )
86 : {
87 :
88 0 : ERROR (
89 : "Could not launch another thread", e.what(), "for file:", output_file,
90 0 : "try to launch in deferred" );
91 :
92 0 : punits.push_back (
93 0 : std::async ( std::launch::deferred, graph::write, g, output_file ) );
94 :
95 0 : WARN (
96 : "File write policy change", "Program execution correction", " for file:",
97 0 : output_file, " launched in deferred" );
98 :
99 : }
100 : else
101 : {
102 0 : throw e;
103 : }
104 0 : }
105 0 : }
106 : else
107 : {
108 : // The standard dictates ( C++11 ) that wait is called on the destructor
109 : // and the futures launched are either async or defered, which puts them
110 : // always in a valid state. All that is needed to do is clear the vector
111 : // of futures to initiate calling the destructors.
112 0 : punits.clear();
113 0 : max_punits = GTOOL_MAX_THREADS;
114 : }
115 : }
116 : }
117 :
118 0 : return EXIT_SUCCESS;
119 0 : }
120 :
121 : } /* namespace graph */
122 : } /* namespace tool */
123 : } /* namespace dbe */
|