service_registry.hpp
Go to the documentation of this file.
00001 //
00002 // service_registry.hpp
00003 // ~~~~~~~~~~~~~~~~~~~~
00004 //
00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
00006 //
00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00009 //
00010 
00011 #ifndef ASIO_DETAIL_SERVICE_REGISTRY_HPP
00012 #define ASIO_DETAIL_SERVICE_REGISTRY_HPP
00013 
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017 
00018 #include "asio/detail/push_options.hpp"
00019 
00020 #include "asio/detail/push_options.hpp"
00021 #include <memory>
00022 #include <typeinfo>
00023 #include "asio/detail/pop_options.hpp"
00024 
00025 #include "asio/io_service.hpp"
00026 #include "asio/detail/mutex.hpp"
00027 #include "asio/detail/noncopyable.hpp"
00028 #include "asio/detail/service_id.hpp"
00029 
00030 #if defined(BOOST_NO_TYPEID)
00031 # if !defined(ASIO_NO_TYPEID)
00032 #  define ASIO_NO_TYPEID
00033 # endif // !defined(ASIO_NO_TYPEID)
00034 #endif // defined(BOOST_NO_TYPEID)
00035 
00036 namespace asio {
00037 namespace detail {
00038 
00039 class service_registry
00040   : private noncopyable
00041 {
00042 public:
00043   // Constructor.
00044   service_registry(asio::io_service& o)
00045     : owner_(o),
00046       first_service_(0)
00047   {
00048   }
00049 
00050   // Destructor.
00051   ~service_registry()
00052   {
00053     // Shutdown all services. This must be done in a separate loop before the
00054     // services are destroyed since the destructors of user-defined handler
00055     // objects may try to access other service objects.
00056     asio::io_service::service* service = first_service_;
00057     while (service)
00058     {
00059       service->shutdown_service();
00060       service = service->next_;
00061     }
00062 
00063     // Destroy all services.
00064     while (first_service_)
00065     {
00066       asio::io_service::service* next_service = first_service_->next_;
00067       delete first_service_;
00068       first_service_ = next_service;
00069     }
00070   }
00071 
00072   // Get the service object corresponding to the specified service type. Will
00073   // create a new service object automatically if no such object already
00074   // exists. Ownership of the service object is not transferred to the caller.
00075   template <typename Service>
00076   Service& use_service()
00077   {
00078     asio::detail::mutex::scoped_lock lock(mutex_);
00079 
00080     // First see if there is an existing service object for the given type.
00081     asio::io_service::service* service = first_service_;
00082     while (service)
00083     {
00084       if (service_id_matches(*service, Service::id))
00085         return *static_cast<Service*>(service);
00086       service = service->next_;
00087     }
00088 
00089     // Create a new service object. The service registry's mutex is not locked
00090     // at this time to allow for nested calls into this function from the new
00091     // service's constructor.
00092     lock.unlock();
00093     std::auto_ptr<Service> new_service(new Service(owner_));
00094     init_service_id(*new_service, Service::id);
00095     Service& new_service_ref = *new_service;
00096     lock.lock();
00097 
00098     // Check that nobody else created another service object of the same type
00099     // while the lock was released.
00100     service = first_service_;
00101     while (service)
00102     {
00103       if (service_id_matches(*service, Service::id))
00104         return *static_cast<Service*>(service);
00105       service = service->next_;
00106     }
00107 
00108     // Service was successfully initialised, pass ownership to registry.
00109     new_service->next_ = first_service_;
00110     first_service_ = new_service.release();
00111 
00112     return new_service_ref;
00113   }
00114 
00115   // Add a service object. Returns false on error, in which case ownership of
00116   // the object is retained by the caller.
00117   template <typename Service>
00118   bool add_service(Service* new_service)
00119   {
00120     asio::detail::mutex::scoped_lock lock(mutex_);
00121 
00122     // Check if there is an existing service object for the given type.
00123     asio::io_service::service* service = first_service_;
00124     while (service)
00125     {
00126       if (service_id_matches(*service, Service::id))
00127         return false;
00128       service = service->next_;
00129     }
00130 
00131     // Take ownership of the service object.
00132     init_service_id(*new_service, Service::id);
00133     new_service->next_ = first_service_;
00134     first_service_ = new_service;
00135 
00136     return true;
00137   }
00138 
00139   // Check whether a service object of the specified type already exists.
00140   template <typename Service>
00141   bool has_service() const
00142   {
00143     asio::detail::mutex::scoped_lock lock(mutex_);
00144 
00145     asio::io_service::service* service = first_service_;
00146     while (service)
00147     {
00148       if (service_id_matches(*service, Service::id))
00149         return true;
00150       service = service->next_;
00151     }
00152 
00153     return false;
00154   }
00155 
00156 private:
00157   // Set a service's id.
00158   void init_service_id(asio::io_service::service& service,
00159       const asio::io_service::id& id)
00160   {
00161     service.type_info_ = 0;
00162     service.id_ = &id;
00163   }
00164 
00165 #if !defined(ASIO_NO_TYPEID)
00166   // Set a service's id.
00167   template <typename Service>
00168   void init_service_id(asio::io_service::service& service,
00169       const asio::detail::service_id<Service>& /*id*/)
00170   {
00171     service.type_info_ = &typeid(Service);
00172     service.id_ = 0;
00173   }
00174 #endif // !defined(ASIO_NO_TYPEID)
00175 
00176   // Check if a service matches the given id.
00177   static bool service_id_matches(
00178       const asio::io_service::service& service,
00179       const asio::io_service::id& id)
00180   {
00181     return service.id_ == &id;
00182   }
00183 
00184 #if !defined(ASIO_NO_TYPEID)
00185   // Check if a service matches the given id.
00186   template <typename Service>
00187   static bool service_id_matches(
00188       const asio::io_service::service& service,
00189       const asio::detail::service_id<Service>& /*id*/)
00190   {
00191     return service.type_info_ != 0 && *service.type_info_ == typeid(Service);
00192   }
00193 #endif // !defined(ASIO_NO_TYPEID)
00194 
00195   // Mutex to protect access to internal data.
00196   mutable asio::detail::mutex mutex_;
00197 
00198   // The owner of this service registry and the services it contains.
00199   asio::io_service& owner_;
00200 
00201   // The first service in the list of contained services.
00202   asio::io_service::service* first_service_;
00203 };
00204 
00205 } // namespace detail
00206 } // namespace asio
00207 
00208 #include "asio/detail/pop_options.hpp"
00209 
00210 #endif // ASIO_DETAIL_SERVICE_REGISTRY_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39