CPP: Add suport for thread-safety on Linux and Mac in non-Boost base/.

This is needed for Chrome on Android which is the only Chrome port that
requires thread-safety.

R=lararennie@google.com

Review URL: https://codereview.appspot.com/10244046

git-svn-id: http://libphonenumber.googlecode.com/svn/trunk/cpp/src/phonenumbers@583 ee073f10-1060-11df-b6a4-87a95322a99c
diff --git a/base/memory/singleton.h b/base/memory/singleton.h
index 38b4bfc..5fd3e4c 100644
--- a/base/memory/singleton.h
+++ b/base/memory/singleton.h
@@ -14,8 +14,8 @@
 
 // Author: Philippe Liard
 
-#ifndef I18N_PHONENUMBERS_BASE_SINGLETON_H_
-#define I18N_PHONENUMBERS_BASE_SINGLETON_H_
+#ifndef I18N_PHONENUMBERS_BASE_MEMORY_SINGLETON_H_
+#define I18N_PHONENUMBERS_BASE_MEMORY_SINGLETON_H_
 
 #if defined(I18N_PHONENUMBERS_USE_BOOST)
 
@@ -48,16 +48,22 @@
 template <class T> boost::scoped_ptr<T> Singleton<T>::instance;
 template <class T> boost::once_flag Singleton<T>::flag = BOOST_ONCE_INIT;
 
+}  // namespace phonenumbers
+}  // namespace i18n
+
 #else  // !I18N_PHONENUMBERS_USE_BOOST
 
 #include "phonenumbers/base/logging.h"
 #include "phonenumbers/base/thread_checker.h"
 
+#if !defined(__linux__) && !defined(__APPLE__)
+
 namespace i18n {
 namespace phonenumbers {
 
 // Note that this implementation is not thread-safe. For a thread-safe
-// implementation, please compile with -DI18N_PHONENUMBERS_USE_BOOST.
+// implementation on non-POSIX platforms, please compile with
+// -DI18N_PHONENUMBERS_USE_BOOST.
 template <class T>
 class Singleton {
  public:
@@ -78,9 +84,12 @@
   const ThreadChecker thread_checker_;
 };
 
-#endif  // !I18N_PHONENUMBERS_USE_BOOST
-
 }  // namespace phonenumbers
 }  // namespace i18n
 
-#endif // I18N_PHONENUMBERS_BASE_SINGLETON_H_
+#else
+#include "phonenumbers/base/memory/singleton_posix.h"
+#endif  // !defined(__linux__) && !defined(__APPLE__)
+
+#endif  // !I18N_PHONENUMBERS_USE_BOOST
+#endif  // I18N_PHONENUMBERS_BASE_MEMORY_SINGLETON_H_
diff --git a/base/memory/singleton_posix.h b/base/memory/singleton_posix.h
new file mode 100644
index 0000000..52cd04d
--- /dev/null
+++ b/base/memory/singleton_posix.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2013 The Libphonenumber Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef I18N_PHONENUMBERS_BASE_MEMORY_SINGLETON_POSIX_H_
+#define I18N_PHONENUMBERS_BASE_MEMORY_SINGLETON_POSIX_H_
+
+#include <pthread.h>
+
+#include "phonenumbers/base/logging.h"
+
+namespace i18n {
+namespace phonenumbers {
+
+template <class T>
+class Singleton {
+ public:
+  virtual ~Singleton() {}
+
+  static T* GetInstance() {
+    const int ret = pthread_once(&once_control_, &Init);
+    (void) ret;
+    DCHECK_EQ(0, ret);
+    return instance_;
+  }
+
+ private:
+  static void Init() {
+    instance_ = new T();
+  }
+
+  static T* instance_;  // Leaky singleton.
+  static pthread_once_t once_control_;
+};
+
+template <class T> T* Singleton<T>::instance_;
+template <class T> pthread_once_t Singleton<T>::once_control_ =
+    PTHREAD_ONCE_INIT;
+
+}  // namespace phonenumbers
+}  // namespace i18n
+
+#endif  // I18N_PHONENUMBERS_BASE_MEMORY_SINGLETON_POSIX_H_
diff --git a/base/synchronization/lock.h b/base/synchronization/lock.h
index 7ef136c..63eab24 100644
--- a/base/synchronization/lock.h
+++ b/base/synchronization/lock.h
@@ -34,11 +34,14 @@
 #include "phonenumbers/base/logging.h"
 #include "phonenumbers/base/thread_checker.h"
 
