You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2018/04/09 21:08:30 UTC

[trafficserver] branch master updated: Add wrapper class for TSCont to CPPAPI.

This is an automated email from the ASF dual-hosted git repository.

amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 358d38f  Add wrapper class for TSCont to CPPAPI.
358d38f is described below

commit 358d38fa576076ee2e124e5f00b037dade466657
Author: Walt Karas <wk...@yahoo-inc.com>
AuthorDate: Thu Mar 15 18:04:21 2018 +0000

    Add wrapper class for TSCont to CPPAPI.
---
 lib/cppapi/Continuation.cc                  |  39 ++++++++
 lib/cppapi/Makefile.am                      |   2 +
 lib/cppapi/include/atscppapi/Continuation.h | 145 ++++++++++++++++++++++++++++
 plugins/test_cppapi/Makefile.inc            |   1 +
 plugins/test_cppapi/test_cppapi.cc          | 135 ++++++++++++++++++++++----
 5 files changed, 301 insertions(+), 21 deletions(-)

diff --git a/lib/cppapi/Continuation.cc b/lib/cppapi/Continuation.cc
new file mode 100644
index 0000000..9c3fc8c
--- /dev/null
+++ b/lib/cppapi/Continuation.cc
@@ -0,0 +1,39 @@
+/**
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+/**
+ * @file Continuation.cc
+ */
+
+#include <atscppapi/Continuation.h>
+
+namespace atscppapi
+{
+int
+Continuation::_generalEventFunc(TSCont cont, TSEvent event, void *edata)
+{
+  TSReleaseAssert(cont != nullptr);
+
+  Continuation *p = static_cast<Continuation *>(TSContDataGet(cont));
+
+  TSReleaseAssert(p != nullptr);
+
+  return p->_run(event, edata);
+}
+
+} // end namespace atscppapi
diff --git a/lib/cppapi/Makefile.am b/lib/cppapi/Makefile.am
index 87716fc..ba09c95 100644
--- a/lib/cppapi/Makefile.am
+++ b/lib/cppapi/Makefile.am
@@ -25,6 +25,7 @@ libatscppapi_la_SOURCES = \
 	AsyncTimer.cc \
 	CaseInsensitiveStringComparator.cc \
 	ClientRequest.cc \
+	Continuation.cc \
 	GlobalPlugin.cc \
 	GzipDeflateTransformation.cc \
 	GzipInflateTransformation.cc \
@@ -54,6 +55,7 @@ library_include_HEADERS = \
 	$(base_include_folder)/AsyncTimer.h \
 	$(base_include_folder)/CaseInsensitiveStringComparator.h \
 	$(base_include_folder)/ClientRequest.h \
+	$(base_include_folder)/Continuation.h \
 	$(base_include_folder)/GlobalPlugin.h \
 	$(base_include_folder)/GzipDeflateTransformation.h \
 	$(base_include_folder)/GzipInflateTransformation.h \
