SXMutex.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/synch/SXMutex.cpp#11 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2005-2009 SQLstream, Inc.
00006 // Copyright (C) 2005-2009 LucidEra, Inc.
00007 // Portions Copyright (C) 1999-2009 John V. Sichi
00008 //
00009 // This program is free software; you can redistribute it and/or modify it
00010 // under the terms of the GNU General Public License as published by the Free
00011 // Software Foundation; either version 2 of the License, or (at your option)
00012 // any later version approved by The Eigenbase Project.
00013 //
00014 // This program is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with this program; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 */
00023 
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/synch/SXMutex.h"
00026 
00027 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/synch/SXMutex.cpp#11 $");
00028 
00029 SXMutex::SXMutex()
00030 {
00031     nShared = 0;
00032     nExclusive = 0;
00033     nExclusivePending = 0;
00034     schedulingPolicy = SCHEDULE_DEFAULT;
00035 }
00036 
00037 SXMutex::~SXMutex()
00038 {
00039     assert(!nShared);
00040     assert(!nExclusive);
00041     assert(!nExclusivePending);
00042     assert(exclusiveHolderId.isNull());
00043 }
00044 
00045 void SXMutex::setSchedulingPolicy(SchedulingPolicy schedulingPolicyInit)
00046 {
00047     StrictMutexGuard mutexGuard(mutex);
00048     assert(!nShared && !nExclusive && !nExclusivePending);
00049     schedulingPolicy = schedulingPolicyInit;
00050 }
00051 
00052 bool SXMutex::waitFor(LockMode lockMode,uint iTimeout,TxnId txnId)
00053 {
00054     boost::xtime atv;
00055     if (iTimeout != ETERNITY) {
00056         convertTimeout(iTimeout,atv);
00057     }
00058     StrictMutexGuard mutexGuard(mutex);
00059     LockHolderId acquirerId(txnId);
00060     bool bExclusive = (lockMode == LOCKMODE_X || lockMode == LOCKMODE_X_NOWAIT);
00061     bool bExclusivePending = (lockMode == LOCKMODE_X)
00062         && (schedulingPolicy == SCHEDULE_FAVOR_EXCLUSIVE);
00063     if (bExclusivePending) {
00064         ++nExclusivePending;
00065     }
00066     for (;;) {
00067         if (exclusiveHolderId == acquirerId) {
00068             break;
00069         }
00070         if (bExclusive) {
00071             if (!nExclusive && !nShared) {
00072                 break;
00073             }
00074         } else {
00075             if (!nExclusive && !nExclusivePending) {
00076                 break;
00077             }
00078         }
00079         if (lockMode >= LOCKMODE_S_NOWAIT) {
00080             // NOTE:  for LOCKMODE_X_NOWAIT, don't need to decrement
00081             // nExclusivePending since we didn't bother incrementing it
00082             return false;
00083         }
00084         if (iTimeout == ETERNITY) {
00085             condition.wait(mutexGuard);
00086         } else {
00087             if (!condition.timed_wait(mutexGuard,atv)) {
00088                 if (bExclusivePending) {
00089                     assert(nExclusivePending > 0);
00090                     --nExclusivePending;
00091                 }
00092                 return false;
00093             }
00094         }
00095     }
00096     if (bExclusive) {
00097         ++nExclusive;
00098         exclusiveHolderId = acquirerId;
00099         if (bExclusivePending) {
00100             assert(nExclusivePending > 0);
00101             --nExclusivePending;
00102         }
00103     } else {
00104         ++nShared;
00105     }
00106     return true;
00107 }
00108 
00109 void SXMutex::release(LockMode lockMode,TxnId txnId)
00110 {
00111     StrictMutexGuard mutexGuard(mutex);
00112     if (lockMode == LOCKMODE_X) {
00113         assert(nExclusive);
00114         LockHolderId releaserId(txnId);
00115         assert(exclusiveHolderId == releaserId);
00116         --nExclusive;
00117         if (!nExclusive) {
00118             exclusiveHolderId.setNull();
00119             condition.notify_all();
00120         }
00121     } else {
00122         assert(lockMode == LOCKMODE_S);
00123         assert(nShared);
00124         // NOTE:  we can't assert(exclusiveHolderId.isNull()) here,
00125         // because a txn may take both a shared lock and an exclusive
00126         // lock simultaneously.
00127         --nShared;
00128         if (!nShared) {
00129             condition.notify_all();
00130         }
00131     }
00132 }
00133 
00134 bool SXMutex::isLocked(LockMode lockMode) const
00135 {
00136     if (lockMode == LOCKMODE_X) {
00137         return nExclusive ? true : false;
00138     } else {
00139         assert(lockMode == LOCKMODE_S);
00140         return nShared ? true : false;
00141     }
00142 }
00143 
00144 bool SXMutex::tryUpgrade(TxnId txnId)
00145 {
00146     StrictMutexGuard mutexGuard(mutex);
00147     assert(nShared);
00148     assert(!nExclusive);
00149     assert(exclusiveHolderId.isNull());
00150     if (nShared > 1) {
00151         return false;
00152     }
00153     // otherwise assume caller holds the unique shared lock, and ignore
00154     // nExclusivePending
00155     nShared = 0;
00156     nExclusive = 1;
00157     LockHolderId holderId(txnId);
00158     exclusiveHolderId = holderId;
00159     return true;
00160 }
00161 
00162 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/synch/SXMutex.cpp#11 $");
00163 
00164 // End SXMutex.cpp

Generated on Mon Jun 22 04:00:20 2009 for Fennel by  doxygen 1.5.1