summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/ImplicitContextI.cpp
diff options
context:
space:
mode:
authorBernard Normier <bernard@zeroc.com>2006-10-20 16:21:11 +0000
committerBernard Normier <bernard@zeroc.com>2006-10-20 16:21:11 +0000
commit6cb72acd28e758df501d0ef0ece489889860e49f (patch)
treedb3891db78db0ac03d1edfff5dc0a203be58fda9 /cpp/src/Ice/ImplicitContextI.cpp
parentConverted Windows build to use nmake (diff)
downloadice-6cb72acd28e758df501d0ef0ece489889860e49f.tar.bz2
ice-6cb72acd28e758df501d0ef0ece489889860e49f.tar.xz
ice-6cb72acd28e758df501d0ef0ece489889860e49f.zip
Implicit context: first cut
Diffstat (limited to 'cpp/src/Ice/ImplicitContextI.cpp')
-rw-r--r--cpp/src/Ice/ImplicitContextI.cpp514
1 files changed, 514 insertions, 0 deletions
diff --git a/cpp/src/Ice/ImplicitContextI.cpp b/cpp/src/Ice/ImplicitContextI.cpp
new file mode 100644
index 00000000000..c49df6dea61
--- /dev/null
+++ b/cpp/src/Ice/ImplicitContextI.cpp
@@ -0,0 +1,514 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2006 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <Ice/ImplicitContextI.h>
+#include <IceUtil/StaticMutex.h>
+
+using namespace std;
+using namespace Ice;
+
+namespace
+{
+
+class SharedImplicitContextWithoutLocking : public ImplicitContextI
+{
+public:
+
+ virtual Context getContext() const;
+ virtual void setContext(const Context&);
+
+ virtual string get(const string&) const;
+ virtual string getWithDefault(const string&, const string&) const;
+ virtual void set(const string&, const string&);
+ virtual void remove(const string&);
+
+ virtual void write(const Context&, ::IceInternal::BasicStream*) const;
+
+protected:
+ Context _context;
+};
+
+class SharedImplicitContext : public SharedImplicitContextWithoutLocking
+{
+public:
+
+ virtual Context getContext() const;
+ virtual void setContext(const Context&);
+
+ virtual string get(const string&) const;
+ virtual string getWithDefault(const string&, const string&) const;
+ virtual void set(const string&, const string&);
+ virtual void remove(const string&);
+
+ virtual void write(const Context&, ::IceInternal::BasicStream*) const;
+
+private:
+ IceUtil::Mutex _mutex;
+};
+
+
+class PerThreadImplicitContext : public ImplicitContextI
+{
+public:
+
+ PerThreadImplicitContext();
+
+ virtual Context getContext() const;
+ virtual void setContext(const Context&);
+
+ virtual string get(const string&) const;
+ virtual string getWithDefault(const string&, const string&) const;
+ virtual void set(const string&, const string&);
+ virtual void remove(const string&);
+
+ virtual void write(const Context&, ::IceInternal::BasicStream*) const;
+
+ static void threadDestructor(void*);
+
+ typedef std::vector<Context*> ContextVector;
+
+
+ static size_t _count;
+
+#ifdef _WIN32
+ static DWORD _key;
+#else
+ static pthread_key_t _key;
+#endif
+
+private:
+
+ Context* getThreadContext(bool) const;
+ void clearThreadContext() const;
+
+ size_t _index;
+};
+
+}
+
+
+/*static*/ ImplicitContextI*
+ImplicitContextI::create(const std::string& kind)
+{
+ if(kind == "None" || kind == "")
+ {
+ return 0;
+ }
+ else if(kind == "Shared")
+ {
+ return new SharedImplicitContext;
+ }
+ else if(kind == "SharedWithoutLocking")
+ {
+ return new SharedImplicitContextWithoutLocking;
+ }
+ else if(kind == "PerThread")
+ {
+ return new PerThreadImplicitContext;
+ }
+ else
+ {
+ throw Ice::InitializationException(
+ __FILE__, __LINE__,
+ "'" + kind + "' is not a valid value for Ice.ImplicitContext");
+ }
+}
+
+#ifdef _WIN32
+void
+ImplicitContextI::cleanupThread()
+{
+ if(PerThreadImplicitContext::_count > 0)
+ {
+ threadDestructor(TlsGetValue(PerThreadImplicitContext::_key));
+ }
+}
+#endif
+
+//
+// SharedImplicitContextWithoutLocking implementation
+//
+
+inline Context
+SharedImplicitContextWithoutLocking::getContext() const
+{
+ return _context;
+}
+
+inline void
+SharedImplicitContextWithoutLocking::setContext(const Context& newContext)
+{
+ _context = newContext;
+}
+
+inline string
+SharedImplicitContextWithoutLocking::get(const string& k) const
+{
+ Context::const_iterator p = _context.find(k);
+ if(p == _context.end())
+ {
+ throw NotSetException(__FILE__, __LINE__, k);
+ }
+ return p->second;
+}
+
+inline string
+SharedImplicitContextWithoutLocking::getWithDefault(const string& k, const string& d) const
+{
+ Context::const_iterator p = _context.find(k);
+ if(p == _context.end())
+ {
+ return d;
+ }
+ return p->second;
+}
+
+inline void
+SharedImplicitContextWithoutLocking::set(const string& k, const string& v)
+{
+ _context[k] = v;
+}
+
+inline void
+SharedImplicitContextWithoutLocking::remove(const string& k)
+{
+ if(_context.erase(k) == 0)
+ {
+ throw NotSetException(__FILE__, __LINE__, k);
+ }
+}
+
+void
+SharedImplicitContextWithoutLocking::write(const Context& proxyCtx, ::IceInternal::BasicStream* s) const
+{
+ if(proxyCtx.size() == 0)
+ {
+ __write(s, _context, __U__Context());
+ }
+ else if(_context.size() == 0)
+ {
+ __write(s, proxyCtx, __U__Context());
+ }
+ else
+ {
+ Context combined = proxyCtx;
+ combined.insert(_context.begin(), _context.end());
+ __write(s, combined, __U__Context());
+ }
+}
+
+
+//
+// SharedImplicitContext implementation
+//
+
+Context
+SharedImplicitContext::getContext() const
+{
+ IceUtil::Mutex::Lock lock(_mutex);
+ return SharedImplicitContextWithoutLocking::getContext();
+}
+
+void
+SharedImplicitContext::setContext(const Context& newContext)
+{
+ IceUtil::Mutex::Lock lock(_mutex);
+ SharedImplicitContextWithoutLocking::setContext(newContext);
+}
+
+string
+SharedImplicitContext::get(const string& k) const
+{
+ IceUtil::Mutex::Lock lock(_mutex);
+ return SharedImplicitContextWithoutLocking::get(k);
+}
+
+string
+SharedImplicitContext::getWithDefault(const string& k, const string& d) const
+{
+ IceUtil::Mutex::Lock lock(_mutex);
+ return SharedImplicitContextWithoutLocking::getWithDefault(k, d);
+}
+
+void
+SharedImplicitContext::set(const string& k, const string& v)
+{
+ IceUtil::Mutex::Lock lock(_mutex);
+ SharedImplicitContextWithoutLocking::set(k, v);
+}
+
+void
+SharedImplicitContext::remove(const string& k)
+{
+ IceUtil::Mutex::Lock lock(_mutex);
+ SharedImplicitContextWithoutLocking::remove(k);
+}
+
+void
+SharedImplicitContext::write(const Context& proxyCtx, ::IceInternal::BasicStream* s) const
+{
+ IceUtil::Mutex::Lock lock(_mutex);
+ if(proxyCtx.size() == 0)
+ {
+ __write(s, _context, __U__Context());
+ }
+ else if(_context.size() == 0)
+ {
+ lock.release();
+ __write(s, proxyCtx, __U__Context());
+ }
+ else
+ {
+ Context combined = proxyCtx;
+ combined.insert(_context.begin(), _context.end());
+ lock.release();
+ __write(s, combined, __U__Context());
+ }
+}
+
+//
+// PerThreadImplicitContext implementation
+//
+
+size_t PerThreadImplicitContext::_count;
+
+#ifdef _WIN32
+DWORD PerThreadImplicitContext::_key;
+#else
+pthread_key_t PerThreadImplicitContext::_key;
+#endif
+
+PerThreadImplicitContext::PerThreadImplicitContext()
+{
+ IceUtil::StaticMutex::Lock lock(IceUtil::globalMutex);
+ _index = _count++;
+ if(_index == 0)
+ {
+ //
+ // Initialize; note that we never dealloc this key (it would be
+ // complex, and since it's a static variable, it's not really a leak)
+ //
+#ifdef _WIN32
+ _key = TlsAlloc();
+ if(_key == TLS_OUT_OF_INDEXES)
+ {
+ throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, GetLastError());
+ }
+#else
+ int err = pthread_key_create(&_key, &threadDestructor);
+ if(err != 0)
+ {
+ throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, err);
+ }
+#endif
+ }
+}
+
+/*static*/ void
+PerThreadImplicitContext::threadDestructor(void* v)
+{
+ delete static_cast<ContextVector*>(v);
+}
+
+Context*
+PerThreadImplicitContext::getThreadContext(bool allocate) const
+{
+#ifdef _WIN32
+ ContextVector* val = static_cast<ContextVector*>(TlsGetValue(_key));
+#else
+ ContextVector* val = static_cast<ContextVector*>(pthread_getspecific(_key));
+#endif
+ if(val == 0)
+ {
+ if(!allocate)
+ {
+ return 0;
+ }
+
+ val = new std::vector<Context*>(_index);
+#ifdef _WIN32
+ if(TlsSetValue(_key, val) != 0)
+ {
+ throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, GetLastError());
+ }
+#else
+ if(int err = pthread_setspecific(_key, val))
+ {
+ throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, err);
+ }
+#endif
+ }
+ else
+ {
+ if(val->size() < _index)
+ {
+ if(!allocate)
+ {
+ return 0;
+ }
+ else
+ {
+ val->resize(_index + 1);
+ }
+ }
+ }
+
+ ContextVector& contextVector = *val;
+
+ Context* result = contextVector[_index];
+ if(result == 0 && allocate)
+ {
+ result = new Context;
+ contextVector[_index] = result;
+ }
+ return result;
+}
+
+void
+PerThreadImplicitContext::clearThreadContext() const
+{
+#ifdef _WIN32
+ ContextVector* val = static_cast<ContextVector*>(TlsGetValue(_key));
+#else
+ ContextVector* val = static_cast<ContextVector*>(pthread_getspecific(_key));
+#endif
+ if(val != 0 && val->size() < _index)
+ {
+ (*val)[_index] = 0;
+
+ int i = val->size() - 1;
+ while(i >= 0 && (*val)[i] == 0)
+ {
+ i--;
+ }
+ if(i < 0)
+ {
+ delete val;
+#ifdef _WIN32
+ if(!TlsSetValue(_key, 0))
+ {
+ IceUtil::ThreadSyscallException(__FILE__, __LINE__, GetLastError());
+ }
+#else
+ if(int err = pthread_setspecific(_key, 0))
+ {
+ throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, err);
+ }
+#endif
+ }
+ else
+ {
+ val->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);
+ *ctx = newContext;
+ }
+}
+
+string
+PerThreadImplicitContext::get(const string& k) const
+{
+ Context* ctx = getThreadContext(false);
+ if(ctx == 0)
+ {
+ throw NotSetException(__FILE__, __LINE__, k);
+ }
+ Context::const_iterator p = ctx->find(k);
+ if(p == ctx->end())
+ {
+ throw NotSetException(__FILE__, __LINE__, k);
+ }
+ return p->second;
+}
+
+string
+PerThreadImplicitContext::getWithDefault(const string& k, const string& d) const
+{
+ Context* ctx = getThreadContext(false);
+ if(ctx == 0)
+ {
+ return d;
+ }
+ Context::const_iterator p = ctx->find(k);
+ if(p == ctx->end())
+ {
+ return d;
+ }
+ return p->second;
+}
+
+void
+PerThreadImplicitContext::set(const string& k, const string& v)
+{
+ Context* ctx = getThreadContext(true);
+ (*ctx)[k] = v;
+}
+
+void
+PerThreadImplicitContext::remove(const string& k)
+{
+ Context* ctx = getThreadContext(false);
+ if(ctx == 0 || ctx->erase(k) == 0)
+ {
+ throw NotSetException(__FILE__, __LINE__, k);
+ }
+
+ if(ctx->size() == 0)
+ {
+ clearThreadContext();
+ }
+}
+
+void
+PerThreadImplicitContext::write(const Context& proxyCtx, ::IceInternal::BasicStream* s) const
+{
+ Context* ctx = getThreadContext(false);
+
+ if(ctx == 0 || ctx->size() == 0)
+ {
+ __write(s, proxyCtx, __U__Context());
+ }
+ else if(proxyCtx.size() == 0)
+ {
+ __write(s, *ctx, __U__Context());
+ }
+ else
+ {
+ Context combined = proxyCtx;
+ combined.insert(ctx->begin(), ctx->end());
+ __write(s, combined, __U__Context());
+ }
+}