diff --git a/lib/cppapi/include/atscppapi/Continuation.h b/lib/cppapi/include/atscppapi/Continuation.h
new file mode 100644
index 0000000..dabd1cc
--- /dev/null
+++ b/lib/cppapi/include/atscppapi/Continuation.h
@@ -0,0 +1,145 @@
+/**
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+/**
+ * @file Continuation.h
+ * @brief Wrapper class for TS API type TSCont.
+ */
+
+#pragma once
+
+#include <ts/ts.h>
+
+namespace atscppapi
+{
+class Continuation
+{
+public:
+  using Mutex = TSMutex;
+
+  using Action = TSAction;
+
+  // Create continuation, mutexp may be nullptr.
+  //
+  explicit Continuation(Mutex mutexp) : _cont(TSContCreate(_generalEventFunc, mutexp))
+  {
+    TSContDataSet(_cont, static_cast<void *>(this));
+  }
+
+  // Create "empty" continuation, can only be populated by move assignement.
+  //
+  Continuation() : _cont(nullptr) {}
+
+  TSCont
+  asTSCont() const
+  {
+    return _cont;
+  }
+
+  // Get mutex (for "non-empty" continuation).
+  //
+  Mutex
+  mutex()
+  {
+    return _cont ? TSContMutexGet(_cont) : nullptr;
+  }
+
+  void
+  destroy()
+  {
+    if (_cont) {
+      TSContDestroy(_cont);
+      _cont = nullptr;
+    }
+  }
+
+  virtual ~Continuation()
+  {
+    if (_cont) {
+      TSContDestroy(_cont);
+    }
+  }
+
+  // No copying.
+  Continuation(const Continuation &) = delete;
+  Continuation &operator=(const Continuation &) = delete;
+
+  // Moving allowed.
+  Continuation(Continuation &&that)
+  {
+    _cont      = that._cont;
+    that._cont = nullptr;
+    TSContDataSet(_cont, static_cast<void *>(this));
+  }
+  Continuation &
+  operator=(Continuation &&that)
+  {
+    if (&that != this) {
+      if (_cont) {
+        TSContDestroy(_cont);
+      }
+      _cont      = that._cont;
+      that._cont = nullptr;
+      TSContDataSet(_cont, static_cast<void *>(this));
+    }
+    return *this;
+  }
+
+  explicit operator bool() const { return _cont != nullptr; }
+
+  int
+  call(TSEvent event, void *edata = nullptr)
+  {
+    return TSContCall(_cont, event, edata);
+  }
+
+  // Timeout of zero means no timeout.
+  //
+  Action
+  schedule(TSEvent event, TSHRTime timeout = 0, TSThreadPool tp = TS_THREAD_POOL_DEFAULT)
+  {
+    return TSContSchedule(_cont, timeout, tp);
+  }
+
+  // Timeout of zero means no timeout.
+  //
+  Action
+  httpSchedule(TSEvent event, TSHttpTxn httpTransactionp, TSHRTime timeout = 0)
+  {
+    return TSHttpSchedule(_cont, httpTransactionp, timeout);
+  }
+
+  Action
+  scheduleEvery(TSEvent event, TSHRTime interval /* milliseconds */, TSThreadPool tp = TS_THREAD_POOL_DEFAULT)
+  {
+    return TSContScheduleEvery(_cont, interval, tp);
+  }
+
+protected:
+  // Distinct continuation behavior is acheived by overriding this function in a derived continutation type.
+  //
+  virtual int _run(TSEvent event, void *edata) = 0;
+
+  // This is the event function for all continuations in C++ plugins.
+  //
+  static int _generalEventFunc(TSCont cont, TSEvent event, void *edata);
+
+  TSCont _cont;
+};
+
+} // end namespace atscppapi
diff --git a/plugins/test_cppapi/Makefile.inc b/plugins/test_cppapi/Makefile.inc
index d1a7c97..42a0e7a 100644
--- a/plugins/test_cppapi/Makefile.inc
+++ b/plugins/test_cppapi/Makefile.inc
@@ -15,4 +15,5 @@
 #  limitations under the License.
 
 pkglib_LTLIBRARIES += test_cppapi/test_cppapi.la
+test_cppapi_test_cppapi_la_LIBADD = $(top_builddir)/lib/cppapi/libatscppapi.la
 test_cppapi_test_cppapi_la_SOURCES = test_cppapi/test_cppapi.cc
diff --git a/plugins/test_cppapi/test_cppapi.cc b/plugins/test_cppapi/test_cppapi.cc
index 5de22c9..5a72ffe 100644
--- a/plugins/test_cppapi/test_cppapi.cc
+++ b/plugins/test_cppapi/test_cppapi.cc
@@ -16,19 +16,22 @@
  * limitations under the License.
  */
 
-#include <sstream>
 #include <vector>
+#include <utility>
+#include <sstream>
 
 #include <ts/ts.h>
 
 #include <ts/TextView.h>
 
+#include <atscppapi/Continuation.h>
+
 // TSReleaseAssert() doesn't seem to produce any logging output for a debug build, so do both kinds of assert.
 //
