summaryrefslogtreecommitdiff
path: root/src/mongo/db/lockstate.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/lockstate.h')
-rw-r--r--src/mongo/db/lockstate.h147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/mongo/db/lockstate.h b/src/mongo/db/lockstate.h
new file mode 100644
index 00000000000..526e810eadd
--- /dev/null
+++ b/src/mongo/db/lockstate.h
@@ -0,0 +1,147 @@
+// lockstate.h
+
+/**
+* Copyright (C) 2008 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* 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 Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#pragma once
+
+#include "mongo/db/d_concurrency.h"
+
+namespace mongo {
+
+ class Acquiring;
+
+ // per thread
+ class LockState {
+ public:
+ LockState();
+
+ void dump();
+ static void Dump();
+ BSONObj reportState();
+ void reportState(BSONObjBuilder& b);
+
+ unsigned recursiveCount() const { return _recursive; }
+
+ /**
+ * @return 0 rwRW
+ */
+ char threadState() const { return _threadState; }
+
+ bool isRW() const; // RW
+ bool isW() const; // W
+ bool hasAnyReadLock() const; // explicitly rR
+ bool hasAnyWriteLock() const; // wWX
+
+ bool isLocked( const StringData& ns ); // rwRW
+
+ /** pending means we are currently trying to get a lock */
+ bool hasLockPending() const { return _lockPending || _lockPendingParallelWriter; }
+
+ // ----
+
+
+ void lockedStart( char newState ); // RWrw
+ void unlocked(); // _threadState = 0
+
+ /**
+ * you have to be locked already to call this
+ * this is mostly for W_to_R or R_to_W
+ */
+ void changeLockState( char newstate );
+
+ Lock::Nestable whichNestable() const { return _whichNestable; }
+ int nestableCount() const { return _nestableCount; }
+
+ int otherCount() const { return _otherCount; }
+ string otherName() const { return _otherName; }
+ WrapperForRWLock* otherLock() const { return _otherLock; }
+
+ void enterScopedLock( Lock::ScopedLock* lock );
+ Lock::ScopedLock* leaveScopedLock();
+
+ void lockedNestable( Lock::Nestable what , int type );
+ void unlockedNestable();
+ void lockedOther( const string& db , int type , WrapperForRWLock* lock );
+ void lockedOther( int type ); // "same lock as last time" case
+ void unlockedOther();
+ bool _batchWriter;
+
+ LockStat* getRelevantLockStat();
+ void recordLockTime() { _scopedLk->recordTime(); }
+ void resetLockTime() { _scopedLk->resetTime(); }
+
+ private:
+ unsigned _recursive; // we allow recursively asking for a lock; we track that here
+
+ // global lock related
+ char _threadState; // 0, 'r', 'w', 'R', 'W'
+
+ // db level locking related
+ Lock::Nestable _whichNestable;
+ int _nestableCount; // recursive lock count on local or admin db XXX - change name
+
+ int _otherCount; // >0 means write lock, <0 read lock - XXX change name
+ string _otherName; // which database are we locking and working with (besides local/admin)
+ WrapperForRWLock* _otherLock; // so we don't have to check the map too often (the map has a mutex)
+
+ // for temprelease
+ // for the nonrecursive case. otherwise there would be many
+ // the first lock goes here, which is ok since we can't yield recursive locks
+ Lock::ScopedLock* _scopedLk;
+
+ bool _lockPending;
+ bool _lockPendingParallelWriter;
+
+ friend class Acquiring;
+ friend class AcquiringParallelWriter;
+ };
+
+ class WrapperForRWLock : boost::noncopyable {
+ SimpleRWLock r;
+ public:
+ string name() const { return r.name; }
+ LockStat stats;
+ WrapperForRWLock(const char *name) : r(name) { }
+ void lock() { r.lock(); }
+ void lock_shared() { r.lock_shared(); }
+ void unlock() { r.unlock(); }
+ void unlock_shared() { r.unlock_shared(); }
+ };
+
+ class ScopedLock;
+
+ class Acquiring {
+ public:
+ Acquiring( Lock::ScopedLock* lock, LockState& ls );
+ ~Acquiring();
+ private:
+ Lock::ScopedLock* _lock;
+ LockState& _ls;
+ };
+
+ class AcquiringParallelWriter {
+ public:
+ AcquiringParallelWriter( LockState& ls );
+ ~AcquiringParallelWriter();
+
+ private:
+ LockState& _ls;
+ };
+
+
+}