From 83fffbbd5eda463c4e344016bfec74fa5b2020c2 Mon Sep 17 00:00:00 2001 From: Noel Grandin Date: Wed, 15 Feb 2023 11:15:00 +0200 Subject: 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 --- include/comphelper/singletonref.hxx | 161 +++++++++++++++++++++++++++++++++ include/connectivity/DriversConfig.hxx | 4 +- include/connectivity/sqlparse.hxx | 4 +- 3 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 include/comphelper/singletonref.hxx (limited to 'include') 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 +#include +#include +#include + +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. + +
    +
  • a) The singleton class can provide a special init() + method, which must be called as first after creation.
  • +
  • b) The singleton class can call a special impl_init() + method implicit for every called interface method.
  • +
+ + 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 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 SingletonClass* SingletonRef::m_pInstance = nullptr; + +template sal_Int32 SingletonRef::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 #include -#include +#include #include #include @@ -56,7 +56,7 @@ namespace connectivity class OOO_DLLPUBLIC_DBTOOLS DriversConfig { - typedef salhelper::SingletonRef OSharedConfigNode; + typedef comphelper::SingletonRef 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 #include #include -#include +#include #include @@ -94,7 +94,7 @@ namespace connectivity void clearAndDelete(); }; - typedef salhelper::SingletonRef OSQLParseNodesGarbageCollector; + typedef comphelper::SingletonRef OSQLParseNodesGarbageCollector; //= OSQLParser -- cgit