114 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef OSRM_ENGINE_DATA_WATCHDOG_HPP
 | |
| #define OSRM_ENGINE_DATA_WATCHDOG_HPP
 | |
| 
 | |
| #include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
 | |
| #include "engine/datafacade/shared_memory_allocator.hpp"
 | |
| #include "engine/datafacade_factory.hpp"
 | |
| 
 | |
| #include "storage/shared_datatype.hpp"
 | |
| #include "storage/shared_memory.hpp"
 | |
| #include "storage/shared_monitor.hpp"
 | |
| 
 | |
| #include <boost/interprocess/sync/named_upgradable_mutex.hpp>
 | |
| #include <boost/thread/lock_types.hpp>
 | |
| #include <boost/thread/locks.hpp>
 | |
| #include <boost/thread/shared_mutex.hpp>
 | |
| 
 | |
| #include <memory>
 | |
| #include <thread>
 | |
| 
 | |
| namespace osrm
 | |
| {
 | |
| namespace engine
 | |
| {
 | |
| 
 | |
| namespace detail
 | |
| {
 | |
| // We need this wrapper type since template-template specilization of FacadeT is broken on clang
 | |
| // when it is combined with an templated alias (DataFacade in this case).
 | |
| // See https://godbolt.org/g/ZS6Xmt for an example.
 | |
| template <typename AlgorithmT, typename FacadeT> class DataWatchdogImpl;
 | |
| 
 | |
| template <typename AlgorithmT>
 | |
| class DataWatchdogImpl<AlgorithmT, datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>> final
 | |
| {
 | |
|     using mutex_type = typename storage::SharedMonitor<storage::SharedDataTimestamp>::mutex_type;
 | |
|     using Facade = datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>;
 | |
| 
 | |
|   public:
 | |
|     DataWatchdogImpl() : active(true), timestamp(0)
 | |
|     {
 | |
|         // create the initial facade before launching the watchdog thread
 | |
|         {
 | |
|             boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
 | |
| 
 | |
|             facade_factory =
 | |
|                 DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
 | |
|                     std::make_shared<datafacade::SharedMemoryAllocator>(barrier.data().region));
 | |
|             timestamp = barrier.data().timestamp;
 | |
|         }
 | |
| 
 | |
|         watcher = std::thread(&DataWatchdogImpl::Run, this);
 | |
|     }
 | |
| 
 | |
|     ~DataWatchdogImpl()
 | |
|     {
 | |
|         active = false;
 | |
|         barrier.notify_all();
 | |
|         watcher.join();
 | |
|     }
 | |
| 
 | |
|     std::shared_ptr<const Facade> Get(const api::BaseParameters ¶ms) const
 | |
|     {
 | |
|         return facade_factory.Get(params);
 | |
|     }
 | |
|     std::shared_ptr<const Facade> Get(const api::TileParameters ¶ms) const
 | |
|     {
 | |
|         return facade_factory.Get(params);
 | |
|     }
 | |
| 
 | |
|   private:
 | |
|     void Run()
 | |
|     {
 | |
|         while (active)
 | |
|         {
 | |
|             boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
 | |
| 
 | |
|             while (active && timestamp == barrier.data().timestamp)
 | |
|             {
 | |
|                 barrier.wait(current_region_lock);
 | |
|             }
 | |
| 
 | |
|             if (timestamp != barrier.data().timestamp)
 | |
|             {
 | |
|                 auto region = barrier.data().region;
 | |
|                 facade_factory =
 | |
|                     DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
 | |
|                         std::make_shared<datafacade::SharedMemoryAllocator>(region));
 | |
|                 timestamp = barrier.data().timestamp;
 | |
|                 util::Log() << "updated facade to region " << region << " with timestamp "
 | |
|                             << timestamp;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         util::Log() << "DataWatchdog thread stopped";
 | |
|     }
 | |
| 
 | |
|     storage::SharedMonitor<storage::SharedDataTimestamp> barrier;
 | |
|     std::thread watcher;
 | |
|     bool active;
 | |
|     unsigned timestamp;
 | |
|     DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT> facade_factory;
 | |
| };
 | |
| }
 | |
| 
 | |
| // This class monitors the shared memory region that contains the pointers to
 | |
| // the data and layout regions that should be used. This region is updated
 | |
| // once a new dataset arrives.
 | |
| template <typename AlgorithmT, template <typename A> class FacadeT>
 | |
| using DataWatchdog = detail::DataWatchdogImpl<AlgorithmT, FacadeT<AlgorithmT>>;
 | |
| }
 | |
| }
 | |
| 
 | |
| #endif
 |