-#define ASS(EXPR)          \
-  {                        \
-    TSAssert(EXPR);        \
-    TSReleaseAssert(EXPR); \
+#define ALWAYS_ASSERT(EXPR) \
+  {                         \
+    TSAssert(EXPR);         \
+    TSReleaseAssert(EXPR);  \
   }
 
 std::vector<void (*)()> testList;
@@ -41,31 +44,121 @@ struct ATest {
 //
 #define TEST(TEST_FUNC) ATest t(TEST_FUNC);
 
-#define TNS_(LN) TestNamespaceName##LN
-
-// Generate a unique name for a separate namespace for each test.
-//
-#define TNS namespace TNS_(__LINE__)
-
 // TextView test. This is not testing the actual TextView code, just that it works to call functions in TextView.cc in the core
 // from a plugin.
 //
-TNS
+namespace TextViewTest
 {
-  void f()
-  {
-    ts::TextView tv("abcdefg");
+void
+f()
+{
+  ts::TextView tv("abcdefg");
+
+  std::ostringstream oss;
+
+  oss << tv;
+
+  ALWAYS_ASSERT(ts::memcmp(ts::TextView(oss.str()), tv) == 0)
+}
+
+TEST(f)
+
+} // end namespace TextViewTest
+
+// Test for Continuation class.
+//
+namespace ContinuationTest
+{
+struct {
+  TSEvent event;
+  void *edata;
+} passedToEventFunc;
+
+bool
+checkPassed(TSEvent event, void *edata)
+{
+  return (passedToEventFunc.event == event) and (passedToEventFunc.edata == edata);
+}
+
+class TestCont : public atscppapi::Continuation
+{
+public:
+  TestCont(Mutex m) : atscppapi::Continuation(m) {}
 
-    std::ostringstream oss;
+  TestCont() = default;
 
-    oss << tv;
+private:
+  int
+  _run(TSEvent event, void *edata) override
+  {
+    passedToEventFunc.event = event;
+    passedToEventFunc.edata = edata;
 
-    ASS(ts::memcmp(ts::TextView(oss.str()), tv) == 0)
+    return 666;
   }
+};
+
+void
+f()
+{
+  TestCont::Mutex m(TSMutexCreate());
+
+  TestCont c(m);
+
+  ALWAYS_ASSERT(!!c)
+  ALWAYS_ASSERT(c.asTSCont() != nullptr)
+  ALWAYS_ASSERT(c.mutex() == m)
+
+  TestCont c2(std::move(c));
+
+  ALWAYS_ASSERT(!!c2)
+  ALWAYS_ASSERT(c2.asTSCont() != nullptr)
+  ALWAYS_ASSERT(c2.mutex() == m)
+
+  ALWAYS_ASSERT(!c)
+  ALWAYS_ASSERT(c.asTSCont() == nullptr)
+  ALWAYS_ASSERT(c.mutex() == nullptr)
+
+  TestCont c3;
+
+  ALWAYS_ASSERT(!c3)
+  ALWAYS_ASSERT(c3.asTSCont() == nullptr)
+  ALWAYS_ASSERT(c3.mutex() == nullptr)
+
+  c3 = std::move(c2);
+
+  ALWAYS_ASSERT(!!c3)
+  ALWAYS_ASSERT(c3.asTSCont() != nullptr)
+  ALWAYS_ASSERT(c3.mutex() == m)
+
+  ALWAYS_ASSERT(!c2)
+  ALWAYS_ASSERT(c2.asTSCont() == nullptr)
+  ALWAYS_ASSERT(c2.mutex() == nullptr)
+
+  c3.destroy();
+
+  ALWAYS_ASSERT(!c3)
+  ALWAYS_ASSERT(c3.asTSCont() == nullptr)
+  ALWAYS_ASSERT(c3.mutex() == nullptr)
+
+  c = TestCont(m);
+
+  ALWAYS_ASSERT(!!c)
+  ALWAYS_ASSERT(c.asTSCont() != nullptr)
+  ALWAYS_ASSERT(c.mutex() == m)
+
+  ALWAYS_ASSERT(c.call(TS_EVENT_INTERNAL_206) == 666)
+  ALWAYS_ASSERT(checkPassed(TS_EVENT_INTERNAL_206, nullptr))
+
+  int dummy;
+
+  ALWAYS_ASSERT(c.call(TS_EVENT_INTERNAL_207, &dummy) == 666)
+  ALWAYS_ASSERT(checkPassed(TS_EVENT_INTERNAL_207, &dummy))
+}
 
-  TEST(f)
+TEST(f)
 
-} // end TNS namespace
+} // end namespace ContinuationTest
 
 // Run all the tests.
 //
@@ -78,7 +171,7 @@ TSPluginInit(int, const char **)
   info.vendor_name   = "Apache Software Foundation";
   info.support_email = "dev@trafficserver.apache.org";
 
-  ASS(TSPluginRegister(&info) == TS_SUCCESS)
+  ALWAYS_ASSERT(TSPluginRegister(&info) == TS_SUCCESS)
 
   for (auto fp : testList) {
     fp();

-- 
To stop receiving notification emails like this one, please contact
amc@apache.org.