Add generic cache for IDispatch objects
authorAndre Heinecke <aheinecke@intevation.de>
Wed, 29 Aug 2018 08:24:14 +0000 (10:24 +0200)
committerAndre Heinecke <aheinecke@intevation.de>
Wed, 29 Aug 2018 08:24:14 +0000 (10:24 +0200)
* src/dispcache.cpp, src/dispcache.h: New.
* src/gpgoladdin.cpp, src/gpgoladdin.h: Carry dispcache as
member.
* src/Makefile.am: Add new Files.

--
The cache shares the lifetime of the addin object and
can be used to keep IDispatch object around without having
to create them again and again.

src/Makefile.am
src/dispcache.cpp [new file with mode: 0644]
src/dispcache.h [new file with mode: 0644]
src/gpgoladdin.cpp
src/gpgoladdin.h

index 599394f..7906794 100644 (file)
@@ -35,6 +35,7 @@ gpgol_SOURCES = \
     cpphelp.cpp cpphelp.h \
     cryptcontroller.cpp cryptcontroller.h \
     dialogs.h \
+    dispcache.h dispcache.cpp \
     eventsink.h \
     eventsinks.h \
     exechelp.c exechelp.h \
diff --git a/src/dispcache.cpp b/src/dispcache.cpp
new file mode 100644 (file)
index 0000000..7b1bbf3
--- /dev/null
@@ -0,0 +1,114 @@
+/* Copyright (C) 2018 Intevation GmbH
+ *
+ * This file is part of GpgOL.
+ *
+ * GpgOL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GpgOL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dispcache.h"
+#include "gpg-error.h"
+
+#include "common.h"
+#include "gpgoladdin.h"
+
+#include <unordered_map>
+
+GPGRT_LOCK_DEFINE (cache_lock);
+
+class DispCache::Private
+{
+public:
+  Private()
+    {
+
+    }
+
+  void addDisp (int id, LPDISPATCH obj)
+   {
+     if (!id || !obj)
+       {
+         TRACEPOINT;
+         return;
+       }
+     gpgrt_lock_lock (&cache_lock);
+     auto it = m_cache.find (id);
+     if (it != m_cache.end ())
+       {
+         log_debug ("%s:%s Item \"%i\" already cached. Replacing it.",
+                    SRCNAME, __func__, id);
+         gpgol_release (it->second);
+         it->second = obj;
+         gpgrt_lock_unlock (&cache_lock);
+         return;
+       }
+     m_cache.insert (std::make_pair (id, obj));
+     gpgrt_lock_unlock (&cache_lock);
+     return;
+   }
+
+  LPDISPATCH getDisp (int id)
+    {
+      if (!id)
+        {
+          TRACEPOINT;
+          return nullptr;
+        }
+      gpgrt_lock_lock (&cache_lock);
+
+      const auto it = m_cache.find (id);
+      if (it != m_cache.end())
+        {
+          LPDISPATCH ret = it->second;
+          gpgrt_lock_unlock (&cache_lock);
+          return ret;
+        }
+      gpgrt_lock_unlock (&cache_lock);
+      return nullptr;
+    }
+
+  ~Private ()
+    {
+      gpgrt_lock_lock (&cache_lock);
+      for (const auto it: m_cache)
+        {
+          gpgol_release (it.second);
+        }
+      gpgrt_lock_unlock (&cache_lock);
+    }
+
+private:
+  std::unordered_map<int, LPDISPATCH> m_cache;
+};
+
+DispCache::DispCache (): d (new Private)
+{
+}
+
+void
+DispCache::addDisp (int id, LPDISPATCH obj)
+{
+  d->addDisp (id, obj);
+}
+
+LPDISPATCH
+DispCache::getDisp (int id)
+{
+  return d->getDisp (id);
+}
+
+DispCache *
+DispCache::instance ()
+{
+  return GpgolAddin::get_instance ()->get_dispcache ().get ();
+}
diff --git a/src/dispcache.h b/src/dispcache.h
new file mode 100644 (file)
index 0000000..465665d
--- /dev/null
@@ -0,0 +1,60 @@
+/* @file dispcache.h
+ * @brief Cache for IDispatch objects that are reusable.
+ *
+ * Copyright (C) 2018 Intevation GmbH
+ *
+ * This file is part of GpgOL.
+ *
+ * GpgOL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GpgOL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef DISPCACHE_H
+#define DISPCACHE_H
+
+#include "config.h"
+
+#include <memory>
+
+#include "oomhelp.h"
+
+class GpgolAddin;
+
+class DispCache
+{
+    friend class GpgolAddin;
+protected:
+    DispCache ();
+
+public:
+    /* Accessor. Returns the instance carried by
+       gpgoladdin. */
+    static DispCache *instance ();
+
+    /* Add a IDispatch with the id id to the cache.
+
+       The IDispatch is released on destruction of
+       the cache.
+
+       Id's are meant to be defined in dialogs.h
+    */
+    void addDisp (int id, LPDISPATCH obj);
+
+    /* Get the according IDispatch object. */
+    LPDISPATCH getDisp (int id);
+
+private:
+    class Private;
+    std::shared_ptr<Private> d;
+};
+
+#endif
index abf8e71..e331b86 100644 (file)
@@ -47,6 +47,7 @@
 #include "mail.h"
 #include "addin-options.h"
 #include "cpphelp.h"
+#include "dispcache.h"
 
 #include <gpg-error.h>
 #include <list>
@@ -178,7 +179,8 @@ GpgolAddin::GpgolAddin (void) : m_lRef(0),
   m_explorersEventSink(nullptr),
   m_disabled(false),
   m_shutdown(false),
-  m_hook(nullptr)
+  m_hook(nullptr),
+  m_dispcache(new DispCache)
 {
   read_options ();
   /* RibbonExtender is it's own object to avoid the pitfalls of
index a8c121b..1641942 100644 (file)
 #include "mymapi.h"
 
 #include <vector>
+#include <memory>
 
 class GpgolAddinRibbonExt;
 class ApplicationEventListener;
+class DispCache;
 
 /* Enums for the IDTExtensibility2 interface*/
 typedef enum
@@ -212,6 +214,7 @@ public:
      crypto mails. */
   void shutdown ();
   LPDISPATCH get_application () { return m_application; }
+  std::shared_ptr<DispCache> get_dispcache () { return m_dispcache; }
   bool isShutdown() { return m_shutdown; };
 
 private:
@@ -227,6 +230,7 @@ private:
   bool m_shutdown;
   HHOOK m_hook;
   std::vector<LPDISPATCH> m_explorerEventSinks;
+  std::shared_ptr<DispCache> m_dispcache;
 };
 
 class GpgolAddinFactory: public IClassFactory