Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/graph/example/file_dependencies.cpp @ 30

Last change on this file since 30 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 5.7 KB
Line 
1//=======================================================================
2// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
3// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
4//
5// Distributed under the Boost Software License, Version 1.0. (See
6// accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//=======================================================================
9
10// Some small modifications are done by Alexander Holler
11
12/*
13
14  Paul Moore's request:
15
16  As an example of a practical problem which is not restricted to graph
17  "experts", consider file dependencies. It's basically graph construction,
18  plus topological sort, but it might make a nice "tutorial" example. Build a
19  dependency graph of files, then use the algorithms to do things like
20
21  1. Produce a full recompilation order (topological sort, by modified date)
22  2. Produce a "parallel" recompilation order (same as above, but group files
23  which can be built in parallel)
24  3. Change analysis (if I change file x, which others need recompiling)
25  4. Dependency changes (if I add a dependency between file x and file y, what
26  are the effects)
27
28*/
29
30#include <boost/config.hpp> // put this first to suppress some VC++ warnings
31
32#include <iostream>
33#include <iterator>
34#include <algorithm>
35#include <time.h>
36
37#include <boost/utility.hpp>
38#include <boost/graph/adjacency_list.hpp>
39#include <boost/graph/topological_sort.hpp>
40#include <boost/graph/depth_first_search.hpp>
41#include <boost/graph/dijkstra_shortest_paths.hpp>
42#include <boost/graph/visitors.hpp>
43
44using namespace std;
45using namespace boost;
46
47enum files_e { dax_h, yow_h, boz_h, zow_h, foo_cpp, 
48               foo_o, bar_cpp, bar_o, libfoobar_a,
49               zig_cpp, zig_o, zag_cpp, zag_o, 
50                 libzigzag_a, killerapp, N };
51const char* name[] = { "dax.h", "yow.h", "boz.h", "zow.h", "foo.cpp",
52                       "foo.o", "bar.cpp", "bar.o", "libfoobar.a",
53                       "zig.cpp", "zig.o", "zag.cpp", "zag.o",
54                       "libzigzag.a", "killerapp" };
55
56
57struct print_visitor : public bfs_visitor<> {
58  template <class Vertex, class Graph>
59  void discover_vertex(Vertex v, Graph&) {
60    cout << name[v] << " ";
61  }
62};
63
64
65struct cycle_detector : public dfs_visitor<>
66{
67  cycle_detector(bool& has_cycle) 
68    : m_has_cycle(has_cycle) { }
69
70  template <class Edge, class Graph>
71  void back_edge(Edge, Graph&) { m_has_cycle = true; }
72protected:
73  bool& m_has_cycle;
74};
75
76
77
78
79int main(int,char*[])
80{
81
82  typedef pair<int,int> Edge;
83  Edge used_by[] = {
84    Edge(dax_h, foo_cpp), Edge(dax_h, bar_cpp), Edge(dax_h, yow_h),
85    Edge(yow_h, bar_cpp), Edge(yow_h, zag_cpp),
86    Edge(boz_h, bar_cpp), Edge(boz_h, zig_cpp), Edge(boz_h, zag_cpp),
87    Edge(zow_h, foo_cpp), 
88    Edge(foo_cpp, foo_o),
89    Edge(foo_o, libfoobar_a),
90    Edge(bar_cpp, bar_o),
91    Edge(bar_o, libfoobar_a),
92    Edge(libfoobar_a, libzigzag_a),
93    Edge(zig_cpp, zig_o),
94    Edge(zig_o, libzigzag_a),
95    Edge(zag_cpp, zag_o),
96    Edge(zag_o, libzigzag_a),
97    Edge(libzigzag_a, killerapp)
98  };
99  const std::size_t nedges = sizeof(used_by)/sizeof(Edge);
100
101  typedef adjacency_list<vecS, vecS, bidirectionalS> Graph;
102#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
103  // VC++ can't handle the iterator constructor
104  Graph g(N);
105  for (std::size_t j = 0; j < nedges; ++j) {
106    graph_traits<Graph>::edge_descriptor e; bool inserted;
107    tie(e, inserted) = add_edge(used_by[j].first, used_by[j].second, g);
108  }
109#else
110  Graph g(used_by, used_by + nedges, N);
111#endif
112  typedef graph_traits<Graph>::vertex_descriptor Vertex;
113
114  // Determine ordering for a full recompilation
115  // and the order with files that can be compiled in parallel
116  {
117    typedef list<Vertex> MakeOrder;
118    MakeOrder::iterator i;
119    MakeOrder make_order;
120
121    topological_sort(g, std::front_inserter(make_order));
122    cout << "make ordering: ";
123    for (i = make_order.begin();
124         i != make_order.end(); ++i) 
125      cout << name[*i] << " ";
126 
127    cout << endl << endl;
128
129    // Parallel compilation ordering
130    std::vector<int> time(N, 0);
131    for (i = make_order.begin(); i != make_order.end(); ++i) {   
132      // Walk through the in_edges an calculate the maximum time.
133      if (in_degree (*i, g) > 0) {
134        Graph::in_edge_iterator j, j_end;
135        int maxdist=0;
136        // Through the order from topological sort, we are sure that every
137        // time we are using here is already initialized.
138        for (tie(j, j_end) = in_edges(*i, g); j != j_end; ++j)
139          maxdist=std::max(time[source(*j, g)], maxdist);
140        time[*i]=maxdist+1;
141      }
142    }
143
144    cout << "parallel make ordering, " << endl
145         << "vertices with same group number can be made in parallel" << endl;
146    {
147      graph_traits<Graph>::vertex_iterator i, iend;
148      for (tie(i,iend) = vertices(g); i != iend; ++i)
149        cout << "time_slot[" << name[*i] << "] = " << time[*i] << endl;
150    }
151
152  }
153  cout << endl;
154
155  // if I change yow.h what files need to be re-made?
156  {
157    cout << "A change to yow.h will cause what to be re-made?" << endl;
158    print_visitor vis;
159    breadth_first_search(g, vertex(yow_h, g), visitor(vis));
160    cout << endl;
161  }
162  cout << endl;
163
164  // are there any cycles in the graph?
165  {
166    bool has_cycle = false;
167    cycle_detector vis(has_cycle);
168    depth_first_search(g, visitor(vis));
169    cout << "The graph has a cycle? " << has_cycle << endl;
170  }
171  cout << endl;
172
173  // add a dependency going from bar.cpp to dax.h
174  {
175    cout << "adding edge bar_cpp -> dax_h" << endl;
176    add_edge(bar_cpp, dax_h, g);
177  }
178  cout << endl;
179
180  // are there any cycles in the graph?
181  {
182    bool has_cycle = false;
183    cycle_detector vis(has_cycle);
184    depth_first_search(g, visitor(vis));
185    cout << "The graph has a cycle now? " << has_cycle << endl;
186  }
187
188  return 0;
189}
Note: See TracBrowser for help on using the repository browser.