You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ji...@apache.org on 2014/05/01 13:43:45 UTC

svn commit: r1591622 [20/33] - in /httpd/mod_spdy/trunk: ./ base/ base/base.xcodeproj/ base/metrics/ build/ build/all.xcodeproj/ build/build_util.xcodeproj/ build/install.xcodeproj/ build/internal/ build/linux/ build/mac/ build/util/ build/win/ install...

Added: httpd/mod_spdy/trunk/net/instaweb/util/mock_hasher.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/mock_hasher.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/mock_hasher.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/mock_hasher.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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: jmarantz@google.com (Joshua Marantz)
+
+#include "net/instaweb/util/public/mock_hasher.h"
+
+namespace net_instaweb {
+
+MockHasher::~MockHasher() {
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/mock_message_handler.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/mock_message_handler.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/mock_message_handler.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/mock_message_handler.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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:  morlovich@google.com (Maksim Orlovich)
+
+#include "net/instaweb/util/public/mock_message_handler.h"
+
+#include <cstdarg>
+#include <map>
+#include <utility>
+
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/abstract_mutex.h"
+#include "net/instaweb/util/public/google_message_handler.h"
+#include "net/instaweb/util/public/message_handler.h"
+#include "net/instaweb/util/public/thread_system.h"
+
+namespace net_instaweb {
+
+MockMessageHandler::MockMessageHandler() {
+  // TODO(morlovich): Allow providing the thread system as an argument.
+  scoped_ptr<ThreadSystem> thread_runtime(ThreadSystem::CreateThreadSystem());
+  mutex_.reset(thread_runtime->NewMutex());
+}
+
+MockMessageHandler::~MockMessageHandler() {
+}
+
+void MockMessageHandler::MessageVImpl(MessageType type,
+                                      const char* msg,
+                                      va_list args) {
+  ScopedMutex hold_mutex(mutex_.get());
+  GoogleMessageHandler::MessageVImpl(type, msg, args);
+  ++message_counts_[type];
+}
+
+void MockMessageHandler::FileMessageVImpl(MessageType type,
+                                          const char* filename, int line,
+                                          const char* msg, va_list args) {
+  ScopedMutex hold_mutex(mutex_.get());
+  GoogleMessageHandler::FileMessageVImpl(type, filename, line, msg, args);
+  ++message_counts_[type];
+}
+
+int MockMessageHandler::MessagesOfType(MessageType type) const {
+  ScopedMutex hold_mutex(mutex_.get());
+  return MessagesOfTypeImpl(type);
+}
+
+int MockMessageHandler::MessagesOfTypeImpl(MessageType type) const {
+  MessageCountMap::const_iterator i = message_counts_.find(type);
+  if (i != message_counts_.end()) {
+    return i->second;
+  } else {
+    return 0;
+  }
+}
+
+int MockMessageHandler::TotalMessages() const {
+  ScopedMutex hold_mutex(mutex_.get());
+  return TotalMessagesImpl();
+}
+
+int MockMessageHandler::TotalMessagesImpl() const {
+
+  int total = 0;
+  for (MessageCountMap::const_iterator i = message_counts_.begin();
+       i != message_counts_.end(); ++i) {
+    total += i->second;
+  }
+  return total;
+}
+
+int MockMessageHandler::SeriousMessages() const {
+  ScopedMutex hold_mutex(mutex_.get());
+  return TotalMessagesImpl() - MessagesOfTypeImpl(kInfo);
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/mock_message_handler_test.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/mock_message_handler_test.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/mock_message_handler_test.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/mock_message_handler_test.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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: morlovich@google.com (Maksim Orlovich)
+
+#include "net/instaweb/util/public/gtest.h"
+#include "net/instaweb/util/public/mock_message_handler.h"
+#include "net/instaweb/util/public/message_handler.h"
+
+namespace net_instaweb {
+
+namespace {
+
+class MockMessageHandlerTest : public testing::Test {
+ protected:
+  void CheckCounts(int expectInfo, int expectWarn, int expectError,
+                   int expectFatal) {
+    EXPECT_EQ(expectInfo, handler_.MessagesOfType(kInfo));
+    EXPECT_EQ(expectWarn, handler_.MessagesOfType(kWarning));
+    EXPECT_EQ(expectError, handler_.MessagesOfType(kError));
+    EXPECT_EQ(expectFatal, handler_.MessagesOfType(kFatal));
+  }
+
+  MockMessageHandler handler_;
+};
+
+
+TEST_F(MockMessageHandlerTest, Simple) {
+  EXPECT_EQ(0, handler_.TotalMessages());
+  EXPECT_EQ(0, handler_.SeriousMessages());
+
+  handler_.Message(kInfo, "test info message");
+  EXPECT_EQ(1, handler_.TotalMessages());
+  EXPECT_EQ(0, handler_.SeriousMessages());
+  CheckCounts(1, 0, 0, 0);
+
+  handler_.Message(kWarning, "text warning message");
+  EXPECT_EQ(2, handler_.TotalMessages());
+  EXPECT_EQ(1, handler_.SeriousMessages());
+  CheckCounts(1, 1, 0, 0);
+
+  handler_.Message(kError, "text Error message");
+  EXPECT_EQ(3, handler_.TotalMessages());
+  EXPECT_EQ(2, handler_.SeriousMessages());
+  CheckCounts(1, 1, 1, 0);
+
+  // We can't actually test fatal, as it aborts
+  // TODO(morlovich) mock the fatal behavior so the test does not crash
+
+  handler_.Message(kInfo, "another test info message");
+  EXPECT_EQ(4, handler_.TotalMessages());
+  EXPECT_EQ(2, handler_.SeriousMessages());
+  CheckCounts(2, 1, 1, 0);
+}
+
+}  // namespace
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/mock_scheduler.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/mock_scheduler.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/mock_scheduler.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/mock_scheduler.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * 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: jmarantz@google.com (Joshua Marantz)
+
+#include "net/instaweb/util/public/mock_scheduler.h"
+
+#include "net/instaweb/util/public/abstract_mutex.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/mock_timer.h"
+#include "net/instaweb/util/public/scheduler.h"
+#include "net/instaweb/util/public/thread_system.h"
+#include "net/instaweb/util/public/timer.h"
+
+namespace net_instaweb {
+
+MockScheduler::MockScheduler(
+    ThreadSystem* thread_system, MockTimer* timer)
+    : Scheduler(thread_system, timer),
+      timer_(timer) {
+}
+
+MockScheduler::~MockScheduler() {
+}
+
+void MockScheduler::AwaitWakeupUntilUs(int64 wakeup_time_us) {
+  // AwaitWakeupUntilUs is used to effectively move simulated time forward
+  // during unit tests.  Various callbacks in the test infrastructure
+  // can be called as a result of Alarms firing, enabling the simulation of
+  // cache/http fetches with non-zero delay, compute-bound rewrites, or
+  // threaded rewrites.
+  //
+  // To make things simple and deterministic, we simply advance the
+  // time when the work threads quiesce.
+  if (QueuedWorkerPool::AreBusy(workers_) || running_waiting_alarms()) {
+    Scheduler::AwaitWakeupUntilUs(timer_->NowUs() + 10 * Timer::kMsUs);
+  } else {
+    // Can fire off alarms, so we have to be careful to have the lock
+    // relinquished.
+
+    mutex()->Unlock();
+    if (wakeup_time_us >= timer_->NowUs()) {
+      timer_->SetTimeUs(wakeup_time_us);
+    }
+    mutex()->Lock();
+  }
+}
+
+void MockScheduler::AwaitQuiescence() {
+  ScopedMutex lock(mutex());
+  while (QueuedWorkerPool::AreBusy(workers_) || running_waiting_alarms()) {
+    Scheduler::AwaitWakeupUntilUs(timer_->NowUs() + 10 * Timer::kMsUs);
+  }
+}
+
+void MockScheduler::RegisterWorker(QueuedWorkerPool::Sequence* w) {
+  ScopedMutex lock(mutex());
+  workers_.insert(w);
+}
+
+void MockScheduler::UnregisterWorker(QueuedWorkerPool::Sequence* w) {
+  ScopedMutex lock(mutex());
+  workers_.erase(w);
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/mock_scheduler_test.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/mock_scheduler_test.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/mock_scheduler_test.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/mock_scheduler_test.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,73 @@
+// Copyright 2011 Google Inc.
+//
+// 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: jmarantz@google.com (Joshua Marantz)
+
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/abstract_mutex.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/function.h"
+#include "net/instaweb/util/public/gtest.h"
+#include "net/instaweb/util/public/mock_scheduler.h"
+#include "net/instaweb/util/public/mock_timer.h"
+#include "net/instaweb/util/public/thread_system.h"
+#include "net/instaweb/util/public/timer.h"
+
+namespace net_instaweb {
+
+namespace {
+
+// Make the simulated times be very long just to show that we are in
+// mock time and don't need to wait a century for this test to finish.
+const int64 kDelayMs = 50 * Timer::kYearMs;
+const int64 kWaitMs = 100 * Timer::kYearMs;
+
+class Alarm : public Function {
+ public:
+  Alarm() {}
+  virtual void Run() { }
+};
+
+}  // namespace
+
+class MockSchedulerTest : public testing::Test {
+ protected:
+  MockSchedulerTest()
+      : timer_(0),
+        thread_system_(ThreadSystem::CreateThreadSystem()),
+        scheduler_(thread_system_.get(), &timer_) {
+  }
+
+ protected:
+  MockTimer timer_;
+  scoped_ptr<ThreadSystem> thread_system_;
+  MockScheduler scheduler_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockSchedulerTest);
+};
+
+TEST_F(MockSchedulerTest, WakeupOnAdvancementOfSimulatedTime) {
+  timer_.AddAlarm(1000 * kDelayMs, new Alarm());
+  {
+    ScopedMutex lock(scheduler_.mutex());
+    scheduler_.BlockingTimedWait(kWaitMs);
+
+    // The idle-callback will get run after 50 years, but TimedWait
+    // won't actually return until the full 100 years has passed.
+    EXPECT_EQ(kWaitMs, timer_.NowMs());
+  }
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/mock_time_cache.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/mock_time_cache.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/mock_time_cache.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/mock_time_cache.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * 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: morlovich@google.com (Maksim Orlovich)
+//
+// Contains MockTimeCache, which lets one inject MockTimer-simulated
+// delays before callback invocations of a cache object, as well as
+// MockTimeCache::Callback, which chains to a passed-in callback to actually
+// implement the delay.
+
+#include "net/instaweb/util/public/mock_time_cache.h"
+
+#include "net/instaweb/util/public/function.h"
+#include "net/instaweb/util/public/mock_timer.h"
+#include "net/instaweb/util/public/shared_string.h"
+
+namespace net_instaweb {
+
+// This calls a passed-in callback with a mock time delay, forwarding
+// on lookup results.
+class MockTimeCache::DelayCallback : public CacheInterface::Callback {
+ public:
+  DelayCallback(MockTimeCache* parent, Callback* orig_callback)
+      : parent_(parent), orig_callback_(orig_callback) {}
+
+  virtual ~DelayCallback() {}
+
+  virtual void Done(KeyState state) {
+    *orig_callback_->value() = *value();
+
+    parent_->timer()->AddAlarm(
+        parent_->timer()->NowUs() + parent_->delay_us(),
+        new MemberFunction1<CacheInterface::Callback, CacheInterface::KeyState>(
+            &CacheInterface::Callback::Done, orig_callback_, state));
+    delete this;
+  };
+
+ private:
+  MockTimeCache* parent_;
+  Callback* orig_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(DelayCallback);
+};
+
+MockTimeCache::MockTimeCache(MockTimer* timer, CacheInterface* cache)
+    : timer_(timer), cache_(cache), delay_us_(0) {}
+
+MockTimeCache::~MockTimeCache() {}
+
+void MockTimeCache::Get(const GoogleString& key, Callback* callback) {
+  if (delay_us_ == 0) {
+    cache_->Get(key, callback);
+  } else {
+    cache_->Get(key, new DelayCallback(this, callback));
+  }
+}
+
+void MockTimeCache::Put(const GoogleString& key, SharedString* value) {
+  cache_->Put(key, value);
+}
+
+void MockTimeCache::Delete(const GoogleString& key) {
+  cache_->Delete(key);
+}
+
+}  // namespace net_instaweb
+

Added: httpd/mod_spdy/trunk/net/instaweb/util/mock_time_cache_test.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/mock_time_cache_test.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/mock_time_cache_test.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/mock_time_cache_test.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * 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: morlovich@google.com (Maksim Orlovich)
+
+// Unit-test for MockTimeCache
+
+#include "net/instaweb/util/public/mock_time_cache.h"
+
+#include <cstddef>
+#include "net/instaweb/util/cache_test_base.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/gtest.h"
+#include "net/instaweb/util/public/lru_cache.h"
+#include "net/instaweb/util/public/mock_timer.h"
+#include "net/instaweb/util/public/shared_string.h"
+
+namespace net_instaweb {
+namespace {
+
+const size_t kMaxSize = 100;
+
+// We start time from a non-zero value to make sure we don't confuse
+// relative and absolute. The value itself is of no particular significance.
+const int64 kStartTime = 3456;
+
+class MockTimeCacheTest : public CacheTestBase {
+ protected:
+  MockTimeCacheTest()
+      : timer_(kStartTime), lru_cache_(kMaxSize), cache_(&timer_, &lru_cache_) {
+  }
+
+  virtual CacheInterface* Cache() { return &cache_; }
+
+ protected:
+  MockTimer timer_;
+  LRUCache lru_cache_;
+  MockTimeCache cache_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockTimeCacheTest);
+};
+
+TEST_F(MockTimeCacheTest, NoDelayOps) {
+  // Basic operation w/o any delay injected.
+  CheckNotFound("Name");
+  CheckPut("Name", "Value");
+  CheckGet("Name", "Value");
+  cache_.Delete("Name");
+  CheckNotFound("Name");
+}
+
+TEST_F(MockTimeCacheTest, DelayOps) {
+  const int64 kDelayUs = 10000;
+  cache_.set_delay_us(kDelayUs);
+
+  // Load the value.
+  CheckPut("Name", "Value");
+
+  // Try getting...
+  CacheTestBase::Callback result;
+  cache_.Get("Name", &result);
+
+  // Initially, should not have been called.
+  EXPECT_FALSE(result.called_);
+
+  // Move halfways to completion; should still have not been called.
+  timer_.AdvanceUs(kDelayUs / 2);
+  EXPECT_FALSE(result.called_);
+
+  // Now after it expires, it should be OK.
+  timer_.AdvanceUs(kDelayUs / 2 + 1);
+  EXPECT_TRUE(result.called_);
+  EXPECT_EQ(CacheInterface::kAvailable, result.state_);
+  EXPECT_EQ("Value", *result.value()->get());
+
+  // Do the same thing after deleting it.
+  cache_.Delete("Name");
+  cache_.Get("Name", result.Reset());
+  EXPECT_FALSE(result.called_);
+  timer_.AdvanceUs(kDelayUs / 2);
+  EXPECT_FALSE(result.called_);
+  timer_.AdvanceUs(kDelayUs / 2 + 1);
+  EXPECT_TRUE(result.called_);
+  EXPECT_EQ(CacheInterface::kNotFound, result.state_);
+}
+
+}  // namespace
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/mock_timer.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/mock_timer.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/mock_timer.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/mock_timer.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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: jmarantz@google.com (Joshua Marantz)
+
+#include "net/instaweb/util/public/mock_timer.h"
+
+#include <cstddef>
+#include <set>
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/abstract_mutex.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/function.h"
+#include "net/instaweb/util/public/null_mutex.h"
+
+namespace net_instaweb {
+
+const int64 MockTimer::kApr_5_2010_ms = 1270493486000LL;
+
+MockTimer::MockTimer(int64 time_ms)
+    : time_us_(1000 * time_ms),
+      next_index_(0),
+      mutex_(new NullMutex) {
+}
+
+MockTimer::~MockTimer() {
+  while (!alarms_.empty()) {
+    AlarmOrderedSet::iterator p = alarms_.begin();
+    Alarm* alarm = *p;
+    alarms_.erase(p);
+    alarm->CallCancel();
+  }
+}
+
+MockTimer::Alarm::Alarm(int64 wakeup_time_us, Function* closure)
+    : index_(kIndexUninitialized),
+      wakeup_time_us_(wakeup_time_us),
+      closure_(closure) {
+}
+
+MockTimer::Alarm::~Alarm() {
+  DCHECK(closure_ == NULL)
+      << "Must call CallRun or CallCancel before deleting Alarm";
+}
+
+int MockTimer::Alarm::Compare(const Alarm* that) const {
+  int cmp = 0;
+  if (wakeup_time_us_ < that->wakeup_time_us_) {
+    cmp = -1;
+  } else if (wakeup_time_us_ > that->wakeup_time_us_) {
+    cmp = 1;
+  } else if (index_ < that->index_) {
+    cmp = -1;
+  } else if (index_ > that->index_) {
+    cmp = 1;
+  }
+  return cmp;
+}
+
+void MockTimer::Alarm::SetIndex(int index) {
+  CHECK_EQ(kIndexUninitialized, index_);
+  index_ = index;
+}
+
+void MockTimer::Alarm::CallRun() {
+  closure_->CallRun();
+  closure_ = NULL;
+  delete this;
+}
+
+void MockTimer::Alarm::CallCancel() {
+  closure_->CallCancel();
+  closure_ = NULL;
+  delete this;
+}
+
+MockTimer::Alarm* MockTimer::AddAlarm(int64 wakeup_time_us, Function* closure) {
+  bool call_now = false;
+  Alarm* alarm = new Alarm(wakeup_time_us, closure);
+  {
+    ScopedMutex lock(mutex_.get());
+    if (time_us_ >= alarm->wakeup_time_us()) {
+      call_now = true;
+    } else {
+      alarm->SetIndex(next_index_++);
+      size_t prev_count = alarms_.size();
+      alarms_.insert(alarm);
+      CHECK_EQ(1 + prev_count, alarms_.size());
+    }
+    // Release lock before running potentially the Alarm.
+  }
+  if (call_now) {
+    alarm->CallRun();
+    alarm = NULL;
+  }
+  return alarm;
+}
+
+void MockTimer::CancelAlarm(Alarm* alarm) {
+  ScopedMutex lock(mutex_.get());
+  int erased = alarms_.erase(alarm);
+  if (erased == 1) {
+    alarm->CallCancel();
+  } else {
+    LOG(DFATAL) << "Canceled alarm not found";
+  }
+}
+
+void MockTimer::SetTimeUs(int64 new_time_us) {
+  mutex_->Lock();
+  while (!alarms_.empty()) {
+    AlarmOrderedSet::iterator p = alarms_.begin();
+    Alarm* alarm = *p;
+    int64 wakeup_us = alarm->wakeup_time_us();
+    if (new_time_us < wakeup_us) {
+      break;
+    } else {
+      alarms_.erase(p);
+      if (wakeup_us > time_us_) {
+        time_us_ = wakeup_us;
+      }
+      mutex_->Unlock();
+      alarm->CallRun();
+      mutex_->Lock();
+    }
+  }
+
+  // If an Alarm::Run function moved us forward in time, don't move us back.
+  if (time_us_ < new_time_us) {
+    time_us_ = new_time_us;
+  }
+  mutex_->Unlock();
+}
+
+int64 MockTimer::NowUs() const {
+  ScopedMutex(mutex_.get());
+  return time_us_;
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/mock_timer_test.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/mock_timer_test.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/mock_timer_test.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/mock_timer_test.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,164 @@
+// Copyright 2011 Google Inc.
+//
+// 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: jmarantz@google.com (Joshua Marantz)
+
+#include "net/instaweb/util/public/mock_timer.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/function.h"
+#include "net/instaweb/util/public/gtest.h"
+#include "net/instaweb/util/public/string.h"
+
+namespace net_instaweb {
+
+namespace {
+
+// This is an alarm implementation which adds new alarms and optionally advances
+// time in its callback.
+class ChainedAlarm : public Function {
+ public:
+  ChainedAlarm(MockTimer* timer, int* count, bool advance)
+    : timer_(timer),
+      count_(count) ,
+      advance_(advance) {}
+
+  virtual void Run() {
+    if (--*count_ > 0) {
+      timer_->AddAlarm(timer_->NowUs() + 100,
+                       new ChainedAlarm(timer_, count_, advance_));
+      if (advance_) {
+        timer_->AdvanceMs(100);
+      }
+    }
+  }
+
+ private:
+  MockTimer* timer_;
+  int* count_;
+  bool advance_;
+};
+
+}  // namespace
+
+class MockTimerTest : public testing::Test {
+ protected:
+  MockTimerTest()
+      : timer_(new MockTimer(0)),
+        was_run_(false),
+        was_cancelled_(false) {}
+
+  MockTimer::Alarm* AddTask(int64 wakeup_time_us, char c) {
+    Function* append_char = new MemberFunction1<GoogleString, char>(
+        &GoogleString::push_back, &string_, c);
+    return timer_->AddAlarm(wakeup_time_us, append_char);
+  }
+
+  void Run() {
+    was_run_ = true;
+  }
+
+  void Cancel() {
+    was_cancelled_ = true;
+  }
+
+  MockTimer::Alarm* AddRunCancelAlarm(int64 timeout_ms) {
+    MockTimerTest* mock_timer_test = this;  // Implicit upcast.
+    return timer_->AddAlarm(timeout_ms, new MemberFunction0<MockTimerTest>(
+        &MockTimerTest::Run, &MockTimerTest::Cancel, mock_timer_test));
+  }
+
+ protected:
+  scoped_ptr<MockTimer> timer_;
+  GoogleString string_;
+  bool was_run_;
+  bool was_cancelled_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockTimerTest);
+};
+
+TEST_F(MockTimerTest, ScheduleOrdering) {
+  AddTask(1, '1');
+  AddTask(3, '3');
+  AddTask(2, '2');
+  timer_->AdvanceUs(3);  // runs all 3 tasks
+  EXPECT_EQ("123", string_);
+}
+
+TEST_F(MockTimerTest, SchedulePartial) {
+  AddTask(5, '5');
+  AddTask(5, '6');  // same wakeup time, but order is preserved.
+  AddTask(6, '7');
+  AddTask(3, '3');
+  AddTask(2, '2');
+  AddTask(4, '4');
+  AddTask(1, '1');
+  timer_->AdvanceUs(3);  // runs first 3 tasks
+  EXPECT_EQ("123", string_);
+  string_.clear();
+  timer_->AdvanceUs(3);  // runs next 4 tasks
+  EXPECT_EQ("4567", string_);
+}
+
+TEST_F(MockTimerTest, Cancellation) {
+  AddTask(1, '1');
+  MockTimer::Alarm* alarm_to_cancel = AddTask(3, '3');
+  AddTask(2, '2');
+  AddTask(4, '4');
+  timer_->CancelAlarm(alarm_to_cancel);
+  timer_->AdvanceUs(4);  // runs the 3 tasks not canceled.
+  EXPECT_EQ("124", string_);
+}
+
+// Verifies that we can add a new alarm from an Alarm::Run() method.
+TEST_F(MockTimerTest, ChainedAlarms) {
+  int count = 10;
+  timer_->AddAlarm(100, new ChainedAlarm(timer_.get(), &count, false));
+  timer_->AdvanceMs(1000);
+  EXPECT_EQ(0, count);
+}
+
+// Verifies that we can advance time from an Alarm::Run() method.
+TEST_F(MockTimerTest, AdvanceFromRun) {
+  int count = 10;
+  timer_->AddAlarm(100, new ChainedAlarm(timer_.get(), &count, true));
+  timer_->AdvanceMs(100);
+  EXPECT_EQ(0, count);
+}
+
+TEST_F(MockTimerTest, RunNotCancelled) {
+  // First, let the alarm run normally.
+  AddRunCancelAlarm(100);
+  timer_->AdvanceUs(200);
+  EXPECT_TRUE(was_run_);
+  EXPECT_FALSE(was_cancelled_);
+}
+
+TEST_F(MockTimerTest, CancelledExplicitly) {
+  // Next cancel the alarm explicitly before it runs.
+  MockTimer::Alarm* alarm = AddRunCancelAlarm(500);
+  timer_->CancelAlarm(alarm);
+  EXPECT_FALSE(was_run_);
+  EXPECT_TRUE(was_cancelled_);
+}
+
+TEST_F(MockTimerTest, CancelledDueToMockTimerDestruction) {
+  // Finally, let the alarm be implicitly cancelled by deleting the timer.
+  AddRunCancelAlarm(500);
+  timer_.reset(NULL);
+  EXPECT_FALSE(was_run_);
+  EXPECT_TRUE(was_cancelled_);
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/named_lock_manager.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/named_lock_manager.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/named_lock_manager.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/named_lock_manager.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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: jmaessen@google.com (Jan Maessen)
+
+#include "net/instaweb/util/public/named_lock_manager.h"
+
+namespace net_instaweb {
+
+NamedLock::~NamedLock() { }
+
+NamedLockManager::~NamedLockManager() { }
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/null_message_handler.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/null_message_handler.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/null_message_handler.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/null_message_handler.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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: lsong@google.com (Libo Song)
+
+#include "net/instaweb/util/public/null_message_handler.h"
+
+#include <cstdarg>
+
+#include "net/instaweb/util/public/message_handler.h"
+
+namespace net_instaweb {
+
+NullMessageHandler::~NullMessageHandler() {
+}
+
+void NullMessageHandler::MessageVImpl(MessageType type, const char* msg,
+                                      va_list args) {
+}
+
+void NullMessageHandler::FileMessageVImpl(MessageType type, const char* file,
+                                          int line, const char* msg,
+                                          va_list args) {
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/null_mutex.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/null_mutex.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/null_mutex.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/null_mutex.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * 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: jmarantz@google.com (Joshua Marantz)
+
+#include "net/instaweb/util/public/null_mutex.h"
+
+namespace net_instaweb {
+
+NullMutex::~NullMutex() {
+}
+
+void NullMutex::Lock() {
+}
+
+void NullMutex::Unlock() {
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/null_statistics.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/null_statistics.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/null_statistics.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/null_statistics.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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: jmarantz@google.com (Joshua Marantz)
+
+#include "net/instaweb/util/public/null_statistics.h"
+#include "net/instaweb/util/public/string_util.h"
+
+namespace net_instaweb {
+
+NullStatisticsVariable::~NullStatisticsVariable() {
+}
+
+NullStatistics::~NullStatistics() {
+}
+
+NullStatisticsVariable* NullStatistics::NewVariable(
+    const StringPiece& name, int index) {
+  return new NullStatisticsVariable;
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/null_writer.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/null_writer.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/null_writer.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/null_writer.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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: jmarantz@google.com (Joshua Marantz)
+
+#include "net/instaweb/util/public/null_writer.h"
+#include "net/instaweb/util/public/string_util.h"
+
+namespace net_instaweb {
+class MessageHandler;
+
+NullWriter::~NullWriter() {
+}
+
+bool NullWriter::Write(const StringPiece& str, MessageHandler* handler) {
+  return true;
+}
+
+bool NullWriter::Flush(MessageHandler* handler) {
+  return true;
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/pool_test.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/pool_test.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/pool_test.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/pool_test.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,201 @@
+// Copyright 2011 Google Inc.
+//
+// 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: jmaessen@google.com (Jan Maessen)
+
+#include "net/instaweb/util/public/pool.h"
+
+#include <list>
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/gtest.h"
+#include "net/instaweb/util/public/pool_element.h"
+#include "net/instaweb/util/public/string.h"
+
+namespace net_instaweb {
+
+namespace {
+
+// Pool element containing an int, for test purposes.
+class IntElement : public PoolElement<IntElement> {
+ public:
+  IntElement() { }
+
+  const int num() const { return num_; }
+  void set_num(int num) { num_ = num; }
+
+ private:
+  int num_;
+
+  DISALLOW_COPY_AND_ASSIGN(IntElement);
+};
+
+typedef Pool<IntElement> IntPool;
+typedef PoolElement<IntElement>::Position PoolPosition;
+
+class PoolTest : public testing::Test {
+ protected:
+  PoolTest() {
+    for (int i = 0; i < arraysize(elements_); ++i) {
+      elements_[i].set_num(i);
+    }
+  }
+
+  ~PoolTest() {
+    pool_.Clear();
+  }
+
+  // Add just the ith element to pool_
+  void Add(int i) {
+    int sz = pool_.size();
+    pool_.Add(&elements_[i]);
+    EXPECT_FALSE(pool_.empty());
+    EXPECT_EQ(sz + 1, pool_.size());
+  }
+
+  // Add the first n elements_ to pool_ for test setup.
+  void Adds(int n) {
+    for (int i = 0; i < n; ++i) {
+      Add(i);
+    }
+  }
+
+  // Expect that pool_ contains the n elements in expected, in order.
+  void ExpectContainsElements(int n, const int* expected) {
+    EXPECT_EQ(n, pool_.size());
+    PoolPosition iter = pool_.begin();
+    for (int i = 0; i < n; ++i) {
+      EXPECT_EQ(expected[i], (*iter)->num()) << "Actually " << Dump();
+      ++iter;
+    }
+  }
+
+  // Expect that pool_ contains the numbers in [lo,hi], in order.
+  void ExpectContains(int lo, int hi) {
+    EXPECT_EQ(hi - lo + 1, pool_.size());
+    IntPool::iterator iter = pool_.begin();
+    for (int i = lo; i <= hi; ++i) {
+      EXPECT_EQ(i, (*iter)->num()) << "Actually " << Dump();
+      ++iter;
+    }
+  }
+
+  // Expect that the next element removed will be i
+  void ExpectRemoveOldest(int i) {
+    int sz = pool_.size();
+    EXPECT_FALSE(pool_.empty());
+    IntElement* e = pool_.oldest();
+    EXPECT_EQ(i, e->num());
+    EXPECT_EQ(e, pool_.RemoveOldest());
+    EXPECT_EQ(sz - 1, pool_.size());
+  }
+
+  // Remove the element i from pool_
+  void Remove(int i) {
+    int sz = pool_.size();
+    EXPECT_FALSE(pool_.empty());
+    EXPECT_EQ(i, pool_.Remove(&elements_[i])->num());
+    EXPECT_EQ(sz - 1, pool_.size());
+  }
+
+  // Dump the pool value.  Yields, dirty, and compact string (but isn't robust
+  // if we were to use enormous pool sizes during testing; since we're backed by
+  // collections this should not be necessary).
+  GoogleString Dump() {
+    GoogleString buf;
+    for (IntPool::iterator iter = pool_.begin(); iter != pool_.end(); ++iter) {
+      buf.push_back((*iter)->num() + '0');
+    }
+    return buf;
+  }
+
+  IntPool pool_;
+  IntElement elements_[4];
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PoolTest);
+};
+
+TEST_F(PoolTest, TestInsertAndOrderedRemoveOldest) {
+  EXPECT_TRUE(pool_.empty());
+  EXPECT_EQ(0, pool_.size());
+  Adds(4);
+  ExpectContains(0, 3);
+  ExpectRemoveOldest(0);
+  ExpectRemoveOldest(1);
+  ExpectRemoveOldest(2);
+  ExpectRemoveOldest(3);
+  EXPECT_TRUE(pool_.empty());
+  EXPECT_TRUE(NULL == pool_.RemoveOldest());
+}
+
+TEST_F(PoolTest, TestInsertAndRemove) {
+  Adds(4);
+  ExpectContains(0, 3);
+  Remove(0);
+  ExpectContains(1, 3);
+  Remove(1);
+  ExpectContains(2, 3);
+  Remove(2);
+  ExpectContains(3, 3);
+  Remove(3);
+  EXPECT_TRUE(pool_.empty());
+}
+
+TEST_F(PoolTest, TestRemoveAndReinsertFront) {
+  Adds(4);
+  ExpectContains(0, 3);
+  Remove(3);
+  ExpectContains(0, 2);
+  Add(3);
+  ExpectContains(0, 3);
+}
+
+TEST_F(PoolTest, TestRemoveAndReinsertBack) {
+  Adds(4);
+  ExpectContains(0, 3);
+  Remove(0);
+  ExpectContains(1, 3);
+  Add(0);
+  ExpectRemoveOldest(1);
+  ExpectRemoveOldest(2);
+  ExpectRemoveOldest(3);
+  ExpectRemoveOldest(0);
+}
+
+TEST_F(PoolTest, TestRemoveAndReinsertMiddle) {
+  Adds(4);
+  ExpectContains(0, 3);
+  Remove(2);
+  const int kMiddleExpected[] = { 0, 1, 3 };
+  ExpectContainsElements(arraysize(kMiddleExpected), kMiddleExpected);
+  Add(2);
+  ExpectRemoveOldest(0);
+  ExpectRemoveOldest(1);
+  ExpectRemoveOldest(3);
+  ExpectRemoveOldest(2);
+}
+
+TEST_F(PoolTest, TestClear) {
+  Adds(4);
+  ExpectContains(0, 3);
+  pool_.Clear();
+  EXPECT_TRUE(pool_.empty());
+}
+
+TEST_F(PoolTest, OldestEmpty) {
+  EXPECT_TRUE(NULL == pool_.oldest());
+}
+
+}  // namespace
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/pthread_condvar.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/pthread_condvar.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/pthread_condvar.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/pthread_condvar.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,73 @@
+// Copyright 2011 Google Inc.
+//
+// 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: jmaessen@google.com (Jan Maessen)
+
+#include "net/instaweb/util/public/pthread_condvar.h"
+
+#include <pthread.h>
+#include <sys/time.h>
+#include <cerrno>
+#include <ctime>
+
+#include "base/logging.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/pthread_mutex.h"
+#include "net/instaweb/util/public/timer.h"
+
+namespace net_instaweb {
+
+PthreadCondvar::~PthreadCondvar() {
+  pthread_cond_destroy(&condvar_);
+}
+
+void PthreadCondvar::Signal() {
+  pthread_cond_signal(&condvar_);
+}
+
+void PthreadCondvar::Broadcast() {
+  pthread_cond_broadcast(&condvar_);
+}
+
+void PthreadCondvar::Wait() {
+  pthread_cond_wait(&condvar_, &mutex_->mutex_);
+}
+
+void PthreadCondvar::TimedWait(int64 timeout_ms) {
+  const int64 kMsNs = Timer::kSecondNs / Timer::kSecondMs;
+  struct timespec timeout;
+  struct timeval current_time;
+  // convert timeout_ms to seconds and ms
+  int64 timeout_sec_incr = timeout_ms / Timer::kSecondMs;
+  timeout_ms %= Timer::kSecondMs;
+  // Figure out current time, compute absolute time for timeout
+  // Carrying ns to s as appropriate.  As morlovich notes, we
+  // get *really close* to overflowing a 32-bit tv_nsec here,
+  // so this code should be modified with caution.
+  if (gettimeofday(&current_time, NULL) != 0) {
+    LOG(FATAL) << "Could not determine time of day";
+  }
+  timeout.tv_nsec = current_time.tv_usec * 1000 + timeout_ms * kMsNs;
+  timeout_sec_incr += timeout.tv_nsec / Timer::kSecondNs;
+  timeout.tv_nsec %= Timer::kSecondNs;
+  timeout.tv_sec = current_time.tv_sec + static_cast<time_t>(timeout_sec_incr);
+  // Finally we actually get to wait.
+  pthread_cond_timedwait(&condvar_, &mutex_->mutex_, &timeout);
+}
+
+void PthreadCondvar::Init() {
+  while (pthread_cond_init(&condvar_, NULL) == EAGAIN) { }
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/pthread_condvar_test.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/pthread_condvar_test.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/pthread_condvar_test.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/pthread_condvar_test.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,103 @@
+// Copyright 2011 Google Inc.
+//
+// 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: jmaessen@google.com (Jan Maessen)
+
+#include "net/instaweb/util/public/pthread_condvar.h"
+
+#include <pthread.h>
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/condvar.h"
+#include "net/instaweb/util/public/condvar_test_base.h"
+#include "net/instaweb/util/public/google_timer.h"
+#include "net/instaweb/util/public/gtest.h"
+#include "net/instaweb/util/public/pthread_mutex.h"
+#include "net/instaweb/util/public/thread_system.h"
+
+namespace net_instaweb {
+class Timer;
+
+class PthreadCondvarTest : public CondvarTestBase {
+ protected:
+  PthreadCondvarTest()
+      : pthread_mutex_(),
+        pthread_startup_condvar_(&pthread_mutex_),
+        pthread_condvar_(&pthread_mutex_) {
+    Init(&pthread_mutex_, &pthread_startup_condvar_, &pthread_condvar_);
+  }
+
+  virtual void CreateHelper() {
+    pthread_create(&helper_thread_, NULL,
+                   &HelperThread, this);
+  }
+
+  virtual void FinishHelper() {
+    pthread_join(helper_thread_, NULL);
+  }
+
+  virtual Timer* timer() { return &timer_; }
+
+  PthreadMutex pthread_mutex_;
+  PthreadCondvar pthread_startup_condvar_;
+  PthreadCondvar pthread_condvar_;
+  pthread_t helper_thread_;
+  GoogleTimer timer_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PthreadCondvarTest);
+};
+
+TEST_F(PthreadCondvarTest, TestStartup) {
+  StartupTest();
+}
+
+TEST_F(PthreadCondvarTest, BlindSignals) {
+  BlindSignalsTest();
+}
+
+TEST_F(PthreadCondvarTest, BroadcastBlindSignals) {
+  signal_method_ = &ThreadSystem::Condvar::Broadcast;
+  BlindSignalsTest();
+}
+
+TEST_F(PthreadCondvarTest, TestPingPong) {
+  PingPongTest();
+}
+
+TEST_F(PthreadCondvarTest, BroadcastTestPingPong) {
+  signal_method_ = &ThreadSystem::Condvar::Broadcast;
+  PingPongTest();
+}
+
+TEST_F(PthreadCondvarTest, TestTimeout) {
+  TimeoutTest();
+}
+
+TEST_F(PthreadCondvarTest, TestLongTimeout1200) {
+  // We pick a value over a second because the implementation special-cases
+  // that situation.
+  LongTimeoutTest(1100);
+  LongTimeoutTest(100);
+}
+
+TEST_F(PthreadCondvarTest, TimeoutPingPong) {
+  TimeoutPingPongTest();
+}
+
+TEST_F(PthreadCondvarTest, BroadcastTimeoutPingPong) {
+  signal_method_ = &ThreadSystem::Condvar::Broadcast;
+  TimeoutPingPongTest();
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/pthread_mutex.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/pthread_mutex.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/pthread_mutex.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/pthread_mutex.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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: jmarantz@google.com (Joshua Marantz)
+
+#include "net/instaweb/util/public/pthread_mutex.h"
+
+#include <pthread.h>
+#include "net/instaweb/util/public/pthread_condvar.h"
+#include "net/instaweb/util/public/thread_system.h"
+
+namespace net_instaweb {
+
+PthreadMutex::PthreadMutex() {
+  pthread_mutex_init(&mutex_, NULL);
+}
+
+PthreadMutex::~PthreadMutex() {
+  pthread_mutex_destroy(&mutex_);
+}
+
+void PthreadMutex::Lock() {
+  pthread_mutex_lock(&mutex_);
+}
+
+void PthreadMutex::Unlock() {
+  pthread_mutex_unlock(&mutex_);
+}
+
+ThreadSystem::Condvar* PthreadMutex::NewCondvar() {
+  return new PthreadCondvar(this);
+}
+
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/pthread_rw_lock.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/pthread_rw_lock.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/pthread_rw_lock.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/pthread_rw_lock.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * 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: pulkitg@google.com (Pulkit Goyal)
+
+#include "net/instaweb/util/public/pthread_rw_lock.h"
+
+#include <pthread.h>
+
+namespace net_instaweb {
+
+PthreadRWLock::PthreadRWLock() {
+  pthread_rwlockattr_init(&attr_);
+  // New writer lock call is given preference over existing reader lock calls,
+  // so that writer lock call will never get starved. However, it is not allowed
+  // if there exists any recursive reader lock call to prevent deadlocks.
+  pthread_rwlockattr_setkind_np(&attr_,
+                                PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+  pthread_rwlock_init(&rwlock_, &attr_);
+}
+
+PthreadRWLock::~PthreadRWLock() {
+  pthread_rwlockattr_destroy(&attr_);
+  pthread_rwlock_destroy(&rwlock_);
+}
+
+void PthreadRWLock::Lock() {
+  pthread_rwlock_wrlock(&rwlock_);
+}
+
+void PthreadRWLock::Unlock() {
+  pthread_rwlock_unlock(&rwlock_);
+}
+
+void PthreadRWLock::ReaderLock() {
+  pthread_rwlock_rdlock(&rwlock_);
+}
+
+void PthreadRWLock::ReaderUnlock() {
+  pthread_rwlock_unlock(&rwlock_);
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/pthread_shared_mem.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/pthread_shared_mem.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/pthread_shared_mem.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/pthread_shared_mem.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,223 @@
+// Copyright 2011 Google Inc.
+//
+// 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: morlovich@google.com (Maksim Orlovich)
+
+#include "net/instaweb/util/public/pthread_shared_mem.h"
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <cerrno>
+#include <cstddef>
+#include <map>
+#include <utility>
+#include "net/instaweb/util/public/abstract_shared_mem.h"
+#include "net/instaweb/util/public/abstract_mutex.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/message_handler.h"
+#include "net/instaweb/util/public/string.h"
+
+namespace net_instaweb {
+
+namespace {
+
+// This implementation relies on readonly copies of old memory and shared R/W
+// mappings being kept across a fork. It simply stashes addresses of
+// shared mmap segments into a map where kid processes can pick them up.
+
+// close() a fd logging failure and dealing with EINTR.
+void CheckedClose(int fd, MessageHandler* message_handler) {
+  while (close(fd) != 0) {
+    if (errno != EINTR) {
+      message_handler->Message(kWarning, "Problem closing SHM segment fd:%d",
+                               errno);
+      return;
+    }
+  }
+}
+
+// Unlike PthreadMutex this doesn't own the lock, but rather refers to an
+// external one.
+class PthreadSharedMemMutex : public AbstractMutex {
+ public:
+  explicit PthreadSharedMemMutex(pthread_mutex_t* external_mutex)
+      : external_mutex_(external_mutex) {}
+
+  virtual void Lock() {
+    pthread_mutex_lock(external_mutex_);
+  }
+
+  virtual void Unlock() {
+    pthread_mutex_unlock(external_mutex_);
+  }
+
+ private:
+  pthread_mutex_t* external_mutex_;
+
+  DISALLOW_COPY_AND_ASSIGN(PthreadSharedMemMutex);
+};
+
+class PthreadSharedMemSegment : public AbstractSharedMemSegment {
+ public:
+  // We will be representing memory mapped in the [base, base + size) range.
+  PthreadSharedMemSegment(char* base, size_t size, MessageHandler* handler)
+      : base_(base),
+        size_(size) {
+  }
+
+  virtual ~PthreadSharedMemSegment() {
+  }
+
+  virtual volatile char* Base() {
+    return base_;
+  }
+
+  virtual size_t SharedMutexSize() const {
+    return sizeof(pthread_mutex_t);
+  }
+
+  virtual bool InitializeSharedMutex(size_t offset, MessageHandler* handler) {
+    pthread_mutexattr_t attr;
+    if (pthread_mutexattr_init(&attr) != 0) {
+      handler->Message(kError, "pthread_mutexattr_init failed with errno:%d",
+                       errno);
+      return false;
+    }
+
+    if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) != 0) {
+      pthread_mutexattr_destroy(&attr);
+      handler->Message(
+          kError, "pthread_mutexattr_setpshared failed with errno:%d", errno);
+      return false;
+    }
+
+    if (pthread_mutex_init(MutexPtr(offset), &attr) != 0) {
+      pthread_mutexattr_destroy(&attr);
+      handler->Message(kError, "pthread_mutex_init failed with errno:%d",
+                       errno);
+      return false;
+    }
+
+    pthread_mutexattr_destroy(&attr);
+    return true;
+  }
+
+  virtual AbstractMutex* AttachToSharedMutex(size_t offset) {
+    return new PthreadSharedMemMutex(MutexPtr(offset));
+  }
+
+ private:
+  pthread_mutex_t* MutexPtr(size_t offset) {
+    return reinterpret_cast<pthread_mutex_t*>(base_ + offset);
+  }
+
+  char* const base_;
+  const size_t size_;
+
+  DISALLOW_COPY_AND_ASSIGN(PthreadSharedMemSegment);
+};
+
+pthread_mutex_t segment_bases_lock = PTHREAD_MUTEX_INITIALIZER;
+
+}  // namespace
+
+PthreadSharedMem::SegmentBaseMap* PthreadSharedMem::segment_bases_ = NULL;
+
+PthreadSharedMem::PthreadSharedMem() {
+}
+
+PthreadSharedMem::~PthreadSharedMem() {
+}
+
+size_t PthreadSharedMem::SharedMutexSize() const {
+  return sizeof(pthread_mutex_t);
+}
+
+AbstractSharedMemSegment* PthreadSharedMem::CreateSegment(
+    const GoogleString& name, size_t size, MessageHandler* handler) {
+  // Create the memory
+  int fd = open("/dev/zero", O_RDWR);
+  if (fd == -1) {
+    handler->Message(kError, "Unable to create SHM segment %s, errno=%d.",
+                     name.c_str(), errno);
+    return NULL;
+  }
+
+  // map it
+  char* base = reinterpret_cast<char*>(
+                   mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
+  CheckedClose(fd, handler);
+  if (base == MAP_FAILED) {
+    return NULL;
+  }
+
+  SegmentBaseMap* bases = AcquireSegmentBases();
+  (*bases)[name] = base;
+  UnlockSegmentBases();
+  return new PthreadSharedMemSegment(base, size, handler);
+}
+
+AbstractSharedMemSegment* PthreadSharedMem::AttachToSegment(
+    const GoogleString& name, size_t size, MessageHandler* handler) {
+  SegmentBaseMap* bases = AcquireSegmentBases();
+  SegmentBaseMap::const_iterator i = bases->find(name);
+  if (i == bases->end()) {
+    handler->Message(kError, "Unable to find SHM segment %s to attach to.",
+                     name.c_str());
+    UnlockSegmentBases();
+    return NULL;
+  }
+  char* base = i->second;
+  UnlockSegmentBases();
+  return new PthreadSharedMemSegment(base, size, handler);
+}
+
+void PthreadSharedMem::DestroySegment(const GoogleString& name,
+                                      MessageHandler* handler) {
+  // Note that in the process state children will not see any mutations
+  // we make here, so it acts mostly for checking in that case.
+  SegmentBaseMap* bases = AcquireSegmentBases();
+  SegmentBaseMap::iterator i = bases->find(name);
+  if (i != bases->end()) {
+    bases->erase(i);
+    if (bases->empty()) {
+      delete segment_bases_;
+      segment_bases_ = NULL;
+    }
+  } else {
+    handler->Message(kError, "Attempt to destroy unknown SHM segment %s.",
+                     name.c_str());
+  }
+  UnlockSegmentBases();
+}
+
+PthreadSharedMem::SegmentBaseMap* PthreadSharedMem::AcquireSegmentBases() {
+  PthreadSharedMemMutex lock(&segment_bases_lock);
+  lock.Lock();
+
+  if (segment_bases_ == NULL) {
+    segment_bases_ = new SegmentBaseMap();
+  }
+
+  return segment_bases_;
+}
+
+void  PthreadSharedMem::UnlockSegmentBases() {
+  PthreadSharedMemMutex lock(&segment_bases_lock);
+  lock.Unlock();
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/pthread_shared_mem_test.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/pthread_shared_mem_test.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/pthread_shared_mem_test.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/pthread_shared_mem_test.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,160 @@
+// Copyright 2011 Google Inc.
+//
+// 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: morlovich@google.com (Maksim Orlovich)
+
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include <cstddef>
+#include <cstdlib>
+#include <vector>
+
+#include "net/instaweb/util/public/function.h"
+#include "net/instaweb/util/public/gtest.h"
+#include "net/instaweb/util/public/pthread_shared_mem.h"
+#include "net/instaweb/util/public/shared_circular_buffer_test_base.h"
+#include "net/instaweb/util/public/shared_dynamic_string_map_test_base.h"
+#include "net/instaweb/util/public/shared_mem_lock_manager_test_base.h"
+#include "net/instaweb/util/public/shared_mem_referer_statistics_test_base.h"
+#include "net/instaweb/util/public/shared_mem_statistics_test_base.h"
+#include "net/instaweb/util/public/shared_mem_test_base.h"
+
+namespace net_instaweb {
+class AbstractSharedMem;
+
+namespace {
+
+// We test operation of pthread shared memory with both thread & process
+// use, which is what PthreadSharedMemThreadEnv and PthreadSharedMemProcEnv
+// provide.
+
+class PthreadSharedMemEnvBase : public SharedMemTestEnv {
+ public:
+  virtual AbstractSharedMem* CreateSharedMemRuntime() {
+    return new PthreadSharedMem();
+  }
+
+  virtual void ShortSleep() {
+    usleep(1000);
+  }
+};
+
+class PthreadSharedMemThreadEnv : public PthreadSharedMemEnvBase {
+ public:
+  virtual bool CreateChild(Function* callback) {
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, InvokeCallback, callback) != 0) {
+      return false;
+    }
+    child_threads_.push_back(thread);
+    return true;
+  }
+
+  virtual void WaitForChildren() {
+    for (size_t i = 0; i < child_threads_.size(); ++i) {
+      void* result = this;  // non-NULL -> failure.
+      EXPECT_EQ(0, pthread_join(child_threads_[i], &result));
+      EXPECT_EQ(NULL, result) << "Child reported failure";
+    }
+    child_threads_.clear();
+  }
+
+  virtual void ChildFailed() {
+    // In case of failure, we exit the thread with a non-NULL status.
+    // We leak the callback object in that case, but this only gets called
+    // for test failures anyway.
+    pthread_exit(this);
+  }
+
+ private:
+  static void* InvokeCallback(void* raw_callback_ptr) {
+    Function* callback = static_cast<Function*>(raw_callback_ptr);
+    callback->CallRun();
+    return NULL;  // Used to denote success
+  }
+
+  std::vector<pthread_t> child_threads_;
+};
+
+class PthreadSharedMemProcEnv : public PthreadSharedMemEnvBase {
+ public:
+  virtual bool CreateChild(Function* callback) {
+    pid_t ret = fork();
+    if (ret == -1) {
+      // Failure
+      callback->CallCancel();
+      return false;
+    } else if (ret == 0) {
+      // Child.
+      callback->CallRun();
+      std::exit(0);
+    } else {
+      // Parent.
+      child_processes_.push_back(ret);
+      callback->CallCancel();
+      return true;
+    }
+  }
+
+  virtual void WaitForChildren() {
+    for (size_t i = 0; i < child_processes_.size(); ++i) {
+      int status;
+      EXPECT_EQ(child_processes_[i], waitpid(child_processes_[i], &status, 0));
+      EXPECT_TRUE(WIFEXITED(status)) << "Child did not exit cleanly";
+      EXPECT_EQ(0, WEXITSTATUS(status)) << "Child reported failure";
+    }
+    child_processes_.clear();
+  }
+
+  virtual void ChildFailed() {
+    exit(-1);
+  }
+
+ private:
+  std::vector<pid_t> child_processes_;
+};
+
+
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadProc, SharedCircularBufferTestTemplate,
+                              PthreadSharedMemProcEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadProc, SharedDynamicStringMapTestTemplate,
+                              PthreadSharedMemProcEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadProc, SharedMemLockManagerTestTemplate,
+                              PthreadSharedMemProcEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadProc,
+                              SharedMemRefererStatisticsTestTemplate,
+                              PthreadSharedMemProcEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadProc, SharedMemStatisticsTestTemplate,
+                              PthreadSharedMemProcEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadProc, SharedMemTestTemplate,
+                              PthreadSharedMemProcEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadThread, SharedCircularBufferTestTemplate,
+                              PthreadSharedMemThreadEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadThread, SharedDynamicStringMapTestTemplate,
+                              PthreadSharedMemThreadEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadThread, SharedMemLockManagerTestTemplate,
+                              PthreadSharedMemThreadEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadThread,
+                              SharedMemRefererStatisticsTestTemplate,
+                              PthreadSharedMemThreadEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadThread, SharedMemStatisticsTestTemplate,
+                              PthreadSharedMemThreadEnv);
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadThread, SharedMemTestTemplate,
+                              PthreadSharedMemThreadEnv);
+
+}  // namespace
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/pthread_thread_system.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/pthread_thread_system.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/pthread_thread_system.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/pthread_thread_system.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * 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: morlovich@google.com (Maksim Orlovich)
+
+#include "net/instaweb/util/public/pthread_thread_system.h"
+
+#include <pthread.h>
+
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/pthread_rw_lock.h"
+#include "net/instaweb/util/public/pthread_mutex.h"
+#include "net/instaweb/util/public/thread.h"
+#include "net/instaweb/util/public/thread_system.h"
+
+namespace net_instaweb {
+
+class PthreadThreadImpl : public ThreadSystem::ThreadImpl {
+ public:
+  PthreadThreadImpl(PthreadThreadSystem* thread_system,
+                    ThreadSystem::Thread* wrapper,
+                    ThreadSystem::ThreadFlags flags)
+      : thread_system_(thread_system),
+        wrapper_(wrapper),
+        flags_(flags) {
+  }
+
+  virtual ~PthreadThreadImpl() {
+  }
+
+  virtual bool StartImpl() {
+    int result;
+
+    pthread_attr_t attr;
+    result = pthread_attr_init(&attr);
+    if (result != 0) {
+      return false;
+    }
+
+    int mode = PTHREAD_CREATE_DETACHED;
+    if ((flags_ & ThreadSystem::kJoinable) != 0) {
+      mode = PTHREAD_CREATE_JOINABLE;
+    }
+
+    result = pthread_attr_setdetachstate(&attr, mode);
+    if (result != 0) {
+      return false;
+    }
+
+    result = pthread_create(&thread_obj_, &attr, InvokeRun, this);
+    if (result != 0) {
+      return false;
+    }
+
+    pthread_attr_destroy(&attr);
+    return true;
+  }
+
+  virtual void JoinImpl() {
+    void* ignored;
+    pthread_join(thread_obj_, &ignored);
+  }
+
+ private:
+  static void* InvokeRun(void* self_ptr) {
+    PthreadThreadImpl* self = static_cast<PthreadThreadImpl*>(self_ptr);
+    self->thread_system_->BeforeThreadRunHook();
+    self->wrapper_->Run();
+    return NULL;
+  }
+
+  PthreadThreadSystem* thread_system_;
+  ThreadSystem::Thread* wrapper_;
+  ThreadSystem::ThreadFlags flags_;
+  pthread_t thread_obj_;
+
+  DISALLOW_COPY_AND_ASSIGN(PthreadThreadImpl);
+};
+
+PthreadThreadSystem::PthreadThreadSystem() {
+}
+
+PthreadThreadSystem::~PthreadThreadSystem() {
+}
+
+ThreadSystem::CondvarCapableMutex* PthreadThreadSystem::NewMutex() {
+  return new PthreadMutex;
+}
+
+ThreadSystem::RWLock* PthreadThreadSystem::NewRWLock() {
+  return new PthreadRWLock;
+}
+
+void PthreadThreadSystem::BeforeThreadRunHook() {
+}
+
+ThreadSystem::ThreadImpl* PthreadThreadSystem::NewThreadImpl(
+    ThreadSystem::Thread* wrapper, ThreadSystem::ThreadFlags flags) {
+  return new PthreadThreadImpl(this, wrapper, flags);
+}
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/pthread_thread_system_test.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/pthread_thread_system_test.cc?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/pthread_thread_system_test.cc (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/pthread_thread_system_test.cc Thu May  1 11:43:36 2014
@@ -0,0 +1,30 @@
+// Copyright 2011 Google Inc.
+//
+// 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: morlovich@google.com (Maksim Orlovich)
+
+#include "net/instaweb/util/thread_system_test_base.h"
+#include "net/instaweb/util/public/pthread_thread_system.h"
+#include "net/instaweb/util/public/gtest.h"
+
+namespace net_instaweb {
+
+namespace {
+
+INSTANTIATE_TYPED_TEST_CASE_P(PthreadThread, ThreadSystemTestTemplate,
+                              PthreadThreadSystem);
+
+}  // namespace
+
+}  // namespace net_instaweb

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/abstract_mutex.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/abstract_mutex.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/abstract_mutex.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/abstract_mutex.h Thu May  1 11:43:36 2014
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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: jmarantz@google.com (Joshua Marantz)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_ABSTRACT_MUTEX_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_ABSTRACT_MUTEX_H_
+
+#include "net/instaweb/util/public/basictypes.h"
+
+namespace net_instaweb {
+
+// Abstract interface for implementing a mutex.
+class AbstractMutex {
+ public:
+  virtual ~AbstractMutex();
+  virtual void Lock() = 0;
+  virtual void Unlock() = 0;
+  // Optionally checks that lock is held (for invariant checking purposes).
+  // Default implementation does no checking.
+  virtual void DCheckLocked();
+};
+
+// Helper class for lexically scoped mutexing.
+class ScopedMutex {
+ public:
+  explicit ScopedMutex(AbstractMutex* mutex) : mutex_(mutex) {
+    mutex_->Lock();
+  }
+
+  void Release() {
+    if (mutex_ != NULL) {
+      mutex_->Unlock();
+      mutex_ = NULL;
+    }
+  }
+
+  ~ScopedMutex() {
+    Release();
+  }
+
+ private:
+  AbstractMutex* mutex_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedMutex);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_ABSTRACT_MUTEX_H_

Propchange: httpd/mod_spdy/trunk/net/instaweb/util/public/abstract_mutex.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/abstract_shared_mem.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/abstract_shared_mem.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/abstract_shared_mem.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/abstract_shared_mem.h Thu May  1 11:43:36 2014
@@ -0,0 +1,120 @@
+// Copyright 2011 Google Inc.
+//
+// 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: morlovich@google.com (Maksim Orlovich)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_ABSTRACT_SHARED_MEM_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_ABSTRACT_SHARED_MEM_H_
+
+#include <cstddef>
+#include "net/instaweb/util/public/abstract_mutex.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/string.h"
+
+namespace net_instaweb {
+
+class MessageHandler;
+
+// This represents a region of memory shared between between multiple processes
+// that may contain mutexes.
+class AbstractSharedMemSegment {
+ public:
+  AbstractSharedMemSegment() {}
+
+  // Destroying the segment object detaches from it, making all pointers into it
+  // invalid.
+  virtual ~AbstractSharedMemSegment();
+
+  // Returns the base address of the segment. Note that there is no guarantee
+  // that this address will be the same for other processes attached to the
+  // same segment.
+  virtual volatile char* Base() = 0;
+
+  // This returns the number of bytes a mutex inside shared memory
+  // takes.
+  virtual size_t SharedMutexSize() const = 0;
+
+  // To use a mutex in shared memory, you first need to dedicate some
+  // [offset, offset + SharedMutexSize()) chunk of memory to it. Then,
+  // exactly one process must call InitializeSharedMutex(offset), and
+  // all users must call AttachToSharedMutex(offset) afterwards.
+  //
+  // InitializeSharedMutex returns whether it succeeded or not.
+  // AttachToSharedMutex returns a fresh object, giving ownership
+  // to the caller. The object returned is outside shared memory,
+  // and acts a helper for referring to the shared state.
+  virtual bool InitializeSharedMutex(size_t offset,
+                                     MessageHandler* handler) = 0;
+  virtual AbstractMutex* AttachToSharedMutex(size_t offset) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AbstractSharedMemSegment);
+};
+
+// Interface for creating and attaching to named shared memory segments.
+// The expectation is that whichever implementation is used at runtime
+// will be able to handle the combination of threads & processes used by
+// the hosting environment.
+//
+// The basic flow here is as follows:
+//
+//            Single process/thread startup stage:
+//            CreateSegment
+//            InitializeSharedMutex -----+
+//           /                           |
+//          /                            |
+//    process/thread:                   process/thread:
+//    AttachToSegment                   AttachToSegment
+//    AttachToSharedMutex               AttachToSharedMutex
+//       |                                     |
+//       |                                     |
+//       |------------------------------------/
+//       |
+//    single process/thread cleanup stage:
+//    DestroySegment
+//
+class AbstractSharedMem {
+ public:
+  AbstractSharedMem() {}
+  virtual ~AbstractSharedMem();
+
+  // Size of mutexes inside shared memory segments.
+  virtual size_t SharedMutexSize() const = 0;
+
+  // This should be called upon main process/thread initialization to create
+  // a shared memory segment that will be accessed by other processes/threads
+  // as identified by a unique name (via AttachToSegment). It will remove
+  // any previous segment with the same name. The memory will be zeroed out.
+  //
+  // May return NULL on failure.
+  virtual AbstractSharedMemSegment* CreateSegment(
+      const GoogleString& name, size_t size, MessageHandler* handler) = 0;
+
+  // Attaches to an existing segment, which must have been created already.
+  // May return NULL on failure
+  virtual AbstractSharedMemSegment* AttachToSegment(
+      const GoogleString& name, size_t size, MessageHandler* handler) = 0;
+
+  // Cleans up the segment with given name. You should call this after there is
+  // no longer any need for AttachToSegment to succeed.
+  virtual void DestroySegment(const GoogleString& name,
+                              MessageHandler* handler) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AbstractSharedMem);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_ABSTRACT_SHARED_MEM_H_

Propchange: httpd/mod_spdy/trunk/net/instaweb/util/public/abstract_shared_mem.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/arena.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/arena.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/arena.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/arena.h Thu May  1 11:43:36 2014
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * 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: morlovich@google.com (Maksim Orlovich)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_ARENA_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_ARENA_H_
+
+#include <vector>
+#include <cstddef>
+
+#include "base/logging.h"
+#include "net/instaweb/util/public/basictypes.h"
+
+namespace net_instaweb {
+
+// This template keeps a packed set of objects inheriting from the same base
+// type (which must have a virtual destructor) where all of the
+// objects in the same arena are expected to be destroyed at once.
+template<typename T>
+class Arena {
+ public:
+  // All allocations we make will be aligned to this. We will also reserve
+  // this much room for our work area, as it keeps things simple.
+  static const size_t kAlign = 8;
+
+  Arena() {
+    InitEmpty();
+  }
+
+  ~Arena() {
+    CHECK(chunks_.empty());
+  }
+
+  void* Allocate(size_t size) {
+    size += kAlign;  // Need room to link the next object.
+    size = ExpandToAlign(size);
+
+    DCHECK(sizeof(void*) <= kAlign);
+    DCHECK(size < Chunk::kSize);
+
+    if (next_alloc_ + size > chunk_end_) {
+      AddChunk();
+    }
+
+    char* base = next_alloc_;
+
+    // Update the links -- the previous object should point to our
+    // chunk's base, our base should point to NULL, and last_link_
+    // should point to our base
+    char** our_last_link_field = reinterpret_cast<char**>(base);
+    *last_link_ = base;
+    *our_last_link_field = NULL;
+    last_link_ = our_last_link_field;
+
+    next_alloc_ += size;
+
+    char* out = base + kAlign;
+    DCHECK((reinterpret_cast<uintptr_t>(out) & (kAlign - 1)) == 0);
+    return out;
+  }
+
+  // Cleans up all the objects in the arena. You must call this explicitly.
+  void DestroyObjects();
+
+  // Rounds block size up to 8; we always align to it, even on 32-bit.
+  static size_t ExpandToAlign(size_t in) {
+    return (in + kAlign - 1) & ~(kAlign - 1);
+  }
+
+ private:
+  struct Chunk {
+    // Representation: the arena is a vector of fixed-size (kSize, 8k) chunks;
+    // we allocate objects from the end of the most recently created chunk until
+    // an allocation doesn't fit (in which case we make a fresh chunk)
+    //
+    // Each chunk is independently organized into a singly-linked list, where
+    // we precede each object with a pointer to the next allocated block, e.g.:
+    //
+    //                  /-----------------|
+    //                  |                \|/
+    // -----------------|---------------|----|-----------|
+    // |   | object 1 | | | object 2    | NU | object 3  |
+    // | | |          |   |             | LL |           |
+    // |_|_|----------|---|-------------|----|-----------|
+    //   |              ^
+    //   \--------------/
+    // We need this because objects may have different sizes, and we'll need
+    // to find everyone to call their destructor
+    static const size_t kSize = 8192;
+    char buf[kSize];
+  };
+
+  // Adds in a new chunk and initializes all the fields below to refer to it
+  void AddChunk();
+
+  // Sets up all the pointers below to denote us being empty.
+  void InitEmpty();
+
+  // First free byte of the current chunk
+  char* next_alloc_;
+
+  // The point where to link in a new object we allocate.
+  // We need this so that the last object in a chunk has
+  // a null 'next' link.
+  char** last_link_;
+
+  // First address after the last byte of the currently active chunk
+  char* chunk_end_;
+
+  // Scratch location in case we want a write to go nowhere.
+  // Does not point anywhere, just bitbuckets writes
+  char* scratch_;
+
+  std::vector<Chunk*> chunks_;
+};
+
+template<typename T>
+void Arena<T>::AddChunk() {
+  Chunk* chunk = new Chunk();
+  chunks_.push_back(chunk);
+  next_alloc_ = chunk->buf;
+  chunk_end_ = next_alloc_ + Chunk::kSize;
+  last_link_ = &scratch_;
+}
+
+template<typename T>
+void Arena<T>::DestroyObjects() {
+  for (int i = 0; i < static_cast<int>(chunks_.size()); ++i) {
+    // Walk through objects in this chunk.
+    char* base = chunks_[i]->buf;
+    while (base != NULL) {
+      reinterpret_cast<T*>(base + kAlign)->~T();
+      base = *reinterpret_cast<char**>(base);
+    }
+    delete chunks_[i];
+  }
+  chunks_.clear();
+  InitEmpty();
+}
+
+template<typename T>
+void Arena<T>::InitEmpty() {
+  // The way this is initialized ensures that the next call to allocate
+  // will call AddChunk(). Doing it this way rather than calling NewChunk()
+  // from here establishes the invariant that all the chunks are non-empty,
+  // which helps in DestroyObjects()
+  next_alloc_ = NULL;
+  last_link_ = NULL;
+  chunk_end_ = NULL;
+}
+
+}  // namespace  net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_ARENA_H_

Propchange: httpd/mod_spdy/trunk/net/instaweb/util/public/arena.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/atom.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/atom.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/atom.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/atom.h Thu May  1 11:43:36 2014
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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: jmarantz@google.com (Joshua Marantz)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_ATOM_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_ATOM_H_
+
+#include <set>
+#include "net/instaweb/util/public/string.h"
+
+namespace net_instaweb {
+
+struct CaseFold;
+struct CasePreserve;
+template<class CharTransform> class SymbolTable;
+
+// Atoms are idempotent representations of strings, created
+// via a symbol table.
+class Atom {
+ public:
+  Atom(const Atom& src) : str_(src.str_) {}
+  Atom();
+  ~Atom() {}  // atoms are memory-managed by SymbolTables.
+
+  Atom& operator=(const Atom& src) {
+    if (&src != this) {
+      str_ = src.str_;
+    }
+    return *this;
+  }
+
+  // string-like accessors.
+  const char* c_str() const { return str_; }
+  int size() const { return strlen(str_); }
+
+  // This is comparing the underlying char* pointers.  It is invalid
+  // to compare Atoms from different symbol tables.
+  bool operator==(const Atom& sym) const {
+    return str_ == sym.str_;
+  }
+
+  // This is comparing the underlying char* pointers.  It is invalid
+  // to compare Atoms from different symbol tables.
+  bool operator!=(const Atom& sym) const {
+    return str_ != sym.str_;
+  }
+
+  // SymbolTable is a friend of Symbol because SymbolTable is the
+  // only class that has the right to construct a new Atom from
+  // a char*.
+  friend class SymbolTable<CaseFold>;
+  friend class SymbolTable<CasePreserve>;
+
+ private:
+  explicit Atom(const char* str) : str_(str) {}
+  const char* str_;
+};
+
+// Once interned, Atoms are very cheap to put in a set, using
+// pointer-comparison.
+struct AtomCompare {
+  bool operator()(const Atom& a1, const Atom& a2) const {
+    return a1.c_str() < a2.c_str();   // compares pointers
+  }
+};
+
+// A set of atoms can be constructed very efficiently.  Note that
+// iteration over this set will *not* be in alphabetical order.
+typedef std::set<Atom, AtomCompare> AtomSet;
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_ATOM_H_

Propchange: httpd/mod_spdy/trunk/net/instaweb/util/public/atom.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/atomic_bool.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/atomic_bool.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/atomic_bool.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/atomic_bool.h Thu May  1 11:43:36 2014
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * 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: morlovich@google.com (Maksim Orlovich)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_ATOMIC_BOOL_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_ATOMIC_BOOL_H_
+
+#include "net/instaweb/util/public/atomicops.h"
+#include "net/instaweb/util/public/basictypes.h"
+
+namespace net_instaweb {
+
+// A boolean flag that can be set atomically and be visible to other
+// threads. Please be extra careful with this --- it can go wrong in
+// incomprehensible  ways; most of the time, you probably want to use a mutex
+// instead.
+class AtomicBool {
+ public:
+  // Guaranteed to be initialized to false.
+  AtomicBool() {
+    set_value(false);
+  }
+
+  ~AtomicBool() {}
+
+  bool value() const {
+    return base::subtle::Acquire_Load(&value_);
+  }
+
+  void set_value(bool v) {
+    base::subtle::Release_Store(&value_, v);
+  }
+
+ private:
+  base::subtle::AtomicWord value_;
+  DISALLOW_COPY_AND_ASSIGN(AtomicBool);
+};
+
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_ATOMIC_BOOL_H_

Propchange: httpd/mod_spdy/trunk/net/instaweb/util/public/atomic_bool.h
------------------------------------------------------------------------------
    svn:eol-style = native