📄 mutex.c
字号:
//// class mutex//// Mutes is a semaphore, that can be used by two threads to mutually// exclude the other. To ensure uniqe access to memory.#include "thread.h"#include "mutex.h"#include "exception.h"#include "thread_lists.h"#include "wait_queue.h"#include "shared.h"#include <cerrno>#define MUTEX_MAGIC_NO 0x212612namespace cpp_threads { std::string Mutex::_project = ""; Mutex::Mutex(attributes::scope scope_p) { init( scope_p ); } Mutex::Mutex() { Pthread *p = Pthread::self(); scope_t scope = attributes::process_private_e; Pthread::debug("Mutex::Mutex()"); if( p && p->inherit() ) scope = p->scope(); init( scope ); } Mutex::~Mutex() { Pthread::debug("Mutex::~Mutex"); if ( _m ) { _m->m_spinlock.acquire(); delete _waiting; if ( _scope == attributes::process_private_e ) delete _m; else SharedMemory::share.deAlloc( _m ); _m = 0; } } void Mutex::init(attributes::scope scope_p) { _id = -1; if ( scope_p == attributes::process_private_e ) { _m = new storage; _m->m_magic = 0; } else { _id = SharedMemory::share.createProj( _project ); _m = (storage*)SharedMemory::share.alloc( sizeof(storage),_id ); if( _m != (storage *)-1 ) exception::fatal( ENOMEM ); } if ( _m->m_magic != MUTEX_MAGIC_NO ) { _m->m_kind = fast_e; _m->m_count = 0; _m->m_owner = -1; _m->m_magic = MUTEX_MAGIC_NO; } _waiting = new WaitQueue( _id ); _scope = scope_p; } attributes::scope Mutex::scope() { return _scope; } int Mutex::isLocked() { bool rv; _m->m_spinlock.acquire(); rv = (_m->m_count != 0); _m->m_spinlock.release(); return rv; } void Mutex::release() { _m->m_owner = 0; _m->m_count = 0; _m->m_exclusive = false; } int Mutex::acquire(bool xlsive_p) { // The owner, is the one holding the exclusive lock. _m->m_exclusive = xlsive_p; _m->m_owner = getpid(); _m->m_count++; return 0; } // // kind // // set the mutex kind. int Mutex::kind(mutex_kind kind_p) { if (kind_p != Mutex::recursive_e && kind_p != Mutex::fast_e) return EINVAL; _m->m_kind = kind_p; return 0; } // // kind // // get the mutex kind. int Mutex::kind() { return _m->m_kind; } // // trylock // // try and lock the mutex. // // return // EBUSY - the mutex is locked by another. // EINVAL - the mutex is of an unknown kind. // 0 - successful. int Mutex::tryLock(bool xlsive_p) { int rval = EBUSY; bool read_lock; _m->m_spinlock.acquire(); read_lock = !(xlsive_p || _m->m_exclusive); switch(_m->m_kind) { case Mutex::fast_e: if ( _m->m_count == 0 || read_lock ) rval = acquire(xlsive_p); break; case Mutex::recursive_e: if ( _m->m_count == 0 || _m->m_owner == getpid() || read_lock ) rval = acquire(xlsive_p); break; case Mutex::errorcheck_e: if ( _m->m_count == 0 || read_lock ) rval = acquire(xlsive_p); else if ( _m->m_owner == getpid() ) rval = EDEADLK; break; default: rval = EINVAL; break; } _m->m_spinlock.release(); return rval; } // // lock // // Try and lock the mutex. If unsuccessful, suspend the calling // process, until the mutex is available. int Mutex::lock(bool xlsive_p, int pri_p) { int rval = EBUSY; while(rval == EBUSY) { if ((rval = tryLock(xlsive_p)) == EBUSY) _waiting->suspendMe(pri_p); } return rval; } // // unlock // // unlock the mutex, and restart any threads, that are waiting // on it. int Mutex::unLock() { bool read_lock; int rval = 0; _m->m_spinlock.acquire(); read_lock = !_m->m_exclusive; switch(_m->m_kind) { case Mutex::fast_e: if ( read_lock || _m->m_owner == getpid() ) release(); else rval = EBUSY; break; case Mutex::recursive_e: if ( (read_lock || _m->m_owner == getpid()) && _m->m_count > 0 ) { if (--_m->m_count == 0) release(); } else rval = EBUSY; break; case Mutex::errorcheck_e: if ( _m->m_count == 0 || (_m->m_owner != getpid() && !read_lock) ) rval = EPERM; else release(); break; default: rval = EINVAL; } _m->m_spinlock.release(); if ( rval == 0 ) _waiting->wakeUp(); return rval; } // // project_part // // change the project part void Mutex::projectPart(const std::string& part_p) { _project = part_p; } Mutex::operator bool() { return isLocked(); }}; // Namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -