From 3d435cc9688b36ef887d9210bb0dd2f0eaab7750 Mon Sep 17 00:00:00 2001
From: Avi Kivity <avi.kivity@gmail.com>
Date: Wed, 2 Jan 2013 20:42:10 +0200
Subject: [PATCH] mutex: add with_lock() function

This function allows executing a block of code under a lock, with a guarantee
that any exit from the block will release the lock.

Examples:

    with_lock(my_mutex, [&] { a += b; });

    return with_lock(my_spinlock, [&] {
        return my_list.size();
    });
---
 libc/fd.cc | 21 +++++++++++----------
 mutex.hh   |  9 +++++++++
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/libc/fd.cc b/libc/fd.cc
index 75c19c73b..6b3741ada 100644
--- a/libc/fd.cc
+++ b/libc/fd.cc
@@ -40,14 +40,15 @@ int open(const char* fname, int mode, ...)
     }
     auto desc = std::shared_ptr<file_desc>(
                     new file_desc(f, mode & O_RDONLY, mode & O_WRONLY));
-    std::lock_guard<mutex> guard(file_table_mutex);
-    auto p = std::find(file_table.begin(), file_table.end(),
-                       std::shared_ptr<file_desc>());
-    if (p == file_table.end()) {
-        file_table.push_back(desc);
-        p = file_table.end() - 1;
-    } else {
-        *p = desc;
-    }
-    return p - file_table.begin();
+    return with_lock(file_table_mutex, [&] {
+        auto p = std::find(file_table.begin(), file_table.end(),
+                           std::shared_ptr<file_desc>());
+        if (p == file_table.end()) {
+            file_table.push_back(desc);
+            p = file_table.end() - 1;
+        } else {
+            *p = desc;
+        }
+        return p - file_table.begin();
+    });
 }
diff --git a/mutex.hh b/mutex.hh
index f28027602..4b3a1ab9d 100644
--- a/mutex.hh
+++ b/mutex.hh
@@ -1,6 +1,8 @@
 #ifndef MUTEX_HH
 #define MUTEX_HH
 
+#include <mutex>
+
 class mutex {
 public:
     void lock();
@@ -8,4 +10,11 @@ public:
     void unlock();
 };
 
+template <class Lock, class Func>
+auto with_lock(Lock& lock, Func func) -> decltype(func())
+{
+    std::lock_guard<Lock> guard(lock);
+    return func();
+}
+
 #endif
-- 
GitLab