[asterisk-scf-commits] asterisk-scf/integration/ice-util-cpp.git branch "retry_deux" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Wed Apr 4 14:35:49 CDT 2012
branch "retry_deux" has been updated
via 31ebb4a34f9f0a4f3e1e6a0c18d655f38ebe4bed (commit)
via a2b337efe361062b487eb5172fd7e03e861e207f (commit)
via 5738e5a108f13ac7e547690b9c27f50bbaa6467e (commit)
from c1aee7ef1cdb3dbab3d4aacf89a5fbd11a89972e (commit)
Summary of changes:
include/AsteriskSCF/Operations/ExceptionWrapper.h | 16 +-
.../AsteriskSCF/Operations/OperationContextCache.h | 236 +++-----------------
include/AsteriskSCF/Operations/OperationMonitor.h | 65 +++++-
.../OperationContextCacheTest.cpp | 79 -------
4 files changed, 97 insertions(+), 299 deletions(-)
- Log -----------------------------------------------------------------
commit 31ebb4a34f9f0a4f3e1e6a0c18d655f38ebe4bed
Author: David M. Lee <dlee at digium.com>
Date: Wed Apr 4 13:42:04 2012 -0500
Removed ValueOperationContextCookie, and associated helpers
diff --git a/include/AsteriskSCF/Operations/OperationContextCache.h b/include/AsteriskSCF/Operations/OperationContextCache.h
index 75c7314..071bf2f 100644
--- a/include/AsteriskSCF/Operations/OperationContextCache.h
+++ b/include/AsteriskSCF/Operations/OperationContextCache.h
@@ -41,126 +41,6 @@ public:
};
typedef ASTSCF_DLL_EXPORT boost::shared_ptr<OperationContextCookie> OperationContextCookiePtr;
-/**
- * An OperationContextCookie which can hold a single, copyable value.
- * Ice proxies are very typical, as are literal values. Be careful when using
- * smart pointers, so that you don't change the contents of the stored value
- * behind the scenes.
- *
- * The value may also be set to an Ice exception, which will be thrown on the
- * call to get().
- *
- * The only constraints on T are 1) it must have a default constructor and 2)
- * must the assignment operator defined.
- */
-template<typename T>
-class ValueOperationContextCookie : public OperationContextCookie
-{
-public:
- ValueOperationContextCookie() : mPoorlyTypedException(false) {}
-
- /** Set the value of this cookie. */
- void set(const T& v)
- {
- boost::mutex::scoped_lock lock(mMutex);
- mVal = v;
- }
-
- /** Set the exception value of this cookie. */
- void setException(const std::exception& e)
- {
- boost::mutex::scoped_lock lock(mMutex);
- const IceUtil::Exception *iceEx = dynamic_cast<const IceUtil::Exception *>(&e);
- if (iceEx)
- {
- // Ice exceptions are clonable; copy it so we can rethrow the original
- // exception
- mEx.reset(iceEx->ice_clone());
- }
- else
- {
- // std::exception can't be copied. Fortunately, Ice doesn't really
- // care what it is if it's not an Ice exception. Just keep the
- // what() message for later.
- mStdExceptionWhat = e.what();
- }
- }
-
- /**
- * Set the cookie to throw an exception, but we don't know what that
- * exception is. Ideally, this code is never called at runtime, because
- * we never throw any type that's not derived from std::exception. But
- * we have to cover our bases.
- */
- void setException()
- {
- boost::mutex::scoped_lock lock(mMutex);
- mPoorlyTypedException = true;
- }
-
- /**
- * If setException has been called, throw that exception. Otherwise,
- * return the value of this cookie.
- */
- T get() const
- {
- boost::mutex::scoped_lock lock(mMutex);
- if (mEx)
- {
- mEx->ice_throw();
- }
- else if (!mStdExceptionWhat.empty())
- {
- // throw an exception with the same what() message as the original
- // exception
- throw StdException(mStdExceptionWhat);
- }
- else if (mPoorlyTypedException)
- {
- // someone throw a non-standard exception; we should, too.
- throw "Okay; who's throwing non-exception types?";
- }
- return mVal;
- }
-
-private:
- // This class has a very high write-to-read ratio, and the chance of two
- // reads happening concurrently are small. There would be no benefit from
- // a shared_mutex, so just using a plain mutex instead.
- mutable boost::mutex mMutex;
- T mVal;
-
- boost::shared_ptr<IceUtil::Exception> mEx;
- std::string mStdExceptionWhat;
- bool mPoorlyTypedException;
-
- class StdException : public std::exception
- {
- public:
- StdException(const std::string& wat): mWhat(wat) {}
- ~StdException() throw() {}
-
- const char* what() throw() { return mWhat.c_str(); }
- private:
- std::string mWhat;
- };
-};
-
-/**
- * A variation of ValueOperationContextCookie which has a mutex in addition to the
- * the return value/exception. This is useful for services that otherwise do not
- * require locking, but need synchronization on getting/setting the cookie's value.
- */
-template<typename T, typename M = boost::mutex>
-class ValueOperationContextCookieWithLock : public ValueOperationContextCookie<T>
-{
-public:
- M& getMutex() { return mMutex; }
-private:
- M mMutex;
-};
-
-
class OperationContextCache;
typedef boost::shared_ptr<OperationContextCache> OperationContextCachePtr;
@@ -173,75 +53,75 @@ public:
/**
* Factory method for non-logging cache.
* @param ttlSeconds The time-to-live for the OperationContexts being cached.
- * Entries will remain in the cache for at least the provided value, but can
- * remain in cache longer.
+ * Entries will remain in the cache for at least the provided value, but can
+ * remain in cache longer.
*/
static OperationContextCachePtr create(int ttlSeconds);
/**
* Factory method for logging cache.
* @param ttlSeconds The time-to-live for the OperationContexts being cached.
- * Entries will remain in the cache for at least the provided value, but can
- * remain in cache longer.
- * @param logger The logger to log to.
+ * Entries will remain in the cache for at least the provided value, but can
+ * remain in cache longer.
+ * @param logger The logger to log to.
* @param label Label to apply when logging to identify this cache.
*/
- static OperationContextCachePtr create(int ttlSeconds,
+ static OperationContextCachePtr create(int ttlSeconds,
const AsteriskSCF::System::Logging::Logger& logger,
const std::string& label);
~OperationContextCache();
/**
- * Caches the specified context if it isn't already in the cache.
+ * Caches the specified context if it isn't already in the cache.
*
- * @param operationContext The context to add to the cache.
+ * @param operationContext The context to add to the cache.
* @return true The context was added, which means it wasn't already in the cache.
*
* @note Make sure you don't confuse the return value of this operation with the return
- * value of the 'contains' operation.
+ * value of the 'contains' operation.
*/
bool addOperationContext(const AsteriskSCF::System::V1::OperationContextPtr& operationContext);
/**
- * Caches the specified context if it isn't already in the cache, and associate a cookie with it.
+ * Caches the specified context if it isn't already in the cache, and associate a cookie with it.
*
- * @param operationContext The context to add to the cache.
- * @param inCookie A cookie object to associate with this entry in the cache.
+ * @param operationContext The context to add to the cache.
+ * @param inCookie A cookie object to associate with this entry in the cache.
* @param existingCookie This value will be set by this method to the cookie of an existing
- * operationContext if there was already an entry in the cache with the same identity.
+ * operationContext if there was already an entry in the cache with the same identity.
* @return true The context was added, which means it wasn't already in the cache.
*
* @note Make sure you don't confuse the return value of this operation with the return
- * value of the 'contains' operation.
+ * value of the 'contains' operation.
*/
bool addOperationContext(
const AsteriskSCF::System::V1::OperationContextPtr& operationContext,
- const OperationContextCookiePtr& inCookie,
+ const OperationContextCookiePtr& inCookie,
OperationContextCookiePtr& existingCookie);
/**
- * Tests if the specified context is in the cache.
+ * Tests if the specified context is in the cache.
*/
bool contains(const AsteriskSCF::System::V1::OperationContextPtr& operationContext);
/**
- * This will remove an OperationContext from the cache if one exists with the given id.
- * Removal is typically done automatically within the cache based on an internal timer.
- * This operation exists to support clients that wish to force an immediate removal of a
- * context themselves.
+ * This will remove an OperationContext from the cache if one exists with the given id.
+ * Removal is typically done automatically within the cache based on an internal timer.
+ * This operation exists to support clients that wish to force an immediate removal of a
+ * context themselves.
*/
void removeOperationContext(const AsteriskSCF::System::V1::OperationContextPtr& operationContext);
/**
- * Drop entries that are older than the TTL.
+ * Drop entries that are older than the TTL.
* @note This method is called by an internal timer task, so clients
- * of this class don't need to call it. (There's no harm if a client does call it.)
+ * of this class don't need to call it. (There's no harm if a client does call it.)
*/
- void prune();
+ void prune();
/**
- * Retrieve the number of entries currently in the cache.
+ * Retrieve the number of entries currently in the cache.
*/
std::size_t size();
@@ -252,7 +132,7 @@ private:
//
OperationContextCache(int ttlSeconds);
- OperationContextCache(int ttlSeconds,
+ OperationContextCache(int ttlSeconds,
const AsteriskSCF::System::Logging::Logger& logger,
const std::string& label);
@@ -269,67 +149,5 @@ private:
std::map<std::string, OperationContextCacheEntryPtr> mCache;
};
-/**
- * Common access pattern for testing the cache for an entry. If the cache contains an entry for the
- * given context, this returns true and that entry. Otherwise, a new cookie of type T is built, put
- * into the cache, and false is returned with the new cookie.
- */
-template<typename T>
-std::pair<bool, boost::shared_ptr<T> > testOrSet(
- OperationContextCachePtr cache, const AsteriskSCF::System::V1::OperationContextPtr& context)
-{
- typedef boost::shared_ptr<T> TPtr;
- const TPtr cookie(new T);
- OperationContextCookiePtr existingCookie;
- cache->addOperationContext(cache, cookie, existingCookie);
-
- if (existingCookie)
- {
- TPtr c = boost::dynamic_pointer_cast<T>(existingCookie);
- assert(c);
- return std::make_pair(true, c);
- }
- return std::make_pair(false, cookie);
-}
-
-/**
- * Just like testOrSet above, but thread safe w.r.t. the cookie's mutex (available via the getMutex() member
- * function). Unfortunately, this function must lock the mutex, and the caller must release it. The recommended
- * pattern is:
- *
- * std::pair<bool, MyCookiePtr> cacheHit = testOrSetAndLock<MyCookie>(cache, context);
- * boost::mutex::scoped_lock lock(cacheHit.second->getMutex(), boost::adopt_lock);
- */
-template<typename T>
-std::pair<bool, boost::shared_ptr<T> > testOrSetAndLock(
- OperationContextCachePtr cache, const AsteriskSCF::System::V1::OperationContextPtr& context)
-{
- typedef boost::shared_ptr<T> TPtr;
- const TPtr cookie(new T);
- OperationContextCookiePtr existingCookie;
- // lock this cookie so that no one will get our results prematurely
- boost::mutex::scoped_lock lock(cookie->getMutex());
- cache->addOperationContext(context, cookie, existingCookie);
-
- if (existingCookie)
- {
- TPtr c = boost::dynamic_pointer_cast<T>(existingCookie);
- assert(c);
- // Even though we're holding a lock on cookie, it's never left this function; no one can be waiting on it.
- // There's no danger of deadlocking while waiting on the lock for existingCookie.
-
- // The caller needs to unlock this mutex when it's ready to return. boost's RAII lock guards
- // aren't the best fit; lock manually. However the lock guard on cookie's mutex will do the
- // right thing and unlock that mutex.
- c->getMutex().lock();
- return std::make_pair(true, c);
- }
-
- // The caller needs to unlock this mutex when it's ready to return state. Release the lock so the caller
- // can unlock when it's donw.
- lock.release();
- return std::make_pair(false, cookie);
-}
-
-} // Operations
-} // AsteriskSCF
+} // Operations
+} // AsteriskSCF
diff --git a/test/OperationContextCache/OperationContextCacheTest.cpp b/test/OperationContextCache/OperationContextCacheTest.cpp
index e3eaf0c..ad8a5c0 100644
--- a/test/OperationContextCache/OperationContextCacheTest.cpp
+++ b/test/OperationContextCache/OperationContextCacheTest.cpp
@@ -91,77 +91,6 @@ void runOperationContextCacheTest()
testOperations.clear();
}
-void ValueOperationContextCookie_valueTest()
-{
- ValueOperationContextCookie<int> uut;
-
- uut.set(5);
-
- BOOST_REQUIRE_EQUAL(5, uut.get());
-}
-
-void ValueOperationContextCookie_iceExceptionTest()
-{
- ValueOperationContextCookie<int> uut;
- IceUtil::NullHandleException e("not-a-file.cpp", 314159);
-
- uut.setException(e);
-
- try
- {
- uut.get();
- }
- catch (const IceUtil::NullHandleException&)
- {
- // expected
- }
-}
-
-void ValueOperationContextCookie_stdExceptionTest()
-{
- ValueOperationContextCookie<int> uut;
- PhonyException e;
-
- uut.setException(e);
-
- try
- {
- uut.get();
- }
- catch (const Ice::Exception&)
- {
- BOOST_FAIL("Unexpected Ice exception");
- }
- catch (const std::exception&)
- {
- // expected
- }
-}
-
-void ValueOperationContextCookie_untypedExceptionTest()
-{
- ValueOperationContextCookie<int> uut;
-
- uut.setException();
-
- try
- {
- uut.get();
- }
- catch (const Ice::Exception&)
- {
- BOOST_FAIL("Unexpected Ice exception");
- }
- catch (const std::exception&)
- {
- BOOST_FAIL("Unexpected std::exception");
- }
- catch (...)
- {
- // expected
- }
-}
-
} // anonymous namespace
using namespace boost::unit_test;
@@ -170,12 +99,4 @@ AsteriskSCF::OperationContextCacheTests::OperationContextCacheTestSuite::Operati
{
framework::master_test_suite().
add(BOOST_TEST_CASE(runOperationContextCacheTest));
- framework::master_test_suite().
- add(BOOST_TEST_CASE(ValueOperationContextCookie_valueTest));
- framework::master_test_suite().
- add(BOOST_TEST_CASE(ValueOperationContextCookie_iceExceptionTest));
- framework::master_test_suite().
- add(BOOST_TEST_CASE(ValueOperationContextCookie_stdExceptionTest));
- framework::master_test_suite().
- add(BOOST_TEST_CASE(ValueOperationContextCookie_untypedExceptionTest));
}
commit a2b337efe361062b487eb5172fd7e03e861e207f
Author: David M. Lee <dlee at digium.com>
Date: Wed Apr 4 13:41:19 2012 -0500
OperationMonitor additions to make non-AMD usage easier.
diff --git a/include/AsteriskSCF/Operations/ExceptionWrapper.h b/include/AsteriskSCF/Operations/ExceptionWrapper.h
index c4d5659..76a3a10 100755
--- a/include/AsteriskSCF/Operations/ExceptionWrapper.h
+++ b/include/AsteriskSCF/Operations/ExceptionWrapper.h
@@ -63,9 +63,19 @@ public:
* occurs.
*/
explicit
- ExceptionWrapper(const std::exception& ex) :
- mException(new Ice::UnknownException(__FILE__, __LINE__, ex.what()))
+ ExceptionWrapper(const std::exception& ex)
{
+ // properly handle the case where ex is actually an IceUtil::Exception
+ const IceUtil::Exception* iceEx = dynamic_cast<const IceUtil::Exception*>(&ex);
+
+ if (iceEx)
+ {
+ mException.reset(iceEx->ice_clone());
+ }
+ else
+ {
+ mException.reset(new Ice::UnknownException(__FILE__, __LINE__, ex.what()));
+ }
}
/**
diff --git a/include/AsteriskSCF/Operations/OperationMonitor.h b/include/AsteriskSCF/Operations/OperationMonitor.h
index c53c7f9..8e3cda0 100755
--- a/include/AsteriskSCF/Operations/OperationMonitor.h
+++ b/include/AsteriskSCF/Operations/OperationMonitor.h
@@ -109,6 +109,19 @@ public:
void setException(const ExceptionWrapperPtr& exception);
+ void setException(const std::exception& exception)
+ {
+ setException(ExceptionWrapper::create(exception));
+ }
+
+ void setException()
+ {
+ // All exceptions _should_ derive from std::exception, so we really
+ // should never get here. but not everyone does what they should,
+ // do they.
+ setException(ExceptionWrapper::create("Unknown unexpected exception"));
+ }
+
/**
* A quick, single point accessor to determine the completion
* statius of the related operation. The alternative would be to
@@ -502,12 +515,21 @@ private:
ASTSCF_DLL_EXPORT ContextDataPtr checkAndThrow(const AsteriskSCF::Operations::OperationContextCachePtr& cache,
const AsteriskSCF::System::V1::OperationContextPtr& context);
-
-template <class DT, class AT>
-ASTSCF_DLL_EXPORT DT getContext(const AsteriskSCF::Operations::OperationContextCachePtr& cache,
- const AsteriskSCF::System::V1::OperationContextPtr& context,
- const AT& amdCallback)
+/**
+ * Gets a OperationContextCookie subclass for a given context, creating it if necessary. This is useful for
+ * non-AMD invocations that return a value.
+ *
+ * @param DT a boost::shared_ptr to the OperationContextCookie subclass
+ * @param cache Cache to get cookie from
+ * @param context Context to look up in cache
+ * @return A pair indicating true if it was a cache hit, and the cookie that's now in the cache for the given
+ * context
+ */
+template <class DT>
+ASTSCF_DLL_EXPORT std::pair<bool, DT> getContextSync(const AsteriskSCF::Operations::OperationContextCachePtr& cache,
+ const AsteriskSCF::System::V1::OperationContextPtr& context)
{
+ bool cacheHit = false;
DT c(new typename DT::element_type);
AsteriskSCF::Operations::OperationContextCookiePtr o;
@@ -515,11 +537,38 @@ ASTSCF_DLL_EXPORT DT getContext(const AsteriskSCF::Operations::OperationContextC
{
c = boost::dynamic_pointer_cast<typename DT::element_type>(o);
assert(c);
- c->addCB(amdCallback);
+ cacheHit = true;
+ }
+ return std::make_pair(cacheHit, c);
+}
+
+/**
+ * Gets a OperationContextCookie subclass for a given context, creating it if necessary.
+ *
+ * If the context is already in the cache, the amdCallback is added to the existing cookie and null is
+ * returned; nothing else need be done.
+ *
+ * If the context is not in the cache, a new cookie is created, the amdCallback is added to it, and the
+ * new cookie is returned. The caller then needs to complete normal execution, and either setException() or
+ * setResult() on the cookie when finished.
+ */
+template <class DT, class AT>
+ASTSCF_DLL_EXPORT DT getContext(const AsteriskSCF::Operations::OperationContextCachePtr& cache,
+ const AsteriskSCF::System::V1::OperationContextPtr& context,
+ const AT& amdCallback)
+{
+ std::pair<bool, DT> cacheHit = getContextSync<DT>(cache, context);
+
+ cacheHit.second->addCB(amdCallback);
+
+ if (cacheHit.first)
+ {
return DT();
}
- c->addCB(amdCallback);
- return c;
+ else
+ {
+ return cacheHit.second;
+ }
}
} /* End of namespace Operations */
commit 5738e5a108f13ac7e547690b9c27f50bbaa6467e
Author: David M. Lee <dlee at digium.com>
Date: Wed Apr 4 09:50:05 2012 -0500
Fixed a copyright statement
diff --git a/include/AsteriskSCF/Operations/ExceptionWrapper.h b/include/AsteriskSCF/Operations/ExceptionWrapper.h
index 52d4a43..c4d5659 100755
--- a/include/AsteriskSCF/Operations/ExceptionWrapper.h
+++ b/include/AsteriskSCF/Operations/ExceptionWrapper.h
@@ -1,7 +1,7 @@
/*
* Asterisk SCF -- An open-source communications framework.
*
- * Copyright (C) 2010-2011, Digium, Inc.
+ * Copyright (C) 2012, Digium, Inc.
*
* See http://www.asterisk.org for more information about
* the Asterisk SCF project. Please do not directly contact
-----------------------------------------------------------------------
--
asterisk-scf/integration/ice-util-cpp.git
More information about the asterisk-scf-commits
mailing list