diff options
Diffstat (limited to 'storage/ndb/src/kernel/vm/Mutex.hpp')
-rw-r--r-- | storage/ndb/src/kernel/vm/Mutex.hpp | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/storage/ndb/src/kernel/vm/Mutex.hpp b/storage/ndb/src/kernel/vm/Mutex.hpp new file mode 100644 index 00000000000..7a16046188c --- /dev/null +++ b/storage/ndb/src/kernel/vm/Mutex.hpp @@ -0,0 +1,267 @@ +/* Copyright (C) 2003 MySQL AB + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef BLOCK_MUTEX_HPP +#define BLOCK_MUTEX_HPP + +#include "Callback.hpp" +#include "SimulatedBlock.hpp" + +class Mutex; + +/** + * MutexHandle - A "reference" to a mutex + * - Should be used together with Mutex + */ +class MutexHandle { + friend class Mutex; +public: + MutexHandle(Uint32 id); + + bool isNull() const; + void release(SimulatedBlock::MutexManager & mgr); + +private: + const Uint32 m_mutexId; + Uint32 m_activeMutexPtrI; +}; + +/** + * MutexHandle2 - A template-based "reference" to a mutex + */ +template<Uint32 MutexId> +class MutexHandle2 { + friend class Mutex; +public: + MutexHandle2(); + + bool isNull() const; + void release(SimulatedBlock::MutexManager & mgr); + +private: + Uint32 m_activeMutexPtrI; +}; + +/** + * A mutex - Used together with a MutexHandle to be put on the stack + */ +class Mutex { +public: + Mutex(Signal*, SimulatedBlock::MutexManager & mgr, MutexHandle &); + + template<Uint32 MutexId> + Mutex(Signal*, SimulatedBlock::MutexManager & mgr, MutexHandle2<MutexId> &); + + ~Mutex(); + + void release(); + bool isNull() const ; + + bool lock(SimulatedBlock::Callback & callback); + bool trylock(SimulatedBlock::Callback & callback); + void unlock(SimulatedBlock::Callback & callback); + void unlock(); // Ignore callback + + bool create(SimulatedBlock::Callback & callback); + bool destroy(SimulatedBlock::Callback & callback); + +private: + Signal* m_signal; + SimulatedBlock::MutexManager & m_mgr; + const Uint32 m_mutexId; + Uint32 & m_srcPtrI; + SimulatedBlock::MutexManager::ActiveMutexPtr m_ptr; + +public: + static void release(SimulatedBlock::MutexManager&, + Uint32 activePtrI, Uint32 mutexId); +}; + +inline +MutexHandle::MutexHandle(Uint32 id) : m_mutexId(id) { + m_activeMutexPtrI = RNIL; +} + +inline +bool +MutexHandle::isNull() const { + return m_activeMutexPtrI == RNIL; +} + +inline +void +MutexHandle::release(SimulatedBlock::MutexManager & mgr){ + if(!isNull()){ + Mutex::release(mgr, m_activeMutexPtrI, m_mutexId); + m_activeMutexPtrI = RNIL; + } +} + +template<Uint32 MutexId> +inline +MutexHandle2<MutexId>::MutexHandle2() { + m_activeMutexPtrI = RNIL; +} + +template<Uint32 MutexId> +inline +bool +MutexHandle2<MutexId>::isNull() const { + return m_activeMutexPtrI == RNIL; +} + + +template<Uint32 MutexId> +inline +void +MutexHandle2<MutexId>::release(SimulatedBlock::MutexManager & mgr){ + if(!isNull()){ + Mutex::release(mgr, m_activeMutexPtrI, MutexId); + m_activeMutexPtrI = RNIL; + } +} + + +inline +Mutex::Mutex(Signal* signal, SimulatedBlock::MutexManager & mgr, + MutexHandle & mh) + : m_signal(signal), + m_mgr(mgr), + m_mutexId(mh.m_mutexId), + m_srcPtrI(mh.m_activeMutexPtrI){ + + m_ptr.i = m_srcPtrI; + +} + +template<Uint32 MutexId> +inline +Mutex::Mutex(Signal* signal, SimulatedBlock::MutexManager & mgr, + MutexHandle2<MutexId> & mh) + : m_signal(signal), + m_mgr(mgr), + m_mutexId(MutexId), + m_srcPtrI(mh.m_activeMutexPtrI){ + + m_ptr.i = m_srcPtrI; + +} + +inline +Mutex::~Mutex(){ + m_srcPtrI = m_ptr.i; +} + +inline +void +Mutex::release(){ + if(!m_ptr.isNull()){ + Mutex::release(m_mgr, m_ptr.i, m_mutexId); + m_ptr.setNull(); + } +} + +inline +bool +Mutex::isNull() const { + return m_ptr.isNull(); +} + +inline +bool +Mutex::lock(SimulatedBlock::Callback & callback){ + if(m_ptr.isNull()){ + if(m_mgr.seize(m_ptr)){ + m_ptr.p->m_mutexId = m_mutexId; + m_ptr.p->m_callback = callback; + m_mgr.lock(m_signal, m_ptr); + return true; + } + return false; + } + ErrorReporter::handleAssert("Mutex::lock mutex alreay inuse", + __FILE__, __LINE__); + return false; +} + +inline +bool +Mutex::trylock(SimulatedBlock::Callback & callback){ + if(m_ptr.isNull()){ + if(m_mgr.seize(m_ptr)){ + m_ptr.p->m_mutexId = m_mutexId; + m_ptr.p->m_callback = callback; + m_mgr.lock(m_signal, m_ptr); + return true; + } + return false; + } + ErrorReporter::handleAssert("Mutex::trylock mutex alreay inuse", + __FILE__, __LINE__); + return false; +} + +inline +void +Mutex::unlock(SimulatedBlock::Callback & callback){ + if(!m_ptr.isNull()){ + m_mgr.getPtr(m_ptr); + if(m_ptr.p->m_mutexId == m_mutexId){ + m_ptr.p->m_callback = callback; + m_mgr.unlock(m_signal, m_ptr); + return; + } + } + ErrorReporter::handleAssert("Mutex::unlock invalid mutex", + __FILE__, __LINE__); +} + +inline +bool +Mutex::create(SimulatedBlock::Callback & callback){ + if(m_ptr.isNull()){ + if(m_mgr.seize(m_ptr)){ + m_ptr.p->m_mutexId = m_mutexId; + m_ptr.p->m_callback = callback; + m_mgr.create(m_signal, m_ptr); + return true; + } + return false; + } + ErrorReporter::handleAssert("Mutex::create mutex alreay inuse", + __FILE__, __LINE__); + return false; +} + +inline +bool +Mutex::destroy(SimulatedBlock::Callback & callback){ + if(m_ptr.isNull()){ + if(m_mgr.seize(m_ptr)){ + m_ptr.p->m_mutexId = m_mutexId; + m_ptr.p->m_callback = callback; + m_mgr.destroy(m_signal, m_ptr); + return true; + } + return false; + } + ErrorReporter::handleAssert("Mutex::destroy mutex alreay inuse", + __FILE__, __LINE__); + return false; +} + + +#endif |