Fixes a race condition when more than one thread tries to access the grid file (thanks Patrick)
This commit is contained in:
		
							parent
							
								
									73ab331506
								
							
						
					
					
						commit
						e176115273
					
				
							
								
								
									
										47
									
								
								DataStructures/HashTable.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								DataStructures/HashTable.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| /*
 | ||||
|     open source routing machine | ||||
|     Copyright (C) Dennis Luxen, others 2010 | ||||
| 
 | ||||
| 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 | ||||
| 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 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, write to the Free Software | ||||
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
| or see http://www.gnu.org/licenses/agpl.txt.
 | ||||
| 
 | ||||
|   Created on: 18.11.2010 | ||||
|   Author: dennis | ||||
| */ | ||||
| 
 | ||||
| #ifndef HASHTABLE_H_ | ||||
| #define HASHTABLE_H_ | ||||
| 
 | ||||
| #include <google/sparse_hash_map> | ||||
| 
 | ||||
| template<typename keyT, typename valueT> | ||||
| class HashTable { | ||||
| 	typedef google::sparse_hash_map<keyT, valueT> MyHashTable; | ||||
| public: | ||||
| 	HashTable() { } | ||||
| 	HashTable(const unsigned size) { | ||||
| 		table.resize(size); | ||||
| 	} | ||||
| 	void Add(const keyT& key, const valueT& value){ | ||||
| 		table[key] = value; | ||||
| 	} | ||||
| 	valueT Find(const keyT& key) { | ||||
| 		return table.find(key)->second; | ||||
| 	} | ||||
| private: | ||||
| 	MyHashTable table; | ||||
| }; | ||||
| 
 | ||||
| #endif /* HASHTABLE_H_ */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -61,6 +61,10 @@ public: | ||||
| 	inline bool FindRoutingStarts(const _Coordinate start, const _Coordinate target, PhantomNodes * phantomNodes) { | ||||
| 	    g->FindRoutingStarts(start, target, phantomNodes); | ||||
| 	} | ||||
| 
 | ||||
| 	inline void RegisterThread(const unsigned k, const unsigned v) { | ||||
| 		g->threadLookup.table.Add(k, v); | ||||
| 	} | ||||
| private: | ||||
| 	vector<_Coordinate> * int2ExtNodeMap; | ||||
| 	ReadOnlyGrid * g; | ||||
|  | ||||
| @ -37,4 +37,12 @@ inline double get_timestamp() | ||||
| double y2lat(double a) { return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2); } | ||||
| double lat2y(double a) { return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2)); } | ||||
| 
 | ||||
| inline unsigned boost_thread_id_hash(boost::thread::id const& id) | ||||
| { | ||||
| 	std::stringstream ostr; | ||||
| 	ostr << id; | ||||
| 	std::tr1::hash<std::string> h; | ||||
| 	return h(ostr.str()); | ||||
| } | ||||
| 
 | ||||
| #endif /* TIMEUTIL_H_ */ | ||||
|  | ||||
| @ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License | ||||
| along with this program; if not, write to the Free Software | ||||
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
| or see http://www.gnu.org/licenses/agpl.txt.
 | ||||
| */ | ||||
|  */ | ||||
| 
 | ||||
| #ifndef HTTP_ROUTER_SERVER_HPP | ||||
| #define HTTP_ROUTER_SERVER_HPP | ||||
| @ -42,79 +42,80 @@ template<typename GraphT> | ||||
| class server: private boost::noncopyable | ||||
| { | ||||
| public: | ||||
|     /// Construct the server to listen on the specified TCP address and port
 | ||||
|     explicit server(const std::string& address, const std::string& port, std::size_t thread_pool_size, SearchEngine<EdgeData, GraphT, NodeInformationHelpDesk> * s) | ||||
|     : thread_pool_size_(thread_pool_size), | ||||
|       acceptor_(io_service_), | ||||
|       new_connection_(new connection<GraphT>(io_service_, request_handler_)), | ||||
|       request_handler_(s), | ||||
|       sEngine(s) | ||||
|     { | ||||
|         // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
 | ||||
|         boost::asio::ip::tcp::resolver resolver(io_service_); | ||||
|         boost::asio::ip::tcp::resolver::query query(address, port); | ||||
|         boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); | ||||
| 	/// Construct the server to listen on the specified TCP address and port
 | ||||
| 	explicit server(const std::string& address, const std::string& port, std::size_t thread_pool_size, SearchEngine<EdgeData, GraphT, NodeInformationHelpDesk> * s) | ||||
| 	: thread_pool_size_(thread_pool_size), | ||||
| 	  acceptor_(io_service_), | ||||
| 	  new_connection_(new connection<GraphT>(io_service_, request_handler_)), | ||||
| 	  request_handler_(s), | ||||
| 	  sEngine(s) | ||||
| 	{ | ||||
| 		// Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
 | ||||
| 		boost::asio::ip::tcp::resolver resolver(io_service_); | ||||
| 		boost::asio::ip::tcp::resolver::query query(address, port); | ||||
| 		boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); | ||||
| 
 | ||||
|         acceptor_.open(endpoint.protocol()); | ||||
|         acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); | ||||
|         acceptor_.bind(endpoint); | ||||
|         acceptor_.listen(); | ||||
|         acceptor_.async_accept(new_connection_->socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error)); | ||||
|     } | ||||
| 		acceptor_.open(endpoint.protocol()); | ||||
| 		acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); | ||||
| 		acceptor_.bind(endpoint); | ||||
| 		acceptor_.listen(); | ||||
| 		acceptor_.async_accept(new_connection_->socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error)); | ||||
| 	} | ||||
| 
 | ||||