+// Dummy lock implementation on non-POSIX platforms. If you are running on a
+// different platform and care about thread-safety, please compile with
+// -DI18N_PHONENUMBERS_USE_BOOST.
+#if !defined(__linux__) && !defined(__APPLE__)
+
 namespace i18n {
 namespace phonenumbers {
 
-// Dummy lock implementation. If you care about thread-safety, please compile
-// with -DI18N_PHONENUMBERS_USE_BOOST.
 class Lock {
  public:
   Lock() : thread_checker_() {}
@@ -47,18 +50,36 @@
     DCHECK(thread_checker_.CalledOnValidThread());
   }
 
-  // No need for Release() since Acquire() is a no-op and Release() is not used
-  // in the codebase.
+  void Release() const {
+    DCHECK(thread_checker_.CalledOnValidThread());
+  }
 
  private:
   const ThreadChecker thread_checker_;
 };
 
+}  // namespace phonenumbers
+}  // namespace i18n
+
+#else
+#include "phonenumbers/base/synchronization/lock_posix.h"
+#endif
+
+namespace i18n {
+namespace phonenumbers {
+
 class AutoLock {
  public:
-  AutoLock(Lock& lock) {
-    lock.Acquire();
+  AutoLock(Lock& lock) : lock_(lock) {
+    lock_.Acquire();
   }
+
+  ~AutoLock() {
+    lock_.Release();
+  }
+
+ private:
+  Lock& lock_;
 };
 
 }  // namespace phonenumbers
diff --git a/base/synchronization/lock_posix.h b/base/synchronization/lock_posix.h
new file mode 100644
index 0000000..8ef1a95
--- /dev/null
+++ b/base/synchronization/lock_posix.h
@@ -0,0 +1,63 @@
+// Copyright (C) 2013 The Libphonenumber Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Author: Philippe Liard
+
+#ifndef I18N_PHONENUMBERS_BASE_SYNCHRONIZATION_LOCK_POSIX_H_
+#define I18N_PHONENUMBERS_BASE_SYNCHRONIZATION_LOCK_POSIX_H_
+
+#include <pthread.h>
+
+#include "phonenumbers/base/basictypes.h"
+#include "phonenumbers/base/logging.h"
+
+namespace i18n {
+namespace phonenumbers {
+
+class Lock {
+ public:
+  Lock() {
+    const int ret = pthread_mutex_init(&mutex_, NULL);
+    (void) ret;
+    DCHECK_EQ(0, ret);
+  }
+
+  ~Lock() {
+    const int ret = pthread_mutex_destroy(&mutex_);
+    (void) ret;
+    DCHECK_EQ(0, ret);
+  }
+
+  void Acquire() const {
+    int ret = pthread_mutex_lock(&mutex_);
+    (void) ret;
+    DCHECK_EQ(0, ret);
+  }
+
+  void Release() const {
+    int ret = pthread_mutex_unlock(&mutex_);
+    (void) ret;
+    DCHECK_EQ(0, ret);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Lock);
+
+  mutable pthread_mutex_t mutex_;
+};
+
+}  // namespace phonenumbers
+}  // namespace i18n
+
+#endif  // I18N_PHONENUMBERS_BASE_SYNCHRONIZATION_LOCK_POSIX_H_
diff --git a/base/thread_checker.h b/base/thread_checker.h
index bac8048..b7a3523 100644
--- a/base/thread_checker.h
+++ b/base/thread_checker.h
@@ -22,7 +22,8 @@
 // Note that I18N_PHONENUMBERS_NO_THREAD_SAFETY must be defined only to let the
 // user of the library know that it can't be used in a thread-safe manner when
 // it is not depending on Boost.
-#if !defined(I18N_PHONENUMBERS_NO_THREAD_SAFETY)
+#if !defined(__linux__) && !defined(__APPLE__) && \
+    !defined(I18N_PHONENUMBERS_NO_THREAD_SAFETY)
 #error Building without Boost, please provide \
        -DI18N_PHONENUMBERS_NO_THREAD_SAFETY
 #endif