1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    CHRouterWrapper.h
11 /// @author  Jakob Erdmann
12 /// @author  Laura Bieker
13 /// @author  Michael Behrisch
14 /// @date    March 2012
15 /// @version $Id$
16 ///
17 // Wraps multiple CHRouters for different vehicle types
18 /****************************************************************************/
19 #ifndef CHRouterWrapper_h
20 #define CHRouterWrapper_h
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27 
28 #include <string>
29 #include <functional>
30 #include <vector>
31 #include <set>
32 #include <limits>
33 #include <algorithm>
34 #include <iterator>
35 #include <utils/common/SysUtils.h>
36 #include <utils/common/MsgHandler.h>
37 #include <utils/common/StdDefs.h>
38 #include <utils/router/SUMOAbstractRouter.h>
39 #include <utils/common/SUMOVehicleClass.h>
40 #include "CHRouter.h"
41 
42 #ifdef HAVE_FOX
43 #include <utils/foxtools/FXWorkerThread.h>
44 #endif
45 
46 
47 // ===========================================================================
48 // class definitions
49 // ===========================================================================
50 /**
51  * @class CHRouterWrapper
52  * @brief Computes the shortest path through a contracted network
53  *
54  * The template parameters are:
55  * @param E The edge class to use (MSEdge/ROEdge)
56  * @param V The vehicle class to use (MSVehicle/ROVehicle)
57  * @param PF The prohibition function to use (prohibited_withPermissions/noProhibitions)
58  *
59  * The router is edge-based. It must know the number of edges for internal reasons
60  *  and whether a missing connection between two given edges (unbuild route) shall
61  *  be reported as an error or as a warning.
62  *
63  */
64 template<class E, class V, class BASE>
65 class CHRouterWrapper: public BASE {
66 
67 public:
68     /// Type of the function that is used to retrieve the edge effort.
69     typedef double(* Operation)(const E* const, const V* const, double);
70 
71     /** @brief Constructor
72      */
CHRouterWrapper(const std::vector<E * > & edges,const bool ignoreErrors,typename BASE::Operation operation,const SUMOTime begin,const SUMOTime end,const SUMOTime weightPeriod,const int numThreads)73     CHRouterWrapper(const std::vector<E*>& edges, const bool ignoreErrors, typename BASE::Operation operation,
74                     const SUMOTime begin, const SUMOTime end, const SUMOTime weightPeriod, const int numThreads) :
75         BASE("CHRouterWrapper", ignoreErrors, operation),
76         myEdges(edges),
77         myIgnoreErrors(ignoreErrors),
78         myBegin(begin),
79         myEnd(end),
80         myWeightPeriod(weightPeriod),
81         myMaxNumInstances(numThreads) {
82     }
83 
~CHRouterWrapper()84     ~CHRouterWrapper() {
85         for (typename RouterMap::iterator i = myRouters.begin(); i != myRouters.end(); ++i) {
86             for (typename std::vector<CHRouterType*>::iterator j = i->second.begin(); j != i->second.end(); ++j) {
87                 delete *j;
88             }
89         }
90     }
91 
92 
clone()93     virtual SUMOAbstractRouter<E, V>* clone() {
94         CHRouterWrapper<E, V, BASE>* clone = new CHRouterWrapper<E, V, BASE>(myEdges, myIgnoreErrors, this->myOperation, myBegin, myEnd, myWeightPeriod, myMaxNumInstances);
95         for (typename RouterMap::iterator i = myRouters.begin(); i != myRouters.end(); ++i) {
96             for (typename std::vector<CHRouterType*>::iterator j = i->second.begin(); j != i->second.end(); ++j) {
97                 clone->myRouters[i->first].push_back(static_cast<CHRouterType*>((*j)->clone()));
98             }
99         }
100         return clone;
101     }
102 
103 
104     bool compute(const E* from, const E* to, const V* const vehicle,
105                  SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
106         const std::pair<const SUMOVehicleClass, const double> svc = std::make_pair(vehicle->getVClass(), vehicle->getMaxSpeed());
107         int index = 0;
108         int numIntervals = 1;
109 #ifdef HAVE_FOX
110         if (myMaxNumInstances >= 2 && myEnd < std::numeric_limits<int>::max()) {
111             index = (int)((msTime - myBegin) / myWeightPeriod);
112             numIntervals = (int)((myEnd - myBegin) / myWeightPeriod);
113             if (numIntervals > 0) {
114                 while ((int)myThreadPool.size() < myMaxNumInstances) {
115                     new FXWorkerThread(myThreadPool);
116                 }
117             } else {
118                 // this covers the cases of negative (unset) end time and unset weight period (no weight file)
119                 numIntervals = 1;
120             }
121         }
122 #endif
123         if (myRouters.count(svc) == 0) {
124             // create new router for the given permissions and maximum speed
125             // XXX a new router may also be needed if vehicles differ in speed factor
126             for (int i = 0; i < numIntervals; i++) {
127                 myRouters[svc].push_back(new CHRouterType(
128                                              myEdges, myIgnoreErrors, &E::getTravelTimeStatic, svc.first, myWeightPeriod, false));
129 #ifdef HAVE_FOX
130                 if (myThreadPool.size() > 0) {
131                     myThreadPool.add(new ComputeHierarchyTask(myRouters[svc].back(), vehicle, myBegin + i * myWeightPeriod));
132                 }
133 #endif
134             }
135 #ifdef HAVE_FOX
136             if (myThreadPool.size() > 0) {
137                 myThreadPool.waitAll();
138             }
139 #endif
140         }
141         return myRouters[svc][index]->compute(from, to, vehicle, msTime, into, silent);
142     }
143 
144 
145 private:
146     typedef CHRouter<E, V, SUMOAbstractRouter<E, V> > CHRouterType;
147 
148 #ifdef HAVE_FOX
149 private:
150     class ComputeHierarchyTask : public FXWorkerThread::Task {
151     public:
ComputeHierarchyTask(CHRouterType * router,const V * const vehicle,const SUMOTime msTime)152         ComputeHierarchyTask(CHRouterType* router, const V* const vehicle, const SUMOTime msTime)
153             : myRouter(router), myVehicle(vehicle), myStartTime(msTime) {}
run(FXWorkerThread *)154         void run(FXWorkerThread* /* context */) {
155             myRouter->buildContractionHierarchy(myStartTime, myVehicle);
156         }
157     private:
158         CHRouterType* myRouter;
159         const V* const myVehicle;
160         const SUMOTime myStartTime;
161     private:
162         /// @brief Invalidated assignment operator.
163         ComputeHierarchyTask& operator=(const ComputeHierarchyTask&);
164     };
165 
166 
167 private:
168     /// @brief for multi threaded routing
169     FXWorkerThread::Pool myThreadPool;
170 #endif
171 
172 private:
173     typedef std::map<std::pair<const SUMOVehicleClass, const double>, std::vector<CHRouterType*> > RouterMap;
174 
175     RouterMap myRouters;
176 
177     /// @brief all edges with numerical ids
178     const std::vector<E*>& myEdges;
179 
180     const bool myIgnoreErrors;
181 
182     const SUMOTime myBegin;
183     const SUMOTime myEnd;
184     const SUMOTime myWeightPeriod;
185     const int myMaxNumInstances;
186 };
187 
188 
189 #endif
190 
191 /****************************************************************************/
192 
193