|     /// Run the server's io_service loop.
 | ||||
|     void run() | ||||
|     { | ||||
|         // Create a pool of threads to run all of the io_services.
 | ||||
|         std::vector<boost::shared_ptr<boost::thread> > threads; | ||||
|         for (std::size_t i = 0; i < thread_pool_size_; ++i) | ||||
|         { | ||||
|             boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_))); | ||||
|             threads.push_back(thread); | ||||
|         } | ||||
| 	/// Run the server's io_service loop.
 | ||||
| 	void run() | ||||
| 	{ | ||||
| 		// Create a pool of threads to run all of the io_services.
 | ||||
| 		std::vector<boost::shared_ptr<boost::thread> > threads; | ||||
| 		for (std::size_t i = 0; i < thread_pool_size_; ++i) | ||||
| 		{ | ||||
| 			boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_))); | ||||
| 			sEngine->RegisterThread( boost_thread_id_hash( thread->get_id() ), threads.size()); | ||||
| 			threads.push_back(thread); | ||||
| 		} | ||||
| 
 | ||||
|         // Wait for all threads in the pool to exit.
 | ||||
|         for (std::size_t i = 0; i < threads.size(); ++i) | ||||
|             threads[i]->join(); | ||||
|     } | ||||
| 		// Wait for all threads in the pool to exit.
 | ||||
| 		for (std::size_t i = 0; i < threads.size(); ++i) | ||||
| 			threads[i]->join(); | ||||
| 	} | ||||
| 
 | ||||
|     /// Stop the server.
 | ||||
|     void stop() | ||||
|     { | ||||
|         io_service_.stop(); | ||||
|     } | ||||
| 	/// Stop the server.
 | ||||
| 	void stop() | ||||
| 	{ | ||||
| 		io_service_.stop(); | ||||
| 	} | ||||
| 
 | ||||
| private: | ||||
|     typedef boost::shared_ptr<connection<GraphT> > connection_ptr; | ||||
| 	typedef boost::shared_ptr<connection<GraphT> > connection_ptr; | ||||
| 
 | ||||
|     /// Handle completion of an asynchronous accept operation.
 | ||||
|     void handle_accept(const boost::system::error_code& e) | ||||
|     { | ||||
|         if (!e) | ||||
|         { | ||||
|             new_connection_->start(); | ||||
|             new_connection_.reset(new connection<GraphT>(io_service_, request_handler_)); | ||||
|             acceptor_.async_accept(new_connection_->socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error)); | ||||
|         } | ||||
|     } | ||||
| 	/// Handle completion of an asynchronous accept operation.
 | ||||
| 	void handle_accept(const boost::system::error_code& e) | ||||
| 	{ | ||||
| 		if (!e) | ||||
| 		{ | ||||
| 			new_connection_->start(); | ||||
| 			new_connection_.reset(new connection<GraphT>(io_service_, request_handler_)); | ||||
| 			acceptor_.async_accept(new_connection_->socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error)); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|     /// The number of threads that will call io_service::run().
 | ||||
|     std::size_t thread_pool_size_; | ||||
| 	/// The number of threads that will call io_service::run().
 | ||||
| 	std::size_t thread_pool_size_; | ||||
| 
 | ||||
|     /// The io_service used to perform asynchronous operations.
 | ||||
|     boost::asio::io_service io_service_; | ||||
| 	/// The io_service used to perform asynchronous operations.
 | ||||
| 	boost::asio::io_service io_service_; | ||||
| 
 | ||||
|     /// Acceptor used to listen for incoming connections.
 | ||||
|     boost::asio::ip::tcp::acceptor acceptor_; | ||||
| 	/// Acceptor used to listen for incoming connections.
 | ||||
| 	boost::asio::ip::tcp::acceptor acceptor_; | ||||
| 
 | ||||
|     /// The next connection to be accepted.
 | ||||
|     connection_ptr new_connection_; | ||||
| 	/// The next connection to be accepted.
 | ||||
| 	connection_ptr new_connection_; | ||||
| 
 | ||||
|     /// The handler for all incoming requests.
 | ||||
|     request_handler<GraphT> request_handler_; | ||||
| 	/// The handler for all incoming requests.
 | ||||
| 	request_handler<GraphT> request_handler_; | ||||
| 
 | ||||
|     /// The object to query the Routing Engine
 | ||||
|     SearchEngine<EdgeData, GraphT> * sEngine; | ||||
| 	/// The object to query the Routing Engine
 | ||||
| 	SearchEngine<EdgeData, GraphT> * sEngine; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -29,6 +29,8 @@ or see http://www.gnu.org/licenses/agpl.txt. | ||||
| #include <cstring> | ||||
| #include <string> | ||||
| 
 | ||||
| #include <boost/thread.hpp> | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| #define VERBOSE(x) x | ||||
| @ -45,6 +47,7 @@ typedef unsigned int EdgeWeight; | ||||
| static const NodeID SPECIAL_NODEID = UINT_MAX; | ||||
| static const EdgeID SPECIAL_EDGEID = UINT_MAX; | ||||
| 
 | ||||
| #include "DataStructures/HashTable.h" | ||||
| #include "DataStructures/NodeCoords.h" | ||||
| typedef NodeCoords<NodeID> NodeInfo; | ||||
| #include "DataStructures/Util.h" | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user