diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2023-02-15 11:15:00 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2023-02-15 13:31:11 +0000 |
commit | 83fffbbd5eda463c4e344016bfec74fa5b2020c2 (patch) | |
tree | 63068a811645edc83f23e972464dc8c9f0b0715a /include | |
parent | 1f43a0dd760ad832ab6963d670ba13f0f43900fe (diff) |
new comphelper::SingletonRef
to replace salhelper::SingletonRef, but using a std::mutex instead of an
osl::Mutex
Change-Id: Ibf88a3778f47300c08b8ec9ee58ed24eb83aed7b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147046
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'include')
-rw-r--r-- | include/comphelper/singletonref.hxx | 161 | ||||
-rw-r--r-- | include/connectivity/DriversConfig.hxx | 4 | ||||
-rw-r--r-- | include/connectivity/sqlparse.hxx | 4 |
3 files changed, 165 insertions, 4 deletions
diff --git a/include/comphelper/singletonref.hxx b/include/comphelper/singletonref.hxx new file mode 100644 index 000000000000..5e90fc78cdc1 --- /dev/null +++ b/include/comphelper/singletonref.hxx @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#pragma once + +#include <sal/config.h> +#include <osl/diagnose.h> +#include <cstddef> +#include <mutex> + +namespace comphelper +{ +/** @short Template for implementing singleton classes. + This is a replacement for salhelper::SingletonRef, but which uses std::mutex instead of osl::Mutex. + + Such classes can be instantiated every time they + are needed. But the internal wrapped object will + be created one times only. Of course it's used + resources are referenced one times only too. + This template hold it alive till the last + reference is gone. Further all operations + on this reference are threadsafe. Only + calls directly to the internal object (which modify + its state) must be made threadsafe by the object itself + or from outside. + + @attention To prevent the code against race conditions, it's not + allowed to start operations inside the ctor + of the internal wrapped object - especially operations + which needs a reference to the same singleton too. + + The only chance to suppress such strange constellations + is a lazy-init mechanism. + + <ul> + <li>a) The singleton class can provide a special init() + method, which must be called as first after creation.</li> + <li>b) The singleton class can call a special impl_init() + method implicit for every called interface method.</li> + </ul> + + Note further that this singleton pattern can work only, if + all user of such singleton are located inside the same library! + Because static values can't be exported - e.g. from windows libraries. + */ +template <class SingletonClass> class SingletonRef +{ + // member + +private: + /** @short pointer to the internal wrapped singleton. */ + static SingletonClass* m_pInstance; + + /** @short ref count, which regulate creation and removing of m_pInstance. */ + static sal_Int32 m_nRef; + + // interface + +public: + /** @short standard ctor. + + The internal wrapped object is created only, + if its ref count was 0. Otherwise this method + does nothing ... except increasing of the internal + ref count! + */ + SingletonRef() + { + // GLOBAL SAFE -> + std::unique_lock aLock(SingletonRef::ownStaticLock()); + + // must be increased before(!) the check is done. + // Otherwise this check can fail inside the same thread ... + ++m_nRef; + if (m_nRef == 1) + m_pInstance = new SingletonClass(); + + OSL_ENSURE(m_nRef > 0 && m_pInstance, + "Race? Ref count of singleton >0, but instance is NULL!"); + // <- GLOBAL SAFE + } + + /** @short standard dtor. + + The internal wrapped object is removed only, + if its ref count will be 0. Otherwise this method + does nothing ... except decreasing of the internal + ref count! + */ + ~SingletonRef() + { + // GLOBAL SAFE -> + std::unique_lock aLock(SingletonRef::ownStaticLock()); + + // must be decreased before(!) the check is done. + // Otherwise this check can fail inside the same thread ... + --m_nRef; + if (m_nRef == 0) + { + delete m_pInstance; + m_pInstance = nullptr; + } + // <- GLOBAL SAFE + } + + SingletonRef& operator=(SingletonRef const&) = default; + + /** @short Allows rSingle->someBodyOp(). + */ + SingletonClass* operator->() const + { + // GLOBAL SAFE -> + std::unique_lock aLock(SingletonRef::ownStaticLock()); + return m_pInstance; + // <- GLOBAL SAFE + } + + /** @short Allows (*rSingle).someBodyOp(). + */ + SingletonClass& operator*() const + { + // GLOBAL SAFE -> + std::unique_lock aLock(SingletonRef::ownStaticLock()); + return *m_pInstance; + // <- GLOBAL SAFE + } + + // helper + +private: + SingletonRef(SingletonRef&) = delete; + + static std::mutex& ownStaticLock() + { + static std::mutex aInstance; + return aInstance; + } +}; + +template <class SingletonClass> SingletonClass* SingletonRef<SingletonClass>::m_pInstance = nullptr; + +template <class SingletonClass> sal_Int32 SingletonRef<SingletonClass>::m_nRef = 0; + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/connectivity/DriversConfig.hxx b/include/connectivity/DriversConfig.hxx index 239259313a72..8dd8d23ca846 100644 --- a/include/connectivity/DriversConfig.hxx +++ b/include/connectivity/DriversConfig.hxx @@ -26,7 +26,7 @@ #include <com/sun/star/uno/Sequence.h> #include <connectivity/dbtoolsdllapi.hxx> -#include <salhelper/singletonref.hxx> +#include <comphelper/singletonref.hxx> #include <comphelper/namedvaluecollection.hxx> #include <unotools/confignode.hxx> @@ -56,7 +56,7 @@ namespace connectivity class OOO_DLLPUBLIC_DBTOOLS DriversConfig { - typedef salhelper::SingletonRef<DriversConfigImpl> OSharedConfigNode; + typedef comphelper::SingletonRef<DriversConfigImpl> OSharedConfigNode; const ::comphelper::NamedValueCollection& impl_get(std::u16string_view _sURL,sal_Int32 _nProps) const; public: diff --git a/include/connectivity/sqlparse.hxx b/include/connectivity/sqlparse.hxx index 7e55d41e339f..0a8523e436a8 100644 --- a/include/connectivity/sqlparse.hxx +++ b/include/connectivity/sqlparse.hxx @@ -28,7 +28,7 @@ #include <connectivity/IParseContext.hxx> #include <connectivity/dbtoolsdllapi.hxx> #include <connectivity/sqlerror.hxx> -#include <salhelper/singletonref.hxx> +#include <comphelper/singletonref.hxx> #include <map> @@ -94,7 +94,7 @@ namespace connectivity void clearAndDelete(); }; - typedef salhelper::SingletonRef<OSQLParseNodesContainer> OSQLParseNodesGarbageCollector; + typedef comphelper::SingletonRef<OSQLParseNodesContainer> OSQLParseNodesGarbageCollector; //= OSQLParser |