diff options
Diffstat (limited to 'include/framework/gate.hxx')
-rw-r--r-- | include/framework/gate.hxx | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/include/framework/gate.hxx b/include/framework/gate.hxx new file mode 100644 index 000000000..ab9f81c24 --- /dev/null +++ b/include/framework/gate.hxx @@ -0,0 +1,146 @@ +/* -*- 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 <mutex> +#include <osl/conditn.hxx> + +namespace framework{ + +/*-************************************************************************************************************ + @short implement a gate to block multiple threads at the same time or unblock all + @descr A gate can be used as a negative-condition! You can open a "door" - wait() will not block ... + or you can close it - wait() blocks till open() is called again. + Then all currently waiting threads are running immediately - but new ones are blocked! + + @attention To prevent us against wrong using, the default ctor, copy ctor and the =operator are marked private! + + @devstatus ready to use +*//*-*************************************************************************************************************/ +class Gate +{ + + // public methods + + public: + + /*-**************************************************************************************************** + @short ctor + @descr These initialize the object right as an open gate. + *//*-*****************************************************************************************************/ + Gate() + : m_bClosed ( false ) + { + open(); + } + + /*-**************************************************************************************************** + @short dtor + @descr Is user forget it - we open the gate ... + blocked threads can running ... but I don't know + if it's right - we are destroyed yet!? + *//*-*****************************************************************************************************/ + ~Gate() + { + open(); + } + /*-**************************************************************************************************** + @short copy-ctor + @descr Forbid copy construction + *//*-*****************************************************************************************************/ + Gate(const Gate&) = delete; + /*-**************************************************************************************************** + @short copy-assignment + @descr Forbid copy assigning + *//*-*****************************************************************************************************/ + Gate& operator=(const Gate&) = delete; + + /*-**************************************************************************************************** + @short open the gate + @descr A wait() call will not block then. + + @seealso method close() + *//*-*****************************************************************************************************/ + void open() + { + // We must safe access to our internal member! + std::unique_lock aLock( m_aAccessLock ); + // Set condition -> wait don't block any longer -> gate is open + m_aPassage.set(); + // Check if operation was successful! + // Check returns false if condition isn't set => m_bClosed will be true then => we must return false; opening failed + m_bClosed = !m_aPassage.check(); + } + + /*-**************************************************************************************************** + @short close the gate + @descr A wait() call will block then. + + @seealso method open() + *//*-*****************************************************************************************************/ + void close() + { + // We must safe access to our internal member! + std::unique_lock aLock( m_aAccessLock ); + // Reset condition -> wait blocks now -> gate is closed + m_aPassage.reset(); + // Check if operation was successful! + // Check returns false if condition was reset => m_bClosed will be true then => we can return true; closing ok + m_bClosed = !m_aPassage.check(); + } + + /*-**************************************************************************************************** + @short must be called to pass the gate + @descr If gate "open" => wait() will not block. + If gate "closed" => wait() will block till somewhere open it again. + + @seealso method wait() + @seealso method open() + + *//*-*****************************************************************************************************/ + void wait() + { + // We must safe access to our internal member! + std::unique_lock aLock( m_aAccessLock ); + // If gate not closed - caller can pass it. + if( m_bClosed ) + { + // Then we must release used access lock - + // because next call will block... + // and if we hold the access lock nobody else can use this object without a deadlock! + aLock.unlock(); + // Wait for opening gate... + m_aPassage.wait(); + } + } + + // private member + + private: + + std::mutex m_aAccessLock; + ::osl::Condition m_aPassage; + bool m_bClosed; + +}; // class Gate + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |