Adds a modified copy of talk/base to webrtc/base. It is the first step in
migrating talk/base to webrtc/base.

BUG=N/A
R=niklas.enbom@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/17479005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6129 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/base/criticalsection.h b/webrtc/base/criticalsection.h
new file mode 100644
index 0000000..a950a47
--- /dev/null
+++ b/webrtc/base/criticalsection.h
@@ -0,0 +1,179 @@
+/*
+ *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_BASE_CRITICALSECTION_H__
+#define WEBRTC_BASE_CRITICALSECTION_H__
+
+#include "webrtc/base/constructormagic.h"
+
+#if defined(WEBRTC_WIN)
+#include "webrtc/base/win32.h"
+#endif
+
+#if defined(WEBRTC_POSIX)
+#include <pthread.h>
+#endif
+
+#ifdef _DEBUG
+#define CS_TRACK_OWNER 1
+#endif  // _DEBUG
+
+#if CS_TRACK_OWNER
+#define TRACK_OWNER(x) x
+#else  // !CS_TRACK_OWNER
+#define TRACK_OWNER(x)
+#endif  // !CS_TRACK_OWNER
+
+namespace rtc {
+
+#if defined(WEBRTC_WIN)
+class CriticalSection {
+ public:
+  CriticalSection() {
+    InitializeCriticalSection(&crit_);
+    // Windows docs say 0 is not a valid thread id
+    TRACK_OWNER(thread_ = 0);
+  }
+  ~CriticalSection() {
+    DeleteCriticalSection(&crit_);
+  }
+  void Enter() {
+    EnterCriticalSection(&crit_);
+    TRACK_OWNER(thread_ = GetCurrentThreadId());
+  }
+  bool TryEnter() {
+    if (TryEnterCriticalSection(&crit_) != FALSE) {
+      TRACK_OWNER(thread_ = GetCurrentThreadId());
+      return true;
+    }
+    return false;
+  }
+  void Leave() {
+    TRACK_OWNER(thread_ = 0);
+    LeaveCriticalSection(&crit_);
+  }
+
+#if CS_TRACK_OWNER
+  bool CurrentThreadIsOwner() const { return thread_ == GetCurrentThreadId(); }
+#endif  // CS_TRACK_OWNER
+
+ private:
+  CRITICAL_SECTION crit_;
+  TRACK_OWNER(DWORD thread_);  // The section's owning thread id
+};
+#endif // WEBRTC_WIN 
+
+#if defined(WEBRTC_POSIX)
+class CriticalSection {
+ public:
+  CriticalSection() {
+    pthread_mutexattr_t mutex_attribute;
+    pthread_mutexattr_init(&mutex_attribute);
+    pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
+    pthread_mutex_init(&mutex_, &mutex_attribute);
+    pthread_mutexattr_destroy(&mutex_attribute);
+    TRACK_OWNER(thread_ = 0);
+  }
+  ~CriticalSection() {
+    pthread_mutex_destroy(&mutex_);
+  }
+  void Enter() {
+    pthread_mutex_lock(&mutex_);
+    TRACK_OWNER(thread_ = pthread_self());
+  }
+  bool TryEnter() {
+    if (pthread_mutex_trylock(&mutex_) == 0) {
+      TRACK_OWNER(thread_ = pthread_self());
+      return true;
+    }
+    return false;
+  }
+  void Leave() {
+    TRACK_OWNER(thread_ = 0);
+    pthread_mutex_unlock(&mutex_);
+  }
+
+#if CS_TRACK_OWNER
+  bool CurrentThreadIsOwner() const { return pthread_equal(thread_, pthread_self()); }
+#endif  // CS_TRACK_OWNER
+
+ private:
+  pthread_mutex_t mutex_;
+  TRACK_OWNER(pthread_t thread_);
+};
+#endif // WEBRTC_POSIX
+
+// CritScope, for serializing execution through a scope.
+class CritScope {
+ public:
+  explicit CritScope(CriticalSection *pcrit) {
+    pcrit_ = pcrit;
+    pcrit_->Enter();
+  }
+  ~CritScope() {
+    pcrit_->Leave();
+  }
+ private:
+  CriticalSection *pcrit_;
+  DISALLOW_COPY_AND_ASSIGN(CritScope);
+};
+
+// Tries to lock a critical section on construction via
+// CriticalSection::TryEnter, and unlocks on destruction if the
+// lock was taken. Never blocks.
+//
+// IMPORTANT: Unlike CritScope, the lock may not be owned by this thread in
+// subsequent code. Users *must* check locked() to determine if the
+// lock was taken. If you're not calling locked(), you're doing it wrong!
+class TryCritScope {
+ public:
+  explicit TryCritScope(CriticalSection *pcrit) {
+    pcrit_ = pcrit;
+    locked_ = pcrit_->TryEnter();
+  }
+  ~TryCritScope() {
+    if (locked_) {
+      pcrit_->Leave();
+    }
+  }
+  bool locked() const {
+    return locked_;
+  }
+ private:
+  CriticalSection *pcrit_;
+  bool locked_;
+  DISALLOW_COPY_AND_ASSIGN(TryCritScope);
+};
+
+// TODO: Move this to atomicops.h, which can't be done easily because of
+// complex compile rules.
+class AtomicOps {
+ public:
+#if defined(WEBRTC_WIN)
+  // Assumes sizeof(int) == sizeof(LONG), which it is on Win32 and Win64.
+  static int Increment(int* i) {
+    return ::InterlockedIncrement(reinterpret_cast<LONG*>(i));
+  }
+  static int Decrement(int* i) {
+    return ::InterlockedDecrement(reinterpret_cast<LONG*>(i));
+  }
+#else
+  static int Increment(int* i) {
+    return __sync_add_and_fetch(i, 1);
+  }
+  static int Decrement(int* i) {
+    return __sync_sub_and_fetch(i, 1);
+  }
+#endif
+};
+
+} // namespace rtc
+
+#endif // WEBRTC_BASE_CRITICALSECTION_H__