diff --git a/.vscode/settings.json b/.vscode/settings.json index 65d1b02ed2e..bf849e35bbb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -72,6 +72,23 @@ "typeinfo": "cpp", "unordered_map": "cpp", "variant": "cpp", - "algorithm": "cpp" + "algorithm": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "chrono": "cpp", + "compare": "cpp", + "concepts": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "random": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "numbers": "cpp", + "semaphore": "cpp", + "stop_token": "cpp", + "cinttypes": "cpp" } } diff --git a/cpp/include/Ice/ImplicitContext.h b/cpp/include/Ice/ImplicitContext.h index 5f2d3cc9d3a..17b60ff030a 100644 --- a/cpp/include/Ice/ImplicitContext.h +++ b/cpp/include/Ice/ImplicitContext.h @@ -5,35 +5,11 @@ #ifndef __Ice_ImplicitContext_h__ #define __Ice_ImplicitContext_h__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef ICE_API -# if defined(ICE_STATIC_LIBS) -# define ICE_API /**/ -# elif defined(ICE_API_EXPORTS) -# define ICE_API ICE_DECLSPEC_EXPORT -# else -# define ICE_API ICE_DECLSPEC_IMPORT -# endif -#endif - -namespace Ice -{ - -class ImplicitContext; +#include "Config.h" +#include "OutputStream.h" +#include -} +#include namespace Ice { @@ -58,30 +34,28 @@ namespace Ice * null replaced by the empty-string. * \headerfile Ice/Ice.h */ -class ICE_CLASS(ICE_API) ImplicitContext +class ICE_API ImplicitContext final { public: - ICE_MEMBER(ICE_API) virtual ~ImplicitContext(); - /** * Get a copy of the underlying context. * @return A copy of the underlying context. */ - virtual ::Ice::Context getContext() const = 0; + Context getContext() const; /** * Set the underlying context. * @param newContext The new context. */ - virtual void setContext(const Context& newContext) = 0; + void setContext(const Context& newContext); /** * Check if this key has an associated value in the underlying context. * @param key The key. * @return True if the key has an associated value, False otherwise. */ - virtual bool containsKey(const ::std::string& key) const = 0; + bool containsKey(const std::string& key) const; /** * Get the value associated with the given key in the underlying context. Returns an empty string if no value is @@ -90,7 +64,7 @@ class ICE_CLASS(ICE_API) ImplicitContext * @param key The key. * @return The value associated with the key. */ - virtual ::std::string get(const ::std::string& key) const = 0; + std::string get(const std::string& key) const; /** * Create or update a key/value entry in the underlying context. @@ -98,33 +72,39 @@ class ICE_CLASS(ICE_API) ImplicitContext * @param value The value. * @return The previous value associated with the key, if any. */ - virtual ::std::string put(const ::std::string& key, const ::std::string& value) = 0; + std::string put(const std::string& key, const std::string& value); /** * Remove the entry for the given key in the underlying context. * @param key The key. * @return The value associated with the key, if any. */ - virtual ::std::string remove(const ::std::string& key) = 0; -}; + std::string remove(const std::string& key); -} + /** + * Marshals the underlying context plus the given context. Entries in the given context overwrite entries in the + * underlying context. + * @param context The context to write to the output stream. + * @param os The output stream. + */ + void write(const Context& context, Ice::OutputStream* os) const; -/// \cond STREAM -namespace Ice -{ + /** + * Combines the underlying context plus the given context. Entries in the given context overwrite entries in the + * underlying context. + * @param context The context to combine with the underlying context. + * @param combined The combined context. + */ + void combine(const Context& context, Context& combined) const; -} -/// \endcond +private: -/// \cond INTERNAL -namespace Ice -{ + mutable std::mutex _mutex; + Context _context; +}; -using ImplicitContextPtr = ::std::shared_ptr; +using ImplicitContextPtr = std::shared_ptr; } -/// \endcond -#include #endif diff --git a/cpp/include/Ice/ImplicitContextF.h b/cpp/include/Ice/ImplicitContextF.h index 672e0f6b777..2d4b908f035 100644 --- a/cpp/include/Ice/ImplicitContextF.h +++ b/cpp/include/Ice/ImplicitContextF.h @@ -5,14 +5,7 @@ #ifndef __Ice_ImplicitContextF_h__ #define __Ice_ImplicitContextF_h__ -#include -#include -#include -#include -#include -#include -#include -#include +#include namespace Ice { diff --git a/cpp/src/Ice/DLLMain.cpp b/cpp/src/Ice/DLLMain.cpp index e232f6bd54e..c49ba56ba2b 100644 --- a/cpp/src/Ice/DLLMain.cpp +++ b/cpp/src/Ice/DLLMain.cpp @@ -2,7 +2,6 @@ // Copyright (c) ZeroC, Inc. All rights reserved. // -#include #include extern "C" BOOL WINAPI _CRT_INIT(HINSTANCE, DWORD, LPVOID); @@ -28,10 +27,6 @@ ice_DLL_Main(HINSTANCE hDLL, DWORD reason, LPVOID reserved) { Ice::Service::setModuleHandle(hDLL); } - else if(reason == DLL_THREAD_DETACH) - { - Ice::ImplicitContextI::cleanupThread(); - } // // During DETACH, we must call _CRT_INIT last. diff --git a/cpp/src/Ice/ImplicitContext.cpp b/cpp/src/Ice/ImplicitContext.cpp index 451d90ad28e..95b2d9b4371 100644 --- a/cpp/src/Ice/ImplicitContext.cpp +++ b/cpp/src/Ice/ImplicitContext.cpp @@ -2,23 +2,109 @@ // Copyright (c) ZeroC, Inc. All rights reserved. // -#ifndef ICE_API_EXPORTS -# define ICE_API_EXPORTS -#endif #include -#include -#include -#include -#include -#if defined(_MSC_VER) -# pragma warning(disable:4458) // declaration of ... hides class member -#elif defined(__clang__) -# pragma clang diagnostic ignored "-Wshadow" -#elif defined(__GNUC__) -# pragma GCC diagnostic ignored "-Wshadow" -#endif +using namespace std; +using namespace Ice; -Ice::ImplicitContext::~ImplicitContext() +Context +ImplicitContext::getContext() const { + lock_guard lock(_mutex); + return _context; +} + +void +ImplicitContext::setContext(const Context& newContext) +{ + lock_guard lock(_mutex); + _context = newContext; +} + +bool +ImplicitContext::containsKey(const string& key) const +{ + lock_guard lock(_mutex); + return _context.find(key) != _context.end(); +} + +string +ImplicitContext::get(const string& key) const +{ + lock_guard lock(_mutex); + Context::const_iterator p = _context.find(key); + if(p == _context.end()) + { + return ""; + } + return p->second; +} + +string +ImplicitContext::put(const string& key, const string& value) +{ + lock_guard lock(_mutex); + string& val = _context[key]; + + string oldVal = val; + val = value; + return oldVal; +} + +string +ImplicitContext::remove(const string& key) +{ + lock_guard lock(_mutex); + Context::iterator p = _context.find(key); + if(p == _context.end()) + { + return ""; + } + else + { + string oldVal = p->second; + _context.erase(p); + return oldVal; + } +} + +void +ImplicitContext::write(const Context& contex, ::Ice::OutputStream* os) const +{ + unique_lock lock(_mutex); + if(contex.size() == 0) + { + os->write(_context); + } + else if(_context.size() == 0) + { + lock.unlock(); + os->write(contex); + } + else + { + Context combined = contex; + combined.insert(_context.begin(), _context.end()); + lock.unlock(); + os->write(combined); + } +} + +void +ImplicitContext::combine(const Context& context, Context& combined) const +{ + lock_guard lock(_mutex); + if(context.size() == 0) + { + combined = _context; + } + else if(_context.size() == 0) + { + combined = context; + } + else + { + combined = context; + combined.insert(_context.begin(), _context.end()); + } } diff --git a/cpp/src/Ice/ImplicitContextI.cpp b/cpp/src/Ice/ImplicitContextI.cpp deleted file mode 100644 index ce0ad12370c..00000000000 --- a/cpp/src/Ice/ImplicitContextI.cpp +++ /dev/null @@ -1,633 +0,0 @@ -// -// Copyright (c) ZeroC, Inc. All rights reserved. -// - -#include -#include -#include -#include - -#include - -using namespace std; -using namespace Ice; - -namespace -{ - -class SharedImplicitContext : public ImplicitContextI -{ -public: - - virtual Context getContext() const; - virtual void setContext(const Context&); - - virtual bool containsKey(const string&) const; - virtual string get(const string&) const; - virtual string put(const string&, const string&); - virtual string remove(const string&); - - virtual void write(const Context&, ::Ice::OutputStream*) const; - virtual void combine(const Context&, Context&) const; - -private: - Context _context; - mutable std::mutex _mutex; -}; - -class PerThreadImplicitContext : public ImplicitContextI -{ -public: - - PerThreadImplicitContext(); - virtual ~PerThreadImplicitContext(); - - virtual Context getContext() const; - virtual void setContext(const Context&); - - virtual bool containsKey(const string&) const; - virtual string get(const string&) const; - virtual string put(const string&, const string&); - virtual string remove(const string&); - - virtual void write(const Context&, ::Ice::OutputStream*) const; - virtual void combine(const Context&, Context&) const; - - struct Slot - { - Slot() : - context(0), - owner(-1) // just to avoid UMR; a random value would work as well - { - } - - Context* context; - long owner; - }; - - // - // Each thread maintains a SlotVector. Each PerThreadImplicitContext instance - // is assigned a slot in this vector. - // - typedef std::vector SlotVector; - - // - // We remember which slot-indices are in use (to be able to reuse indices) - // - typedef std::vector IndexInUse; - static IndexInUse* _indexInUse; - static mutex _mutex; - - static long _nextId; - static long _destroyedIds; - static size_t _slotVectors; - -#ifdef _WIN32 - static DWORD _key; -#else - static pthread_key_t _key; -#endif - - static void tryCleanupKey(); // must be called with _mutex locked - -private: - - Context* getThreadContext(bool) const; - void clearThreadContext() const; - - size_t _index; // index in all SlotVector - long _id; // corresponds to owner in the Slot -}; -} - -extern "C" void iceImplicitContextThreadDestructor(void*); - -ImplicitContextIPtr -ImplicitContextI::create(const std::string& kind) -{ - if(kind == "None" || kind == "") - { - return 0; - } - else if(kind == "Shared") - { - return std::make_shared(); - } - else if(kind == "PerThread") - { - return std::make_shared(); - } - else - { - throw Ice::InitializationException( - __FILE__, __LINE__, - "'" + kind + "' is not a valid value for Ice.ImplicitContext"); - } -} - -#if defined(_WIN32) -void -ImplicitContextI::cleanupThread() -{ - if(PerThreadImplicitContext::_nextId > 0) - { - iceImplicitContextThreadDestructor(TlsGetValue(PerThreadImplicitContext::_key)); - } -} -#endif - -// -// SharedImplicitContext implementation -// - -Context -SharedImplicitContext::getContext() const -{ - lock_guard lock(_mutex); - return _context; -} - -void -SharedImplicitContext::setContext(const Context& newContext) -{ - lock_guard lock(_mutex); - _context = newContext; -} - -bool -SharedImplicitContext::containsKey(const string& k) const -{ - lock_guard lock(_mutex); - Context::const_iterator p = _context.find(k); - return p != _context.end(); -} - -string -SharedImplicitContext::get(const string& k) const -{ - lock_guard lock(_mutex); - Context::const_iterator p = _context.find(k); - if(p == _context.end()) - { - return ""; - } - return p->second; -} - -string -SharedImplicitContext::put(const string& k, const string& v) -{ - lock_guard lock(_mutex); - string& val = _context[k]; - - string oldVal = val; - val = v; - return oldVal; -} - -string -SharedImplicitContext::remove(const string& k) -{ - lock_guard lock(_mutex); - Context::iterator p = _context.find(k); - if(p == _context.end()) - { - return ""; - } - else - { - string oldVal = p->second; - _context.erase(p); - return oldVal; - } -} - -void -SharedImplicitContext::write(const Context& proxyCtx, ::Ice::OutputStream* s) const -{ - unique_lock lock(_mutex); - if(proxyCtx.size() == 0) - { - s->write(_context); - } - else if(_context.size() == 0) - { - lock.unlock(); - s->write(proxyCtx); - } - else - { - Context combined = proxyCtx; - combined.insert(_context.begin(), _context.end()); - lock.unlock(); - s->write(combined); - } -} - -void -SharedImplicitContext::combine(const Context& proxyCtx, Context& ctx) const -{ - lock_guard lock(_mutex); - if(proxyCtx.size() == 0) - { - ctx = _context; - } - else if(_context.size() == 0) - { - ctx = proxyCtx; - } - else - { - ctx = proxyCtx; - ctx.insert(_context.begin(), _context.end()); - } -} - -// -// PerThreadImplicitContext implementation -// -long PerThreadImplicitContext::_nextId; -long PerThreadImplicitContext::_destroyedIds; -size_t PerThreadImplicitContext::_slotVectors; -PerThreadImplicitContext::IndexInUse* PerThreadImplicitContext::_indexInUse; -mutex PerThreadImplicitContext::_mutex; - -# ifdef _WIN32 -DWORD PerThreadImplicitContext::_key; -# else -pthread_key_t PerThreadImplicitContext::_key; -# endif - -PerThreadImplicitContext::PerThreadImplicitContext() -{ - lock_guard lock(_mutex); - _id = _nextId++; - if(_id == 0) - { -# ifdef _WIN32 - _key = TlsAlloc(); - if(_key == TLS_OUT_OF_INDEXES) - { - throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, GetLastError()); - } -# else - int err = pthread_key_create(&_key, &iceImplicitContextThreadDestructor); - if(err != 0) - { - throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, err); - } -# endif - } - - // - // Now grab an index - // - if(_indexInUse == 0) - { - _indexInUse = new IndexInUse(1); - } - size_t i = 0; - while(i < _indexInUse->size() && (*_indexInUse)[i]) - { - i++; - } - - if(i == _indexInUse->size()) - { - _indexInUse->resize(i + 1); - } - (*_indexInUse)[i] = true; - _index = i; -} - -PerThreadImplicitContext::~PerThreadImplicitContext() -{ - lock_guard lock(_mutex); - (*_indexInUse)[_index] = false; - - if(find(_indexInUse->begin(), _indexInUse->end(), true) == _indexInUse->end()) - { - delete _indexInUse; - _indexInUse = 0; - } - - _destroyedIds++; - tryCleanupKey(); -} - -void -PerThreadImplicitContext::tryCleanupKey() -{ - if(_destroyedIds == _nextId && _slotVectors == 0) - { - // - // We can do a full reset - // - _nextId = 0; - _destroyedIds = 0; -# ifdef _WIN32 - TlsFree(_key); -# else - pthread_key_delete(_key); -# endif - } -} - -Context* -PerThreadImplicitContext::getThreadContext(bool allocate) const -{ -# ifdef _WIN32 - SlotVector* sv = static_cast(TlsGetValue(_key)); -# else - SlotVector* sv = static_cast(pthread_getspecific(_key)); -# endif - if(sv == 0) - { - if(!allocate) - { - return 0; - } - - { - lock_guard lock(_mutex); - sv = new SlotVector(_index + 1); - _slotVectors++; - } - -# ifdef _WIN32 - - if(TlsSetValue(_key, sv) == 0) - { - throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, GetLastError()); - } -# else - if(int err = pthread_setspecific(_key, sv)) - { - throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, err); - } -# endif - } - else - { - if(sv->size() <= _index) - { - if(!allocate) - { - return 0; - } - else - { - sv->resize(_index + 1); - } - } - } - - Slot& slot = (*sv)[_index]; - if(slot.context != 0) - { - if(slot.owner != _id) - { - // - // Reuse the slot from another (dead) communicator - // - slot.context->clear(); - slot.owner = _id; - } - // - // else keep this slot.context - // - } - else - { - if(allocate) - { - slot.context = new Context; - slot.owner = _id; - } - // - // else keep null slot.context - // - } - return slot.context; -} - -void -PerThreadImplicitContext::clearThreadContext() const -{ -# ifdef _WIN32 - SlotVector* sv = static_cast(TlsGetValue(_key)); -# else - SlotVector* sv = static_cast(pthread_getspecific(_key)); -# endif - if(sv != 0 && _index < sv->size()) - { - delete (*sv)[_index].context; - (*sv)[_index].context = 0; - - // - // Trim tailing empty contexts. - // - size_t i = sv->size(); - - bool clear = true; - while(i != 0) - { - i--; - if((*sv)[i].context != 0) - { - clear = false; - break; - } - } - - // - // If we did not find any contexts, delete the SlotVector. - // - if(clear) - { - delete sv; -# ifdef _WIN32 - if(TlsSetValue(_key, 0) == 0) - { - throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, GetLastError()); - } -# else - if(int err = pthread_setspecific(_key, 0)) - { - throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, err); - } - - { - lock_guard lock(_mutex); - _slotVectors--; - } -# endif - } - else - { - sv->resize(i + 1); - } - } -} - -Context -PerThreadImplicitContext::getContext() const -{ - Context* ctx = getThreadContext(false); - if(ctx == 0) - { - return Context(); - } - else - { - return *ctx; - } -} - -void -PerThreadImplicitContext::setContext(const Context& newContext) -{ - if(newContext.size() == 0) - { - clearThreadContext(); - } - else - { - Context* ctx = getThreadContext(true); - assert(ctx != 0); - *ctx = newContext; - } -} - -bool -PerThreadImplicitContext::containsKey(const string& k) const -{ - const Context* ctx = getThreadContext(false); - if(ctx == 0) - { - return false; - } - Context::const_iterator p = ctx->find(k); - return p != ctx->end(); -} - -string -PerThreadImplicitContext::get(const string& k) const -{ - const Context* ctx = getThreadContext(false); - if(ctx == 0) - { - return ""; - } - Context::const_iterator p = ctx->find(k); - if(p == ctx->end()) - { - return ""; - } - return p->second; -} - -string -PerThreadImplicitContext::put(const string& k, const string& v) -{ - Context* ctx = getThreadContext(true); - - string& val = (*ctx)[k]; - - string oldVal = val; - val = v; - return oldVal; -} - -string -PerThreadImplicitContext::remove(const string& k) -{ - Context* ctx = getThreadContext(false); - if(ctx == 0) - { - return ""; - } - - Context::iterator p = ctx->find(k); - if(p == ctx->end()) - { - return ""; - } - else - { - string oldVal = p->second; - ctx->erase(p); - - if(ctx->size() == 0) - { - clearThreadContext(); - } - return oldVal; - } -} - -void -PerThreadImplicitContext::write(const Context& proxyCtx, ::Ice::OutputStream* s) const -{ - const Context* threadCtx = getThreadContext(false); - - if(threadCtx == 0 || threadCtx->size() == 0) - { - s->write(proxyCtx); - } - else if(proxyCtx.size() == 0) - { - s->write(*threadCtx); - } - else - { - Context combined = proxyCtx; - combined.insert(threadCtx->begin(), threadCtx->end()); - s->write(combined); - } -} - -void -PerThreadImplicitContext::combine(const Context& proxyCtx, Context& ctx) const -{ - const Context* threadCtx = getThreadContext(false); - - if(threadCtx == 0 || threadCtx->size() == 0) - { - ctx = proxyCtx; - } - else if(proxyCtx.size() == 0) - { - ctx = *threadCtx; - } - else - { - ctx = proxyCtx; - ctx.insert(threadCtx->begin(), threadCtx->end()); - } -} - -extern "C" void iceImplicitContextThreadDestructor(void* v) -{ - PerThreadImplicitContext::SlotVector* sv = static_cast(v); - if(sv != 0) - { - // - // Cleanup each slot - // - for(PerThreadImplicitContext::SlotVector::iterator p = sv->begin(); p != sv->end(); ++p) - { - delete p->context; - } - // - // Then the vector - // - delete sv; - - { - lock_guard lock(PerThreadImplicitContext::_mutex); - PerThreadImplicitContext::_slotVectors--; - PerThreadImplicitContext::tryCleanupKey(); - } - } -} diff --git a/cpp/src/Ice/ImplicitContextI.h b/cpp/src/Ice/ImplicitContextI.h deleted file mode 100644 index 97d9ed34e79..00000000000 --- a/cpp/src/Ice/ImplicitContextI.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) ZeroC, Inc. All rights reserved. -// - -#ifndef ICE_IMPLICIT_CONTEXT_I_H -#define ICE_IMPLICIT_CONTEXT_I_H - -#include - -namespace Ice -{ - -// -// The base class for all ImplicitContext implementations -// -class ImplicitContextI; -using ImplicitContextIPtr = std::shared_ptr; - -class ImplicitContextI : public ImplicitContext -{ -public: - - static ImplicitContextIPtr create(const std::string&); - -#ifdef _WIN32 - static void cleanupThread(); -#endif - - // - // Marshals the underlying context plus the given context - // (entries in the given context overwrite entries in - // the underlying context) - // - virtual void write(const Context&, ::Ice::OutputStream*) const = 0; - - // - // Combines the underlying context plus the given context - // (entries in the given context overwrite entries in - // the underlying context) - // - virtual void combine(const Context&, Context&) const = 0; - -}; - -using ImplicitContextIPtr = std::shared_ptr; - -} -#endif diff --git a/cpp/src/Ice/Instance.cpp b/cpp/src/Ice/Instance.cpp index b32b29b7ee4..b8cfd39b25a 100644 --- a/cpp/src/Ice/Instance.cpp +++ b/cpp/src/Ice/Instance.cpp @@ -913,7 +913,6 @@ IceInternal::Instance::Instance(const InitializationData& initData) : _classGraphDepthMax(0), _toStringMode(ToStringMode::Unicode), _acceptClassCycles(false), - _implicitContext(nullptr), _stringConverter(Ice::getProcessStringConverter()), _wstringConverter(Ice::getProcessWstringConverter()), _adminEnabled(false) @@ -1192,8 +1191,27 @@ IceInternal::Instance::initialize(const Ice::CommunicatorPtr& communicator) const_cast(_acceptClassCycles) = _initData.properties->getPropertyAsInt("Ice.AcceptClassCycles") > 0; - const_cast(_implicitContext) = - ImplicitContextI::create(_initData.properties->getProperty("Ice.ImplicitContext")); + string implicitContextKind = _initData.properties->getPropertyWithDefault("Ice.ImplicitContext", "None"); + if(implicitContextKind == "Shared") + { + _implicitContextKind = ImplicitContextKind::Shared; + _sharedImplicitContext = std::make_shared(); + } + else if(implicitContextKind == "PerThread") + { + _implicitContextKind = ImplicitContextKind::PerThread; + } + else if (implicitContextKind == "None") + { + _implicitContextKind = ImplicitContextKind::None; + } + else + { + throw Ice::InitializationException( + __FILE__, + __LINE__, + "'" + implicitContextKind + "' is not a valid value for Ice.ImplicitContext"); + } _routerManager = make_shared(); @@ -1283,6 +1301,39 @@ IceInternal::Instance::initialize(const Ice::CommunicatorPtr& communicator) } } +const Ice::ImplicitContextPtr& +IceInternal::Instance::getImplicitContext() const +{ + switch (_implicitContextKind) + { + case ImplicitContextKind::PerThread: + { + static thread_local std::map perThreadImplicitContextMap; + auto it = perThreadImplicitContextMap.find(this); + if (it == perThreadImplicitContextMap.end()) + { + auto r = perThreadImplicitContextMap.emplace(make_pair(this, std::make_shared())); + return r.first->second; + } + else + { + return it->second; + } + } + case ImplicitContextKind::Shared: + { + assert(_sharedImplicitContext); + return _sharedImplicitContext; + } + default: + { + assert(_sharedImplicitContext == nullptr); + assert(_implicitContextKind == ImplicitContextKind::None); + return _sharedImplicitContext; + } + } +} + IceInternal::Instance::~Instance() { assert(_state == StateDestroyed); diff --git a/cpp/src/Ice/Instance.h b/cpp/src/Ice/Instance.h index 5cf3b3ac706..f0b8303bfe7 100644 --- a/cpp/src/Ice/Instance.h +++ b/cpp/src/Ice/Instance.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -113,10 +113,7 @@ class Instance : public std::enable_shared_from_this std::shared_ptr findAdminFacet(const std::string&); Ice::FacetMap findAllAdminFacets(); - const Ice::ImplicitContextIPtr& getImplicitContext() const - { - return _implicitContext; - } + const Ice::ImplicitContextPtr& getImplicitContext() const; void setDefaultLocator(const std::optional&); void setDefaultRouter(const std::optional&); @@ -183,7 +180,7 @@ class Instance : public std::enable_shared_from_this EndpointFactoryManagerPtr _endpointFactoryManager; DynamicLibraryListPtr _dynamicLibraryList; Ice::PluginManagerPtr _pluginManager; - const Ice::ImplicitContextIPtr _implicitContext; + const Ice::ImplicitContextPtr _implicitContext; Ice::StringConverterPtr _stringConverter; Ice::WstringConverterPtr _wstringConverter; bool _adminEnabled; @@ -196,6 +193,16 @@ class Instance : public std::enable_shared_from_this std::mutex _setBufSizeWarnMutex; mutable std::recursive_mutex _mutex; std::condition_variable_any _conditionVariable; + + enum ImplicitContextKind + { + None, + PerThread, + Shared + }; + ImplicitContextKind _implicitContextKind; + // Only set when _implicitContextKind == Shared. + Ice::ImplicitContextPtr _sharedImplicitContext; }; class ProcessI : public Ice::Process diff --git a/cpp/src/Ice/OutgoingAsync.cpp b/cpp/src/Ice/OutgoingAsync.cpp index b6a70ed0f8a..18a994e33e5 100644 --- a/cpp/src/Ice/OutgoingAsync.cpp +++ b/cpp/src/Ice/OutgoingAsync.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -693,15 +693,15 @@ OutgoingAsync::prepare(const string& operation, OperationMode mode, const Contex // // Implicit context // - const ImplicitContextIPtr& implicitContext = ref->getInstance()->getImplicitContext(); + const ImplicitContextPtr& implicitContext = ref->getInstance()->getImplicitContext(); const Context& prxContext = ref->getContext()->getValue(); - if(implicitContext == 0) + if(implicitContext) { - _os.write(prxContext); + implicitContext->write(prxContext, &_os); } else { - implicitContext->write(prxContext, &_os); + _os.write(prxContext); } } } diff --git a/cpp/src/Ice/msbuild/ice/ice.vcxproj b/cpp/src/Ice/msbuild/ice/ice.vcxproj index aaba4c3c079..ef3a7f8eb8b 100644 --- a/cpp/src/Ice/msbuild/ice/ice.vcxproj +++ b/cpp/src/Ice/msbuild/ice/ice.vcxproj @@ -529,7 +529,6 @@ - @@ -930,4 +929,4 @@ - \ No newline at end of file + diff --git a/cpp/src/Ice/msbuild/ice/ice.vcxproj.filters b/cpp/src/Ice/msbuild/ice/ice.vcxproj.filters index 2288ae52462..d6938fc121a 100644 --- a/cpp/src/Ice/msbuild/ice/ice.vcxproj.filters +++ b/cpp/src/Ice/msbuild/ice/ice.vcxproj.filters @@ -327,9 +327,6 @@ Source Files - - Source Files - Source Files @@ -820,4 +817,4 @@ Slice Files - \ No newline at end of file +