Revert "Remove lambda expression to support older compilers"

This reverts commit 5d5b1d8c8ec4c578f72a12f5b81f705764cdf804.
diff --git a/src/cpp/server/thread_pool.cc b/src/cpp/server/thread_pool.cc
index 10dceec..d3013b8 100644
--- a/src/cpp/server/thread_pool.cc
+++ b/src/cpp/server/thread_pool.cc
@@ -35,29 +35,28 @@
 
 namespace grpc {
 
-#ifdef __GNUC__
-#if (__GNUC__ * 100 + __GNUC_MINOR__ < 406)
-#define GRPC_NO_NULLPTR
-#endif
-#endif
-
-#ifdef GRPC_NO_NULLPTR
-#include <memory>
-const class {
-public:
-  template <class T> operator T*() const {return static_cast<T *>(0);}
-  template <class T> operator std::unique_ptr<T>() const {
-    return std::unique_ptr<T>(static_cast<T *>(0));
-  }
-  operator bool() const {return false;}
-private:
-  void operator&() const = delete;
-} nullptr = {};
-#endif
-
 ThreadPool::ThreadPool(int num_threads) : shutdown_(false) {
   for (int i = 0; i < num_threads; i++) {
-    threads_.push_back(std::thread(&ThreadPool::ThreadFunc, this));
+    threads_.push_back(std::thread([this]() {
+      for (;;) {
+        // Wait until work is available or we are shutting down.
+        auto have_work = [this]() { return shutdown_ || !callbacks_.empty(); };
+        std::unique_lock<std::mutex> lock(mu_);
+        if (!have_work()) {
+          cv_.wait(lock, have_work);
+        }
+        // Drain callbacks before considering shutdown to ensure all work
+        // gets completed.
+        if (!callbacks_.empty()) {
+          auto cb = callbacks_.front();
+          callbacks_.pop();
+          lock.unlock();
+          cb();
+        } else if (shutdown_) {
+          return;
+        }
+      }
+    }));
   }
 }
 
diff --git a/src/cpp/server/thread_pool.h b/src/cpp/server/thread_pool.h
index 41e2009..6225d82 100644
--- a/src/cpp/server/thread_pool.h
+++ b/src/cpp/server/thread_pool.h
@@ -58,8 +58,6 @@
   bool shutdown_;
   std::queue<std::function<void()>> callbacks_;
   std::vector<std::thread> threads_;
-
-  void ThreadFunc();
 };
 
 }  // namespace grpc