summaryrefslogtreecommitdiff
path: root/src/thread
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2018-01-02 12:10:41 +0100
committerMax Kellermann <max@musicpd.org>2018-01-02 12:10:41 +0100
commit196df1ccd5ab747a82c0d4519cd285226e6ada6d (patch)
treeeba721c47dfcfee710f8c05fe29089a59d82c955 /src/thread
parentd2358b42b6d121da2b7b260607b7162c586a5f3a (diff)
thread/SafeSingleton: new thread-safe utility class
Diffstat (limited to 'src/thread')
-rw-r--r--src/thread/SafeSingleton.hxx82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/thread/SafeSingleton.hxx b/src/thread/SafeSingleton.hxx
new file mode 100644
index 000000000..ce2f4bb81
--- /dev/null
+++ b/src/thread/SafeSingleton.hxx
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2003-2017 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_SAFE_SINGLETON_HXX
+#define MPD_SAFE_SINGLETON_HXX
+
+#include "check.h"
+#include "Mutex.hxx"
+
+/**
+ * This class manages at most one instance of a specific type. All
+ * instances of this class share the one object which gets deleted
+ * when the last instance of this class is destructed.
+ *
+ * This class is thread-safe, but the contained class may not be.
+ */
+template<typename T>
+class SafeSingleton {
+ static Mutex mutex;
+ static unsigned ref;
+ static T *instance;
+
+public:
+ SafeSingleton() {
+ const std::lock_guard<Mutex> lock(mutex);
+
+ if (ref == 0)
+ instance = new T;
+
+ /* increment after creating the instance; this way is
+ exception-safe, because we must not increment the
+ reference counter if we throw */
+ ++ref;
+ }
+
+ ~SafeSingleton() noexcept {
+ const std::lock_guard<Mutex> lock(mutex);
+ if (--ref > 0)
+ return;
+
+ delete std::exchange(instance, nullptr);
+ }
+
+ T *get() {
+ return instance;
+ }
+
+ T &operator*() noexcept {
+ return *instance;
+ }
+
+ T *operator->() noexcept {
+ return instance;
+ }
+};
+
+template<typename T>
+Mutex SafeSingleton<T>::mutex;
+
+template<typename T>
+unsigned SafeSingleton<T>::ref;
+
+template<typename T>
+T *SafeSingleton<T>::instance;
+
+#endif