Browse Source

[1704] Use the is_locked_ flag to call unlock() just once

Mukund Sivaraman 13 years ago
parent
commit
7987b09972

+ 0 - 1
src/lib/log/tests/logger_lock_test.sh.in

@@ -34,7 +34,6 @@ cat > $tempfile << .
 LOGGER_LOCK_TEST: LOCK
 INFO  [bind10.log] LOG_LOCK_TEST_MESSAGE this is a test message.
 LOGGER_LOCK_TEST: UNLOCK
-LOGGER_LOCK_TEST: UNLOCK
 .
 rm -f $destfile
 B10_LOGGER_SEVERITY=INFO B10_LOGGER_DESTINATION=stdout ./logger_lock_test > $destfile

+ 16 - 2
src/lib/util/interprocess_sync.h

@@ -38,6 +38,10 @@ class InterprocessSyncLocker; // forward declaration
 /// 4. Client performs task that needs mutual exclusion.
 /// 5. Client frees lock with unlock(), or simply returns from the basic
 /// block which forms the scope for the InterprocessSyncLocker.
+///
+/// NOTE: All implementations of InterprocessSync should keep the
+/// is_locked_ member variable updated whenever their
+/// lock()/tryLock()/unlock() implementations are called.
 class InterprocessSync {
   // InterprocessSyncLocker is the only code outside this class that
   // should be allowed to call the lock(), tryLock() and unlock()
@@ -100,7 +104,8 @@ public:
 
     /// \brief Destructor
     ~InterprocessSyncLocker() {
-        unlock();
+        if (isLocked())
+            unlock();
     }
 
     /// \brief Acquire the lock (blocks if something else has acquired a
@@ -113,11 +118,20 @@ public:
 
     /// \brief Try to acquire a lock (doesn't block)
     ///
-    /// \return Returns true if the lock was acquired, false otherwise.
+    /// \return Returns true if a new lock could be acquired, false
+    ///         otherwise.
     bool tryLock() {
         return (sync_.tryLock());
     }
 
+    /// \brief Check if the lock is taken
+    ///
+    /// \return Returns true if a lock is currently acquired, false
+    ///         otherwise.
+    bool isLocked() {
+        return (sync_.is_locked_);
+    }
+
     /// \brief Release the lock
     ///
     /// \return Returns true if the lock was released, false otherwise.

+ 3 - 0
src/lib/util/interprocess_sync_null.cc

@@ -22,16 +22,19 @@ InterprocessSyncNull::~InterprocessSyncNull() {
 
 bool
 InterprocessSyncNull::lock() {
+    is_locked_ = true;
     return (true);
 }
 
 bool
 InterprocessSyncNull::tryLock() {
+    is_locked_ = true;
     return (true);
 }
 
 bool
 InterprocessSyncNull::unlock() {
+    is_locked_ = false;
     return (true);
 }
 

+ 6 - 0
src/lib/util/tests/interprocess_sync_file_unittest.cc

@@ -55,7 +55,9 @@ TEST(InterprocessSyncFileTest, TestLock) {
   InterprocessSyncFile sync("test");
   InterprocessSyncLocker locker(sync);
 
+  EXPECT_FALSE(locker.isLocked());
   EXPECT_TRUE(locker.lock());
+  EXPECT_TRUE(locker.isLocked());
 
   int fds[2];
 
@@ -77,7 +79,10 @@ TEST(InterprocessSyncFileTest, TestLock) {
       InterprocessSyncLocker locker2(sync2);
 
       if (!locker2.tryLock()) {
+          EXPECT_FALSE(locker2.isLocked());
           locked = 1;
+      } else {
+          EXPECT_TRUE(locker2.isLocked());
       }
 
       write(fds[1], &locked, sizeof(locked));
@@ -95,6 +100,7 @@ TEST(InterprocessSyncFileTest, TestLock) {
   }
 
   EXPECT_TRUE(locker.unlock());
+  EXPECT_FALSE(locker.isLocked());
 
   EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test_lockfile"));
 }

+ 19 - 4
src/lib/util/tests/interprocess_sync_null_unittest.cc

@@ -24,28 +24,43 @@ TEST(InterprocessSyncNullTest, TestNull) {
   InterprocessSyncNull sync("test1");
   InterprocessSyncLocker locker(sync);
 
-  // All of these must always return true
-
+  // Check if the is_locked_ flag is set correctly during lock().
+  EXPECT_FALSE(locker.isLocked());
   EXPECT_TRUE(locker.lock());
+  EXPECT_TRUE(locker.isLocked());
+
+  // lock() must always return true (this is called 4 times, just an
+  // arbitrary number)
   EXPECT_TRUE(locker.lock());
   EXPECT_TRUE(locker.lock());
   EXPECT_TRUE(locker.lock());
   EXPECT_TRUE(locker.lock());
 
+  // Check if the is_locked_ flag is set correctly during unlock().
+  EXPECT_TRUE(locker.isLocked());
   EXPECT_TRUE(locker.unlock());
+  EXPECT_FALSE(locker.isLocked());
+
+  // unlock() must always return true (this is called 4 times, just an
+  // arbitrary number)
   EXPECT_TRUE(locker.unlock());
   EXPECT_TRUE(locker.unlock());
   EXPECT_TRUE(locker.unlock());
   EXPECT_TRUE(locker.unlock());
 
+  // Check if the is_locked_ flag is set correctly during tryLock().
+  EXPECT_FALSE(locker.isLocked());
   EXPECT_TRUE(locker.tryLock());
+  EXPECT_TRUE(locker.isLocked());
+
+  // tryLock() must always return true (this is called 4 times, just an
+  // arbitrary number)
   EXPECT_TRUE(locker.tryLock());
   EXPECT_TRUE(locker.tryLock());
   EXPECT_TRUE(locker.tryLock());
   EXPECT_TRUE(locker.tryLock());
 
-  // Random order
-
+  // Random order (should all return true)
   EXPECT_TRUE(locker.unlock());
   EXPECT_TRUE(locker.lock());
   EXPECT_TRUE(locker.tryLock());