Permalink
Browse files

Handle recursive service factory calls.

Fixes #213.
  • Loading branch information...
saschazelzer committed Jul 18, 2017
1 parent 05b605c commit 3fd5aecad2bb578d73689945975f386efa7630a4
@@ -36,22 +36,23 @@ set(CMAKE_CXX_STANDARD 11)
# We make use of the following C++11 language and library features:
#
# Language feature GCC Clang AppleClang VisualStudio
# ------------------------------------------------------------------------
# Rvalue references 4.3 2.9 ?? 2012
# Variadic templates 4.3 2.9 ?? 2013*
# Initializer lists 4.4 3.1 ?? 2013
# Static assertions 4.3 2.9 ?? 2010
# auto 4.4 2.9 ?? 2010
# Lambdas 4.5 3.1 ?? 2012
# decltype 4.3 2.9 ?? 2012
# Right angle brackets 4.3 2.9 ?? 2010
# Null pointer constant 4.6 3.0 ?? 2010
# Explicit conversion operators 4.5 3.0 ?? 2013
# Defaulted functions 4.4 3.0 ?? 2013*
# Deleted functions 4.4 2.9 ?? 2013*
# Range-based for 4.6 3.0 ?? 2012
# Atomic operations 4.4 3.1 ?? 2012
# Language feature GCC Clang Xcode VisualStudio
# -------------------------------------------------------------------
# Rvalue references 4.3 2.9 6 2012
# Variadic templates 4.3 2.9 6 2013*
# Initializer lists 4.4 3.1 6 2013
# Static assertions 4.3 2.9 6 2010
# auto 4.4 2.9 6 2010
# Lambdas 4.5 3.1 6 2012
# decltype 4.3 2.9 6 2012
# Right angle brackets 4.3 2.9 6 2010
# Null pointer constant 4.6 3.0 6 2010
# Explicit conversion operators 4.5 3.0 6 2013
# Defaulted functions 4.4 3.0 6 2013*
# Deleted functions 4.4 2.9 6 2013*
# Range-based for 4.6 3.0 6 2012
# Atomic operations 4.4 3.1 6 2012
# thread_local (optional) 4.8 3.3 8 2015
#
# Library features used
# ---------------------
@@ -65,37 +66,42 @@ set(CMAKE_CXX_STANDARD 11)
# wait_condition
# exception_ptr
set(US_COMPILER_GNU_MINIMUM_VERSION 4.6 )
set(US_COMPILER_CLANG_MINIMUM_VERSION 3.1 )
set(US_COMPILER_APPLE_CLANG_MINIMUM_VERSION 5.0 ) # ??
set(US_COMPILER_MSVC_MINIMUM_VERSION 18.00.31101 )
set(US_COMPILER_GNU_MINIMUM_VERSION 4.6 )
set(US_COMPILER_Clang_MINIMUM_VERSION 3.1 )
set(US_COMPILER_AppleClang_MINIMUM_VERSION 6.0 )
set(US_COMPILER_MSVC_MINIMUM_VERSION 18.00.31101 )
set(US_COMPILER_MSVC_MINIMUM_VERSION_PRODUCT "Visual Studio 2013 Update 4")
set(US_COMPILER_GNU_MINIMUM_VERSION_PRODUCT "GCC ${US_COMPILER_GNU_MINIMUM_VERSION}")
set(US_COMPILER_Clang_MINIMUM_VERSION_PRODUCT "Clang ${US_COMPILER_CLANG_MINIMUM_VERSION}")
set(US_COMPILER_AppleClang_MINIMUM_VERSION_PRODUCT "Xcode 6.0 (Clang ${US_COMPILER_AppleClang_MINIMUM_VERSION})")
set(US_COMPILER_MSVC_MINIMUM_VERSION_PRODUCT "Visual Studio 2013 Update 4 (MSVC ${US_COMPILER_MSVC_MINIMUM_VERSION})")
set(US_COMPILER_GNU_MINIMUM_RECOMMENDED_VERSION 4.8 )
set(US_COMPILER_Clang_MINIMUM_RECOMMENDED_VERSION 3.3 )
set(US_COMPILER_AppleClang_MINIMUM_RECOMMENDED_VERSION 8.0 )
set(US_COMPILER_MSVC_MINIMUM_RECOMMENDED_VERSION 19.00 )
set(US_COMPILER_GNU_MINIMUM_RECOMMENDED_VERSION_PRODUCT "GCC ${US_COMPILER_GNU_MINIMUM_RECOMMENDED_VERSION}")
set(US_COMPILER_Clang_MINIMUM_RECOMMENDED_VERSION_PRODUCT "Clang ${US_COMPILER_CLANG_MINIMUM_RECOMMENDED_VERSION}")
set(US_COMPILER_AppleClang_MINIMUM_RECOMMENDED_VERSION_PRODUCT "Xcode 8.0 (Clang ${US_COMPILER_AppleClang_MINIMUM_RECOMMENDED_VERSION})")
set(US_COMPILER_MSVC_MINIMUM_RECOMMENDED_VERSION_PRODUCT "Visual Studio 2013 Update 4 (MSVC ${US_COMPILER_MSVC_MINIMUM_RECOMMENDED_VERSION})")
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if (CMAKE_CXX_COMPILER_VERSION AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${US_COMPILER_GNU_MINIMUM_VERSION})
message(FATAL_ERROR "GCC version ${US_COMPILER_GNU_MINIMUM_VERSION} or higher required (you are using version ${CMAKE_CXX_COMPILER_VERSION}).")
endif()
set(US_COMPILER_GNU 1)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if (CMAKE_CXX_COMPILER_VERSION AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${US_COMPILER_CLANG_MINIMUM_VERSION})
message(FATAL_ERROR "Clang version ${US_COMPILER_CLANG_MINIMUM_VERSION} or higher required (you are using version ${CMAKE_CXX_COMPILER_VERSION}).")
endif()
set(US_COMPILER_CLANG 1)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
if (CMAKE_CXX_COMPILER_VERSION AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${US_COMPILER_APPLE_CLANG_MINIMUM_VERSION})
message(FATAL_ERROR "Apple Clang version ${US_COMPILER_APPLE_CLANG_MINIMUM_VERSION} or higher required (you are using version ${CMAKE_CXX_COMPILER_VERSION}).")
endif()
set(US_COMPILER_APPLE_CLANG 1)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
if (CMAKE_CXX_COMPILER_VERSION AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${US_COMPILER_MSVC_MINIMUM_VERSION})
message(FATAL_ERROR "${US_COMPILER_MSVC_MINIMUM_VERSION_PRODUCT} or newer required (MSVC ${US_COMPILER_MSVC_MINIMUM_VERSION} or higher, you are using version ${CMAKE_CXX_COMPILER_VERSION})")
endif()
set(US_COMPILER_MSVC 1)
else()
message(WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang (Linux or Apple), GCC and MSVC.")
endif()
if (CMAKE_CXX_COMPILER_VERSION AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${US_COMPILER_${CMAKE_CXX_COMPILER_ID}_MINIMUM_VERSION})
message(FATAL_ERROR "${US_COMPILER_${CMAKE_CXX_COMPILER_ID}_MINIMUM_VERSION_PRODUCT} or higher required (you are using ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}).")
endif()
#-----------------------------------------------------------------------------
# Update CMake module path
#------------------------------------------------------------------------------
@@ -379,7 +385,7 @@ else()
if(NOT US_CXX_TSAN_FLAGS AND US_ENABLE_TSAN)
message(WARNING "TSAN requested, but compiler does not recognize it")
endif()
set(CMAKE_REQUIRED_LIBRARIES "-fprofile-arcs -ftest-coverage")
usFunctionCheckCompilerFlags("-fprofile-arcs -ftest-coverage" US_CXX_COVERAGE_FLAGS)
set(CMAKE_REQUIRED_LIBRARIES "${_orig_req_libs}")
@@ -458,6 +464,25 @@ include(CheckIncludeFileCXX)
CHECK_INCLUDE_FILE_CXX(cxxabi.h US_HAVE_CXXABI_H)
#-----------------------------------------------------------------------------
# C++ language support
#-----------------------------------------------------------------------------
set(disabled_func )
CHECK_CXX_SOURCE_COMPILES(
"
#include <string>
static thread_local std::string dummy;
int main() {
return 0;
}
" US_HAVE_THREAD_LOCAL)
if(NOT US_HAVE_THREAD_LOCAL AND US_ENABLE_THREADING_SUPPORT)
set(disabled_func "${disabled_func}thread_local support unavailable. Recursive service factory calls will not be detected. See also https://github.com/CppMicroServices/CppMicroServices/issues/213\n")
endif()
#-----------------------------------------------------------------------------
# C++ library support
#-----------------------------------------------------------------------------
@@ -479,6 +504,15 @@ return 0;
}
" US_HAVE_REGEX)
if(NOT US_HAVE_THREAD_LOCAL AND US_BUILD_TESTING)
set(disabled_func "${disabled_func}regular expression support unavailable. Some tests will be disalbed.\n")
endif()
# Print a warning summary
if (disabled_func)
message(WARNING "${US_COMPILER_${CMAKE_CXX_COMPILER_ID}_MINIMUM_RECOMMENDED_VERSION_PRODUCT} or higher recommended (you are using ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}). The following functionality will not be available:\n${disabled_func}")
endif()
#-----------------------------------------------------------------------------
# System Information
#-----------------------------------------------------------------------------
@@ -34,7 +34,7 @@ modular and dynamic service-oriented applications. It is based on
`OSGi <http://osgi.org>`_, but tailored to support native cross-platform solutions.
Proper usage of C++ Micro Services patterns and concepts leads to systems
with one or more of the following properties:
with one or more of the following properties:
- Re-use of software components
- Loose coupling between service providers and consumers
@@ -55,7 +55,16 @@ Supported Platforms
The library makes use of some C++11 features and compiles on many
different platforms.
Minimum required compiler versions:
Recommended minimum required compiler versions:
- GCC 4.8
- Clang 3.3
- Clang from Xcode 8.0
- Visual Studio 2015
You may use older compilers, but certain functionality may not be
available. Check the warnings printed during configuration of
your build tree. The following are the absolut minimum requirements:
- GCC 4.6
- Clang 3.1
@@ -108,7 +117,7 @@ Quick Start
Essentially, the C++ Micro Services library provides you with a powerful
dynamic service registry on top of a managed lifecycle. The framework manages,
among other things, logical units of modularity called *bundles* that
among other things, logical units of modularity called *bundles* that
are contained in shared or static libraries. Each bundle
within a library has an associated :any:`cppmicroservices::BundleContext`
object, through which the service registry is accessed.
@@ -189,7 +198,7 @@ file for details about the contribution process.
.. |RTD Build Status (development)| image:: https://readthedocs.org/projects/cppmicroservices/badge/?version=latest&style=flat-square
:target: http://docs.cppmicroservices.org/en/latest/?badge=development
:alt: Documentation Status (development)
.. |Code Coverage Status| image:: https://codecov.io/gh/cppmicroservices/CppMicroServices/branch/master/graph/badge.svg
:target: https://codecov.io/gh/cppmicroservices/CppMicroServices
.. |Code Coverage Status (development)| image:: https://codecov.io/gh/cppmicroservices/CppMicroServices/branch/development/graph/badge.svg
:target: https://codecov.io/gh/cppmicroservices/CppMicroServices
.. |Code Coverage Status| image:: https://img.shields.io/codecov/c/github/CppMicroServices/CppMicroServices/master.svg?style=flat-square
:target: https://codecov.io/gh/cppmicroservices/CppMicroServices/branch/master
.. |Code Coverage Status (development)| image:: https://img.shields.io/codecov/c/github/CppMicroServices/CppMicroServices/development.svg?style=flat-square
:target: https://codecov.io/gh/cppmicroservices/CppMicroServices/branch/development
@@ -122,6 +122,11 @@ US_MSVC_DISABLE_WARNING(4996)
// Mark a variable or expression result as unused
#define US_UNUSED(x) (void)(x)
//-------------------------------------------------------------------
// C++ Language features
//-------------------------------------------------------------------
#cmakedefine US_HAVE_THREAD_LOCAL
//-------------------------------------------------------------------
// C++ Library features
@@ -329,11 +329,11 @@ class US_Framework_EXPORT Bundle
* <code>BundleContext</code> can be used by the caller to act on behalf
* of this bundle.
*
* If this bundle is not in the <code>STATE_STARTED</code> state, then this
* bundle has no valid <code>BundleContext</code> and this method will
* return a default constructed \c BundleContext object.
* If this bundle is not in the \c STATE_STARTING, \c STATE_ACTIVE, or
* \c STATE_STOPPING states, then this bundle has no valid \c BundleContext
* and this method will an invalid \c BundleContext object.
*
* @return A valid or invalid <code>BundleContext</code> for this bundle or.
* @return A valid or invalid <code>BundleContext</code> for this bundle.
*/
BundleContext GetBundleContext() const;
@@ -34,29 +34,24 @@ namespace cppmicroservices {
* A factory for \link Constants::SCOPE_BUNDLE bundle scope\endlink services.
* The factory can provide service objects unique to each bundle.
*
* <p>
* When registering a service, a <code>ServiceFactory</code> object can be
* used instead of a service object, so that the bundle developer can gain
* control of the specific service object granted to a bundle that is using the
* service.
* When registering a service, a \c ServiceFactory object can be
* used instead of a service object, so that the bundle developer can create
* a customized service object for each bundle that is using the service.
*
* <p>
* When this happens, the
* <code>BundleContext::GetService(const ServiceReference&)</code> method calls the
* <code>ServiceFactory::GetService</code> method to create a service object
* specifically for the requesting bundle. The service object returned by the
* <code>ServiceFactory</code> is cached by the framework until the bundle
* releases its use of the service.
* When a bundle requests the service object, the framework calls the
* \c ServiceFactory::GetService method to return a service object
* customized for the requesting bundle. The returned service object is
* cached by the framework for subsequent calls to
* <code>BundleContext::GetService(const ServiceReference&)</code> until
* the bundle releases its use of the service.
*
* <p>
* When the bundle's use count for the service equals zero (including the bundle
* stopping or the service being unregistered), the
* <code>ServiceFactory::UngetService</code> method is called.
* When the bundle's use count for the service is decremented to zero
* (including the bundle stopping or the service being unregistered), the
* framework will call the \c ServiceFactory::UngetService method.
*
* <p>
* <code>ServiceFactory</code> objects are only used by the framework and are
* not made available to other bundles in the bundle environment. The framework
* may concurrently call a <code>ServiceFactory</code>.
* \c ServiceFactory objects are only used by the framework and are not
* made available to other bundles in the bundle environment. The framework
* may concurrently call a \c ServiceFactory.
*
* @see BundleContext#GetService
* @see PrototypeServiceFactory
@@ -70,25 +65,35 @@ class ServiceFactory
virtual ~ServiceFactory() {}
/**
* Creates a new service object.
* Returns a service object for a bundle.
*
* <p>
* The Framework invokes this method the first time the specified
* <code>bundle</code> requests a service object using the
* The framework invokes this method the first time the specified
* \c bundle requests a service object using the
* <code>BundleContext::GetService(const ServiceReferenceBase&)</code> method. The
* service factory can then return a specific service object for each
* factory can then return a customized service object for each bundle.
*
* The framework checks that the returned service object is valid. If the
* returned service object is null or does not contain entries for all the
* classes named when the service was registered, a framework event of type
* \c FrameworkEvent::FRAMEWORK_ERROR is fired containing a service exception
* of type \c ServiceException::FACTORY_ERROR and null is returned to the
* bundle. If this method throws an exception, a framework event of type
* \c FrameworkEvent::FRAMEWORK_ERROR is fired containing a service exception
* of type \c ServiceException::FACTORY_EXCEPTION with the thrown exception
* as a nested exception and null is returned to the bundle. If this method is
* recursively called for the specified bundle, a framework event of type
* \c FrameworkEvent::FRAMEWORK_ERROR is fired containing a service exception
* of type \c ServiceException::FACTORY_RECURSION and null is returned to the
* bundle.
*
* <p>
* The framework caches the value returned (unless the InterfaceMap is empty),
* and will return the same service object on any future call to
* <code>BundleContext::GetService</code> for the same bundles. This means the
* framework does not allow this method to be concurrently called for the
* same bundle.
* The framework caches the valid service object, and will return the same
* service object on any future call to \c BundleContext::GetService for the
* specified bundle. This means the framework does not allow this method to
* be concurrently called for the specified bundle.
*
* @param bundle The bundle using the service.
* @param bundle The bundle requesting the service.
* @param registration The <code>ServiceRegistrationBase</code> object for the
* service.
* requested service.
* @return A service object that <strong>must</strong> contain entries for all
* the interfaces named when the service was registered.
* @see BundleContext#GetService
@@ -98,17 +103,19 @@ class ServiceFactory
const ServiceRegistrationBase& registration) = 0;
/**
* Releases a service object.
* Releases a service object customized for a bundle.
*
* <p>
* The framework invokes this method when a service has been released by a
* bundle.
* The Framework invokes this method when a service has been released by a
* bundle. If this method throws an exception, a framework event of type
* \c FrameworkEvent::FRAMEWORK_ERROR is fired containing a service
* exception of type ServiceException::FACTORY_EXCEPTION with the thrown
* exception as a nested exception.
*
* @param bundle The Bundle releasing the service.
* @param registration The <code>ServiceRegistration</code> object for the
* service.
* @param registration The \c ServiceRegistration object for the
* service being released.
* @param service The service object returned by a previous call to the
* <code>ServiceFactory::GetService</code> method.
* \c ServiceFactory::GetService method.
* @see InterfaceMapConstPtr
*/
virtual void UngetService(const Bundle& bundle,
Oops, something went wrong.

0 comments on commit 3fd5aec

Please sign in to comment.