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 [23/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/public/pthread_shared_mem.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/pthread_shared_mem.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/pthread_shared_mem.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/pthread_shared_mem.h Thu May  1 11:43:36 2014
@@ -0,0 +1,71 @@
+// 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_PTHREAD_SHARED_MEM_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_PTHREAD_SHARED_MEM_H_
+
+#include <cstddef>
+#include <map>
+
+#include "net/instaweb/util/public/abstract_shared_mem.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/string.h"
+
+namespace net_instaweb {
+class MessageHandler;
+
+// POSIX shared memory support, using mmap/pthread_mutexattr_setpshared
+// Supports both processes and threads, but processes that want to access it
+// must be results of just fork (without exec), and all the CreateSegment
+// calls must occur before the fork.
+//
+// This implementation is also not capable of deallocating segments except
+// at exit, so it should not be used when the set of segments may be dynamic.
+class PthreadSharedMem : public AbstractSharedMem {
+ public:
+  PthreadSharedMem();
+  virtual ~PthreadSharedMem();
+
+  virtual size_t SharedMutexSize() const;
+
+  virtual AbstractSharedMemSegment* CreateSegment(
+      const GoogleString& name, size_t size, MessageHandler* handler);
+
+  virtual AbstractSharedMemSegment* AttachToSegment(
+      const GoogleString& name, size_t size, MessageHandler* handler);
+
+  virtual void DestroySegment(const GoogleString& name,
+                              MessageHandler* handler);
+
+ private:
+  typedef std::map<GoogleString, char*> SegmentBaseMap;
+
+  // Accessor for below. Note that the segment_bases_lock will be held at exit.
+  static SegmentBaseMap* AcquireSegmentBases();
+
+  static void UnlockSegmentBases();
+
+  // The root process stores segment locations here. Child processes will
+  // inherit a readonly copy of this map after the fork. Note that this is
+  // initialized in a thread-unsafe manner, given the above assumptions.
+  static SegmentBaseMap* segment_bases_;
+
+  DISALLOW_COPY_AND_ASSIGN(PthreadSharedMem);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_PTHREAD_SHARED_MEM_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/pthread_thread_system.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/pthread_thread_system.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/pthread_thread_system.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/pthread_thread_system.h Thu May  1 11:43:36 2014
@@ -0,0 +1,53 @@
+/*
+ * 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)
+//
+// Implementation of thread-creation for pthreads
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_PTHREAD_THREAD_SYSTEM_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_PTHREAD_THREAD_SYSTEM_H_
+
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/thread_system.h"
+
+namespace net_instaweb {
+
+class PthreadThreadSystem : public ThreadSystem {
+ public:
+  PthreadThreadSystem();
+  virtual ~PthreadThreadSystem();
+
+  virtual CondvarCapableMutex* NewMutex();
+
+  virtual RWLock* NewRWLock();
+
+ protected:
+  // This hook will get invoked by the implementation in the context of a
+  // thread before invoking its Run() method.
+  virtual void BeforeThreadRunHook();
+
+ private:
+  friend class PthreadThreadImpl;
+
+  virtual ThreadImpl* NewThreadImpl(Thread* wrapper, ThreadFlags flags);
+
+  DISALLOW_COPY_AND_ASSIGN(PthreadThreadSystem);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_PTHREAD_THREAD_SYSTEM_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/query_params.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/query_params.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/query_params.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/query_params.h Thu May  1 11:43:36 2014
@@ -0,0 +1,51 @@
+// Copyright 2010-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)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_QUERY_PARAMS_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_QUERY_PARAMS_H_
+
+#include "net/instaweb/util/public/string_multi_map.h"
+
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_util.h"
+
+namespace net_instaweb {
+
+// Parses and rewrites URL query parameters.
+class QueryParams : public StringMultiMapSensitive {
+ public:
+  QueryParams() { }
+
+  // Parse a query param string, e.g. x=0&y=1&z=2.  We expect the "?"
+  // to be extracted (e.g. this string is the output of GURL::query().
+  //
+  // Note that the value can be NULL, indicating that the variables
+  // was not followed by a '='.  So given "a=0&b&c=", the values will
+  // be {"0", NULL, ""}.
+  void Parse(const StringPiece& query_string);
+
+  GoogleString ToString() const;
+
+  int size() const { return num_values(); }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(QueryParams);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_QUERY_PARAMS_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/queued_alarm.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/queued_alarm.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/queued_alarm.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/queued_alarm.h Thu May  1 11:43:36 2014
@@ -0,0 +1,86 @@
+// 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_QUEUED_ALARM_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_QUEUED_ALARM_H_
+
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/function.h"
+#include "net/instaweb/util/public/queued_worker_pool.h"
+#include "net/instaweb/util/public/scheduler.h"
+
+namespace net_instaweb {
+
+class AbstractMutex;
+
+// A helper for managing alarms that need to both run in a sequence and be
+// cancellable (in the CancelAlarm sense) safely; note that
+// QueuedWorkerPool::Sequence::AddFunction does not provide alarm awareness.
+class QueuedAlarm : public Function {
+ public:
+  // Schedules a function to run at a given time in a given sequence.
+  // (Note that the function's invocation may be delayed by other work
+  //  present in the sequence at time of alarm going off).
+  //
+  // This constructor must be invoked from that sequence as well.
+  //
+  // The object will be destroyed automatically when either the callback
+  // is invoked or the cancellation is complete. You should not free the
+  // sequence until one of these points is reached.
+  QueuedAlarm(Scheduler* scheduler,
+              QueuedWorkerPool::Sequence* sequence,
+              int64 wakeup_time_us,
+              Function* callback);
+
+  // Cancels the alarm. This method must be run from the sequence given to the
+  // constructor; and should not be called when the callback has already been
+  // invoked. It is suggested that as both invocations of CancelAlarm and
+  // the callback are deallocation points that you defensively clear any
+  // pointers to the QueuedAlarm object when they occur.
+  //
+  // The function's Cancel method will be invoked; but no guarantee is made
+  // as to when or in what thread context. The class does guarantee, however,
+  // that it will not access the sequence_ once CancelAlarm() completes.
+  void CancelAlarm();
+
+ private:
+  virtual ~QueuedAlarm();
+
+  // Runs in an arbitrary thread.
+  virtual void Run();
+
+  // Runs in the sequence case.
+  void SequencePortionOfRun();
+
+  // This can get invoked if our client freed the sequence upon calling
+  // CancelAlarm, in the case where what normally would be SequencePortionOfRun
+  // is already on the queue.
+  void SequencePortionOfRunCancelled();
+
+  scoped_ptr<AbstractMutex> mutex_;
+  Scheduler* scheduler_;
+  QueuedWorkerPool::Sequence* sequence_;
+  Function* callback_;
+  Scheduler::Alarm* alarm_;
+
+  bool canceled_;
+  bool queued_sequence_portion_;
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_QUEUED_ALARM_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/queued_worker.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/queued_worker.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/queued_worker.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/queued_worker.h Thu May  1 11:43:36 2014
@@ -0,0 +1,63 @@
+/*
+ * 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)
+//
+// This contains QueuedWorker, which runs tasks in a background thread
+// in FIFO order.
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_QUEUED_WORKER_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_QUEUED_WORKER_H_
+
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/thread_system.h"
+#include "net/instaweb/util/public/worker.h"
+
+namespace net_instaweb {
+
+class Function;
+
+// See file comment.
+class QueuedWorker : public Worker {
+ public:
+  // Initializes the worker. You still need to call ->Start to actually
+  // start the thread, however. (Note: start can return false on failure).
+  explicit QueuedWorker(ThreadSystem* runtime);
+
+  // This waits for the running task to terminate.
+  virtual ~QueuedWorker();
+
+  // Runs the given closure in the work thread. Not that it's possible for the
+  // closure to be deleted without running in case where the system is shutting
+  // down.
+  //
+  // Takes ownership of the closure.
+  void RunInWorkThread(Function* closure);
+
+  // Issue a TimedWait on the specified condition variable.  In a mock-time
+  // world, this queues a time-advancement closure on the worker, and then
+  // blocks waiting for the work-queue to be drained.
+  void TimedWait(ThreadSystem::Condvar* condvar, int64 timeout_ms);
+
+ private:
+  virtual bool IsPermitted(Function* closure);
+
+  DISALLOW_COPY_AND_ASSIGN(QueuedWorker);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_QUEUED_WORKER_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/queued_worker_pool.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/queued_worker_pool.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/queued_worker_pool.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/queued_worker_pool.h Thu May  1 11:43:36 2014
@@ -0,0 +1,206 @@
+/*
+ * 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)
+//
+// implements a simple worker pool, allowing arbitrary functions to run
+// using a pool of threads of predefined maximum size.
+//
+// This differs from QueuedWorker, which always uses exactly one thread.
+// In this interface, any task can be assigned to any thread.
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_QUEUED_WORKER_POOL_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_QUEUED_WORKER_POOL_H_
+
+#include <cstddef>  // for size_t
+#include <deque>
+#include <set>
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/function.h"
+#include "net/instaweb/util/public/thread_system.h"
+
+namespace net_instaweb {
+
+class AbstractMutex;
+class QueuedWorker;
+class Waveform;
+
+// Maintains a predefined number of worker threads, and dispatches any
+// number of groups of sequential tasks to those threads.
+class QueuedWorkerPool {
+ public:
+  QueuedWorkerPool(int max_workers, ThreadSystem* thread_system);
+  ~QueuedWorkerPool();
+
+  // Functions added to a Sequence will be run sequentially, though not
+  // necessarily always from the same worker thread.  The scheduler will
+  // continue to schedule new work added to the sequence until
+  // FreeSequence is called.
+  class Sequence {
+   public:
+    // AddFunction is a callback that when invoked queues another callback on
+    // the given sequence, and when canceled queues a cancel call to the
+    // sequence instead.  The cancellation behavior is what makes this different
+    // from a simple call to MakeFunction(sequence, &Sequence::Add, callback).
+    class AddFunction : public Function {
+     public:
+      AddFunction(Sequence* sequence, Function* callback)
+          : sequence_(sequence), callback_(callback) { }
+      virtual ~AddFunction();
+
+     protected:
+      virtual void Run() {
+        sequence_->Add(callback_);
+      }
+      virtual void Cancel() {
+        sequence_->Add(MakeFunction(callback_, &Function::CallCancel));
+      }
+
+     private:
+      Sequence* sequence_;
+      Function* callback_;
+      DISALLOW_COPY_AND_ASSIGN(AddFunction);
+    };
+
+    // Adds 'function' to a sequence.  Note that this can occur at any time
+    // the sequence is live -- you can add functions to a sequence that has
+    // already started processing.
+    //
+    // 'function' can be called any time after Add(), and may in fact be
+    // called before Add() returns.
+    //
+    // Ownership of 'function' is transferred to the Sequence, which deletes
+    // it after execution or upon cancellation due to shutdown.
+    void Add(Function* function);
+
+    void set_queue_size_stat(Waveform* x) { queue_size_ = x; }
+
+   private:
+    // Construct using QueuedWorkerPool::NewSequence().
+    Sequence(ThreadSystem* thread_system, QueuedWorkerPool* pool);
+
+    // Free by calling QueuedWorkerPool::FreeSequence().
+    ~Sequence();
+
+    // Resets a new or recycled Sequence to its original state.
+    void Reset();
+
+    // Waits for any currently active function to complete, deletes
+    // any other outstanding functions.  During the shutdown process,
+    // the Sequence will simply delete, without running, any function
+    // added to it from another thread.
+    //
+    // This function blocks until shutdown is complete.
+    void WaitForShutDown();
+
+    // Puts the Sequence in shutdown mode, but does not block until shutdown
+    // is complete.  Return 'true' if the sequence is inactive and thus can
+    // be immediately recycled.
+    bool InitiateShutDown();
+
+    // Gets the next function in the sequence, and transfers ownership
+    // the the caller.
+    Function* NextFunction();
+
+    // Assumes sequence_mutex_ held
+    bool IsBusy();
+
+    // Assumes sequence_mutex_ held. Returns number of tasks that were canceled.
+    int CancelTasksOnWorkQueue();
+
+    friend class QueuedWorkerPool;
+    std::deque<Function*> work_queue_;
+    scoped_ptr<ThreadSystem::CondvarCapableMutex> sequence_mutex_;
+    QueuedWorkerPool* pool_;
+    bool shutdown_;
+    bool active_;
+    scoped_ptr<ThreadSystem::Condvar> termination_condvar_;
+    Waveform* queue_size_;
+
+    DISALLOW_COPY_AND_ASSIGN(Sequence);
+  };
+
+  typedef std::set<Sequence*> SequenceSet;
+
+  // Sequence is owned by the pool, and will be automatically freed when
+  // the pool is finally freed (e.g. on server shutdown).  But the sequence
+  // does *not* auto-destruct when complete; it must be explicitly freed
+  // using FreeSequence().
+  Sequence* NewSequence();  // Returns NULL if shutting down.
+
+  // Shuts down a sequence and frees it.  This does *not* block waiting
+  // for the Sequence to finish.
+  void FreeSequence(Sequence* sequence);
+
+  // Shuts down all Sequences and Worker threads, but does not delete the
+  // sequences.  The sequences will be deleted when the pool is destructed.
+  void ShutDown();
+
+  // Returns true if any of the given sequences is busy. Note that multiple
+  // sequences are checked atomically; otherwise we could end up missing
+  // work. For example, consider if we had a sequence for main rewrite work,
+  // and an another one for expensive work.
+  // In this case, if we tried to check their busyness independently, the
+  // following could happen:
+  // 1) First portion of inexpensive work is done, so we queue up
+  //    some on expensive work thread.
+  // 2) We check whether inexpensive work sequence is busy. It's not.
+  // 3) The expensive work runs, finishes, and queues up more inexpensive
+  //    work.
+  // 4) We check whether expensive sequence is busy. It's not, so we would
+  //    conclude we quiesced --- while there was still work in the inexpensive
+  //    queue.
+  static bool AreBusy(const SequenceSet& sequences);
+
+  // Sets up a timed-variable statistic indicating the current queue depth.
+  //
+  // This must be called prior to creating sequences.
+  void set_queue_size_stat(Waveform* x) { queue_size_ = x; }
+
+ private:
+  friend class Sequence;
+  void Run(Sequence* sequence, QueuedWorker* worker);
+  void QueueSequence(Sequence* sequence);
+  Sequence* AssignWorkerToNextSequence(QueuedWorker* worker);
+  void SequenceNoLongerActive(Sequence* sequence);
+
+  ThreadSystem* thread_system_;
+  scoped_ptr<AbstractMutex> mutex_;
+
+  // active_workers_ and available_workers_ are mutually exclusive.
+  std::set<QueuedWorker*> active_workers_;
+  std::vector<QueuedWorker*> available_workers_;
+
+  // queued_sequences_ and free_sequences_ are mutually exclusive, but
+  // all_sequences contains all of them.
+  std::vector<Sequence*> all_sequences_;
+  std::deque<Sequence*> queued_sequences_;
+  std::vector<Sequence*> free_sequences_;
+
+  size_t max_workers_;
+  bool shutdown_;
+
+  Waveform* queue_size_;
+
+  DISALLOW_COPY_AND_ASSIGN(QueuedWorkerPool);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_QUEUED_WORKER_POOL_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/ref_counted_owner.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/ref_counted_owner.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/ref_counted_owner.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/ref_counted_owner.h Thu May  1 11:43:36 2014
@@ -0,0 +1,131 @@
+/*
+ * 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)
+//
+// A RefCountedOwner<T> helps a family of objects manage lifetime of a single
+// shared T, initializing it with the first owner, and getting rid of it
+// when all the owners are gone. This is different from a singleton in that
+// there is no limit to having only a single instance of T, but rather
+// a single T instance per a single RefCountedOwner<T>::Family instance.
+//
+// Warning: this class doesn't provide for full thread safety; as it assumes
+// that all the owners will be created and destroyed in a single thread.
+// The accessors, however, are readonly, so can be used from multiple threads
+// if their use follows the sequential initialization and precedes object
+// destruction.
+//
+// Typical usage:
+//  class OwnerClass {
+//     static RefCountedOwner<SharedClass>::Family shared_family_;
+//     RefCountedOwner<SharedClass> shared_;
+//  };
+//
+//  OwnerClass::OwnerClass() : shared_(&shared_family_) {
+//    if (shared_.ShouldInitialize()) {
+//      shared_->Initialize(new SharedClass(...));
+//    }
+//  }
+//
+
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_REF_COUNTED_OWNER_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_REF_COUNTED_OWNER_H_
+
+#include "base/logging.h"
+#include "net/instaweb/util/public/basictypes.h"
+
+// See file comment.
+template<typename T>
+class RefCountedOwner {
+ public:
+  class Family {
+   public:
+    Family() : ptr_(NULL), ref_count_(0) {}
+
+   private:
+    friend class RefCountedOwner<T>;
+    T* ptr_;
+    int ref_count_;
+    DISALLOW_COPY_AND_ASSIGN(Family);
+  };
+
+  // Instances of RefCountedOwner that share the same 'family' object will
+  // share an instance of T.
+  explicit RefCountedOwner(Family* family)
+      : family_(family),
+        attached_(false) {}
+
+  ~RefCountedOwner() {
+    if (attached_) {
+      --family_->ref_count_;
+      if (family_->ref_count_ == 0) {
+        delete family_->ptr_;
+        family_->ptr_ = NULL;
+      }
+    }
+  }
+
+  // If an another member of the family has already created the managed
+  // object, Attach() will return true and attach 'this' to it, making the
+  // object accessible via get() and pointer operations.
+  //
+  // Otherwise, it returns false, and you should call Initialize() to
+  // set the object.
+  bool Attach() {
+    if (attached_) {
+      return true;  // we are already attached, no need to initialize.
+    } else if (family_->ref_count_ != 0) {
+      // Someone already made an instance
+      attached_ = true;
+      ++family_->ref_count_;
+      return true;
+    } else {
+      // If need to create it.
+      return false;
+    }
+  }
+
+  // Sets the value of the object our family will share. Pre-condition:
+  // one must not have been set already (in other words, this must only be
+  // called if Attach() returned false).
+  void Initialize(T* value) {
+    CHECK(!attached_ && family_->ref_count_ == 0);
+    attached_ = true;
+    family_->ref_count_ = 1;
+    family_->ptr_ = value;
+  }
+
+  // Note that you must call Attach() (and Initialize() if it
+  // returned false) before using these.
+  T* Get() {
+    DCHECK(attached_);
+    return family_->ptr_;
+  }
+
+  const T* Get() const {
+    DCHECK(attached_);
+    return family_->ptr_;
+  }
+
+ private:
+  friend class Family;
+  Family* family_;
+  bool attached_;  // whether we've grabbed a reference to the data.
+  DISALLOW_COPY_AND_ASSIGN(RefCountedOwner);
+};
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_REF_COUNTED_OWNER_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/ref_counted_ptr.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/ref_counted_ptr.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/ref_counted_ptr.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/ref_counted_ptr.h Thu May  1 11:43:36 2014
@@ -0,0 +1,142 @@
+/*
+ * 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)
+//
+// Implements a generic ref-counted class, with full sharing.  This
+// class does *not* implement copy-on-write semantics, but it provides
+// 'unique()', which helps implement COW at a higher level.
+//
+// There are two pointer templates here:
+// - RefCountedPtr<T> --- requires T to inherit off RefCounted<T>,
+//   stores it by pointer to supports full polymorphism.
+// - RefCountedObj<T> --- no requirements on T besides default and copy
+//   construction, but stores T by value so it must always store exactly T.
+//
+// TODO(jmaessen): explore adding C++x0 shared_ptr support
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_REF_COUNTED_PTR_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_REF_COUNTED_PTR_H_
+
+#include "net/instaweb/util/public/basictypes.h"
+
+#include "base/memory/ref_counted.h"
+
+namespace net_instaweb {
+
+
+template<class T>
+class RefCounted : public base::RefCountedThreadSafe<T> {
+};
+
+// Template class to help make reference-counted pointers.  You can use
+// a typedef or subclass RefCountedPtr<YourClass>.  YourClass has to inherit
+// off RefCounted<T>.
+template<class T>
+class RefCountedPtr : public scoped_refptr<T> {
+ public:
+  RefCountedPtr() : scoped_refptr<T>(NULL) {}
+  explicit RefCountedPtr(T* t) : scoped_refptr<T>(t) {}
+
+  template<class U>
+  explicit RefCountedPtr(const RefCountedPtr<U>& src)
+      : scoped_refptr<T>(src) {
+  }
+
+  // Determines whether any other RefCountedPtr objects share the same
+  // storage.  This can be used to create copy-on-write semantics if
+  // desired.
+  bool unique() const { return !this->ptr_ || this->ptr_->HasOneRef(); }
+
+  void clear() {
+    *this = RefCountedPtr();
+  }
+  void reset(T* ptr) {
+    *this = RefCountedPtr(ptr);
+  }
+  void reset(const RefCountedPtr& src) {
+    *this = src;
+  }
+
+ private:
+  operator void*() const;  // don't compare directly to NULL; use get()
+  operator T*() const;     // don't assign directly to pointer; use get()
+
+  // Note that copy and assign of RefCountedPtr is allowed -- that
+  // is how the reference counts are updated.
+};
+
+// If you can't inherit off RefCounted due to using a pre-existing
+// class, you can use RefCountedObj instead. This however is limited to
+// having a single type (so no polymorphism). It also has slightly
+// different semantics in that it initializes to a default-constructed object
+// and not NULL.
+template<class T>
+class RefCountedObj {
+ public:
+  RefCountedObj() : data_ptr_(new Data()) {}
+  explicit RefCountedObj(const T& val) : data_ptr_(new Data(val)) {}
+
+  // Determines whether any other RefCountedObj objects share the same
+  // storage.  This can be used to create copy-on-write semantics if
+  // desired.
+  bool unique() const { return data_ptr_.unique(); }
+
+  T* get() { return &data_ptr_->value; }
+  const T* get() const { return &data_ptr_->value; }
+  T* operator->() { return &data_ptr_->value; }
+  const T* operator->() const { return &data_ptr_->value; }
+  T& operator*() { return data_ptr_->value; }
+  const T& operator*() const { return data_ptr_->value; }
+
+ protected:
+  struct Data : public RefCounted<Data> {
+    Data() {}
+    explicit Data(const T& val) : value(val) {}
+    T value;
+  };
+
+  RefCountedPtr<Data> data_ptr_;
+
+ private:
+  operator void*() const;  // don't compare directly to NULL; use get()
+  operator T*() const;     // don't assign directly to pointer; use get()
+
+  // Copying, etc., are OK thanks to data_ptr_.
+};
+
+// Helper macro to allow declaration of user-visible macro
+// REFCOUNT_DISALLOW_EXPLICIT_DESTROY which is used to generate
+// compile-time errors for code that deletes ref-counted objects
+// explicitly.
+#define REFCOUNT_SHARED_MEM_IMPL_CLASS base::RefCountedThreadSafe
+
+
+// Macro for users implementing C++ ref-counted classes to prevent
+// explicit destruction.  Once a class is reference counted, it
+// should never be stack-allocated or explicitly deleted.  It should
+// only be deleted by the reference count object.  Put this declaration
+// in the 'protected:' or 'private:' section, and group it with
+// a destructor declaration.
+//
+// This is only required for RefCountedPtr<T>, not RefCountedObj<T>.
+//
+#define REFCOUNT_FRIEND_DECLARATION(class_name) \
+  friend class REFCOUNT_SHARED_MEM_IMPL_CLASS<class_name>
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_REF_COUNTED_PTR_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/rolling_hash.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/rolling_hash.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/rolling_hash.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/rolling_hash.h Thu May  1 11:43:36 2014
@@ -0,0 +1,70 @@
+/*
+ * 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)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_ROLLING_HASH_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_ROLLING_HASH_H_
+
+#include <cstddef>
+#include "base/logging.h"
+#include "net/instaweb/util/public/basictypes.h"
+
+namespace net_instaweb {
+
+// Rolling hash for char buffers based on a polynomial lookup table.
+// See http://en.wikipedia.org/wiki/Rolling_hash
+
+// Per character hash values.  Exported for use in NextRollingHash.
+extern const uint64 kRollingHashCharTable[256];
+
+// Compute the rolling hash of buf[start : start + n - 1]
+uint64 RollingHash(const char* buf, size_t start, size_t n);
+
+// Given the rolling hash prev of buf[start - 1 : start + n - 2], efficiently
+// compute the hash of buf[start : start + n - 1].  Note that this indexes
+// buf[start - 1], so we can't just use a StringPiece here.  We eschew
+// StringPiece in any case, because of efficiency.
+//
+// Note that to get efficient operation here for fixed n (eg when we're doing
+// something like Rabin-Karp string matching), we must inline the computation of
+// shift amounts and then hoist them as loop invariants.  That is why this
+// function (intended for use in an inner loop) is inlined.
+inline uint64 NextRollingHash(
+    const char* buf, size_t start, size_t n, uint64 prev) {
+  // In a reasonable loop, the following two tests should be eliminated based on
+  // contextual information, if our compiler is optimizing enough.
+  CHECK_LT(static_cast<size_t>(0), start);
+  uint64 start_hash =
+      kRollingHashCharTable[static_cast<uint8>(buf[start - 1])];
+  uint64 end_hash =
+      kRollingHashCharTable[static_cast<uint8>(buf[start - 1 + n])];
+  uint64 prev_rot1 = (prev << 1) | (prev >> 63);  // rotate left 1
+  uint64 start_hash_rotn;
+  // Corner case: shift by >= 64 bits is not defined in C.  gcc had better
+  // constant-fold this to a rotate!  (It appears to.)  We inline in large part
+  // to ensure the truthiness of this fact.
+  size_t shift = n % 64;
+  if (shift == 0) {
+    start_hash_rotn = start_hash;
+  } else {
+    // rotate left by shift (equiv to rotating left n times).
+    start_hash_rotn = (start_hash << shift) | (start_hash >> (64 - shift));
+  }
+  return (start_hash_rotn ^ prev_rot1 ^ end_hash);
+}
+}  // net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_ROLLING_HASH_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler.h Thu May  1 11:43:36 2014
@@ -0,0 +1,193 @@
+// 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)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_SCHEDULER_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_SCHEDULER_H_
+
+#include <set>
+
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/atomic_bool.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/function.h"
+#include "net/instaweb/util/public/queued_worker_pool.h"
+#include "net/instaweb/util/public/thread_system.h"
+
+namespace net_instaweb {
+
+class Timer;
+
+// Implements a simple scheduler that allows a thread to block until either time
+// expires, or a condition variable is signaled.  Also permits various alarms to
+// be scheduled; these are lightweight short-lived callbacks that must be safely
+// runnable from any thread in any lock state in which scheduler invocations
+// occur.  Finally, implements a hybrid between these: a callback that can be
+// run when the condition variable is signaled.
+//
+// This class is designed to be overridden, but only to re-implement its
+// internal notion of blocking to permit time to be mocked by MockScheduler.
+class Scheduler {
+ public:
+  // A callback for a scheduler alarm, with an associated wakeup time (absolute
+  // time after which the callback will be invoked with Run() by the scheduler).
+  // Alarm should be treated as an opaque type.
+  class Alarm;
+
+  // Sorting comparator for Alarms, so that they can be retrieved in time
+  // order.  For use by std::set, thus public.
+  struct CompareAlarms {
+    bool operator()(const Alarm* a, const Alarm* b) const;
+  };
+
+  Scheduler(ThreadSystem* thread_system, Timer* timer);
+  virtual ~Scheduler();
+
+  ThreadSystem::CondvarCapableMutex* mutex();
+
+  // Optionally check that mutex is locked for debugging purposes.
+  void DCheckLocked();
+
+  // Condition-style methods: The following three methods provide a simple
+  // condition-variable-style interface that can be used to coordinate the
+  // threads sharing the scheduler.
+
+  // Wait at most timeout_us, or until Signal() is called.  mutex() must be held
+  // when calling BlockingTimedWait.
+  void BlockingTimedWait(int64 timeout_ms);
+
+  // Non-blocking invocation of callback either when Signal() is called, or
+  // after timeout_us have passed.  Ownership of callback passes to the
+  // scheduler, which deallocates it after invocation.  mutex() must be held on
+  // the initial call, and is locked for the duration of callback.  Note that
+  // callback may be invoked in a different thread from the calling thread.
+  void TimedWait(int64 timeout_ms, Function* callback);
+
+  // Signal threads in BlockingTimedWait and invoke TimedWait callbacks.
+  // mutex() must be held when calling Signal.  Performs outstanding work,
+  // including any triggered by the signal, before returning; note that this
+  // means it may drop the scheduler lock internally while doing callback
+  // invocation, which is different from the usual condition variable signal
+  // semantics.
+  void Signal();
+
+  // Alarms.  The following two methods provide a mechanism for scheduling
+  // alarm tasks, each run at a particular time.
+
+  // Schedules an alarm for absolute time wakeup_time_us, using the passed-in
+  // Function* as the alarm callback.  Returns the created Alarm.  Performs
+  // outstanding work.  The returned alarm will own the callback and will clean
+  // itself and the callback when it is run or cancelled.  NOTE in particular
+  // that calls to CancelAlarm must ensure the callback has not been invoked
+  // yet.  This is why the scheduler mutex must be held for CancelAlarm.
+  Alarm* AddAlarm(int64 wakeup_time_us, Function* callback);
+
+  // Cancels an alarm, calling the Cancel() method and deleting the alarm
+  // object.  Scheduler mutex must be held before call to ensure that alarm is
+  // not called back before cancellation occurs.  Doesn't perform outstanding
+  // work.  Returns true if the cancellation occurred.  If false is returned,
+  // the alarm is already being run / has been run in another thread; if the
+  // alarm deletes itself on Cancel(), it may no longer safely be used.
+  bool CancelAlarm(Alarm* alarm);
+
+  // Finally, ProcessAlarms provides a mechanism to ensure that pending alarms
+  // are executed in the absence of other scheduler activity.  ProcessAlarms:
+  // handle outstanding alarms, or if there are none wait until the next wakeup
+  // and handle alarms then before relinquishing control.  Idle no longer than
+  // timeout_us.  Passing in timeout_us=0 will run without blocking.
+  // mutex() must be held.
+  void ProcessAlarms(int64 timeout_us);
+
+  // Obtain the timer that the scheduler is using internally.  Important if you
+  // and the scheduler want to agree on the passage of time.
+  Timer* timer() { return timer_; }
+
+  // Obtain the thread system used by the scheduler.
+  ThreadSystem* thread_system() { return thread_system_; }
+
+  // Internal method to kick the system because something of interest to the
+  // overridden AwaitWakeup method has happened.  Exported here because C++
+  // naming hates you.
+  void Wakeup();
+
+  // These methods notify the scheduler of work sequences that may run work
+  // on it. They are only used for time simulations in MockScheduler and
+  // are no-ops during normal usage.
+  virtual void RegisterWorker(QueuedWorkerPool::Sequence* w);
+  virtual void UnregisterWorker(QueuedWorkerPool::Sequence* w);
+
+ protected:
+  // Internal method to await a wakeup event.  Block until wakeup_time_us (an
+  // absolute time since the epoch), or until something interesting (such as a
+  // call to Signal) occurs.  This is virtual to permit us to mock it out (the
+  // mock simply advances time). This maybe called with 0 in case where there
+  // are no timers currently active.
+  virtual void AwaitWakeupUntilUs(int64 wakeup_time_us);
+
+  bool running_waiting_alarms() const { return running_waiting_alarms_; }
+
+ private:
+  class CondVarTimeout;
+  class CondVarCallbackTimeout;
+  friend class SchedulerTest;
+
+  typedef std::set<Alarm*, CompareAlarms> AlarmSet;
+
+  int64 RunAlarms(bool* ran_alarms);
+  void AddAlarmMutexHeld(int64 wakeup_time_us, Alarm* alarm);
+  void CancelWaiting(Alarm* alarm);
+  bool NoPendingAlarms();
+
+  ThreadSystem* thread_system_;
+  Timer* timer_;
+  scoped_ptr<ThreadSystem::CondvarCapableMutex> mutex_;
+  // condvar_ tracks whether interesting (next-wakeup decreasing or
+  // signal_count_ increasing) events occur.
+  scoped_ptr<ThreadSystem::Condvar> condvar_;
+  uint32 index_;  // Used to disambiguate alarms with equal deadlines
+  AlarmSet outstanding_alarms_;  // Priority queue of future alarms
+  // An alarm may be deleted iff it is successfully removed from
+  // outstanding_alarms_.
+  int64 signal_count_;           // Number of times Signal has been called
+  AlarmSet waiting_alarms_;      // Alarms waiting for signal_count to change
+  bool running_waiting_alarms_;  // True if we're in process of invoking
+                                 // user callbacks...
+  DISALLOW_COPY_AND_ASSIGN(Scheduler);
+};
+
+// A simple adapter class that permits blocking until an alarm has been run or
+// cancelled.  Designed for stack allocation.
+//
+// Note that success_ is guarded by the acquire/release semantics of
+// atomic_bool and by monotonicity of done_.  Field order (==initialization
+// order) is important here.
+class SchedulerBlockingFunction : public Function {
+ public:
+  explicit SchedulerBlockingFunction(Scheduler* scheduler);
+  virtual ~SchedulerBlockingFunction();
+  virtual void Run();
+  virtual void Cancel();
+  // Block until called back, returning true for Run and false for Cancel.
+  bool Block();
+ private:
+  Scheduler* scheduler_;
+  bool success_;
+  AtomicBool done_;
+  DISALLOW_COPY_AND_ASSIGN(SchedulerBlockingFunction);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_SCHEDULER_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler_based_abstract_lock.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler_based_abstract_lock.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler_based_abstract_lock.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler_based_abstract_lock.h Thu May  1 11:43:36 2014
@@ -0,0 +1,59 @@
+/*
+ * 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)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_SCHEDULER_BASED_ABSTRACT_LOCK_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_SCHEDULER_BASED_ABSTRACT_LOCK_H_
+
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/named_lock_manager.h"
+
+namespace net_instaweb {
+
+class Function;
+class Scheduler;
+
+// A SchedulerBasedAbstractLock implements a Lock by blocking using the
+// scheduler, using exponential sleep time backoff and polling the lock on
+// wakeup.  The total time blocked on a long-held lock will be about 1.5 times
+// the time between the initial call to the lock routine attempt and the time
+// the lock is unlocked (ie we might wait for an extra amount of time equal to
+// half the time we were forced to wait).
+class SchedulerBasedAbstractLock : public NamedLock {
+ public:
+  virtual ~SchedulerBasedAbstractLock();
+  virtual bool LockTimedWait(int64 wait_ms);
+  virtual void LockTimedWait(int64 wait_ms, Function* callback);
+
+  virtual bool LockTimedWaitStealOld(int64 wait_ms, int64 steal_ms);
+  virtual void LockTimedWaitStealOld(
+      int64 wait_ms, int64 steal_ms, Function* callback);
+
+ protected:
+  virtual Scheduler* scheduler() const = 0;
+
+ private:
+  typedef bool (SchedulerBasedAbstractLock::*TryLockMethod)(int64 steal_ms);
+  bool TryLockIgnoreSteal(int64 steal_ignored);
+  bool BusySpin(TryLockMethod try_lock, int64 steal_ms);
+  void PollAndCallback(TryLockMethod try_lock, int64 steal_ms,
+                       int64 wait_ms, Function* callback);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_SCHEDULER_BASED_ABSTRACT_LOCK_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler_thread.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler_thread.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler_thread.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/scheduler_thread.h Thu May  1 11:43:36 2014
@@ -0,0 +1,63 @@
+// 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 SchedulerThread, used to run the Scheduler dispatch loop for
+// non-blocking servers.
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_SCHEDULER_THREAD_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_SCHEDULER_THREAD_H_
+
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/thread.h"
+#include "net/instaweb/util/public/thread_system.h"
+
+namespace net_instaweb {
+
+class Function;
+class Scheduler;
+
+// This class is a helper used to dispatch events on a scheduler in a thread
+// in case where the server infrastructure is non-blocking and therefore does
+// not provide a natural way to do it.
+class SchedulerThread : public ThreadSystem::Thread {
+ public:
+  // Creates the thread. The user still needs to call Start() manually.
+  SchedulerThread(ThreadSystem* thread_system, Scheduler* scheduler);
+
+  // Returns a function that, when run, will properly synchronize with this
+  // thread and shut it down cleanly, deleting the object as well.
+  // It is suggested for use with RewriteDriverFactory::defer_delete(); as it
+  // needs to be run after it's OK if scheduler timeouts no longer work.
+  Function* MakeDeleter();
+
+ protected:
+  virtual void Run();
+
+ private:
+  class CleanupFunction;
+  friend class CleanupFunction;
+
+  virtual ~SchedulerThread();
+
+  bool quit_;
+  Scheduler* scheduler_;
+
+  DISALLOW_COPY_AND_ASSIGN(SchedulerThread);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_SCHEDULER_THREAD_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/shared_circular_buffer.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/shared_circular_buffer.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/shared_circular_buffer.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/shared_circular_buffer.h Thu May  1 11:43:36 2014
@@ -0,0 +1,94 @@
+/*
+ * 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: fangfei@google.com (Fangfei Zhou)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_SHARED_CIRCULAR_BUFFER_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_SHARED_CIRCULAR_BUFFER_H_
+
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_util.h"
+
+namespace net_instaweb {
+
+class AbstractSharedMem;
+class AbstractSharedMemSegment;
+class AbstractMutex;
+class CircularBuffer;
+class MessageHandler;
+class Writer;
+
+// Shared memory circular buffer, the content of its shared memory segment is a
+// Mutex and a CircularBuffer.
+// In parent process, we initialize a shared memory segment. Then we create a
+// SharedCircularBuffer object in each process and attach it to the segment by
+// calling InitSegment(true, handler) once in the parent process and calling
+// InitSegment(false, handler) in each child.
+
+class SharedCircularBuffer {
+ public:
+  // Construct with shared memory, data buffer capacity, filename_prefix and
+  // filename_suffix. filename_prefix and filename_suffix are used to name
+  // segment for the shared circular buffer.
+  SharedCircularBuffer(AbstractSharedMem* shm_runtime,
+                       const int buffer_capacity,
+                       const GoogleString& filename_prefix,
+                       const GoogleString& filename_suffix);
+  virtual ~SharedCircularBuffer();
+  // Initialize the shared memory segment.
+  // parent = true if this is invoked in root process -- initialize the shared
+  // memory; parent = false if this is invoked in child process -- attach to
+  // existing segment.
+  bool InitSegment(bool parent, MessageHandler* handler);
+  // Reset circular buffer.
+  void Clear();
+  // Write content to circular buffer.
+  bool Write(const StringPiece& message);
+  // Write content of data in buffer to writer, without clearing the buffer.
+  bool Dump(Writer* writer, MessageHandler* handler);
+  // Return data content as string. This is for test purposes.
+  GoogleString ToString(MessageHandler* handler);
+  // This should be called from the root process as it is about to exit, when no
+  // future children are expected to start.
+  void GlobalCleanup(MessageHandler* handler);
+
+ private:
+  bool InitMutex(MessageHandler* handler);
+  GoogleString SegmentName() const;
+
+  // SegmentName looks like:
+  // filename_prefix/SharedCircularBuffer.filename_suffix.
+  AbstractSharedMem* shm_runtime_;
+  // Capacity of circular buffer.
+  const int buffer_capacity_;
+  // Circular buffer.
+  CircularBuffer* buffer_;
+  const GoogleString filename_prefix_;
+  // filename_suffix_ is used to distinguish SharedCircularBuffer.
+  const GoogleString filename_suffix_;
+  // Mutex for segment.
+  scoped_ptr<AbstractMutex> mutex_;
+  // Shared memory segment.
+  scoped_ptr<AbstractSharedMemSegment> segment_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedCircularBuffer);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_SHARED_CIRCULAR_BUFFER_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/shared_circular_buffer_test_base.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/shared_circular_buffer_test_base.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/shared_circular_buffer_test_base.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/shared_circular_buffer_test_base.h Thu May  1 11:43:36 2014
@@ -0,0 +1,108 @@
+// 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: fangfei@google.com (Fangfei Zhou)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_SHARED_CIRCULAR_BUFFER_TEST_BASE_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_SHARED_CIRCULAR_BUFFER_TEST_BASE_H_
+
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/abstract_shared_mem.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/gtest.h"
+#include "net/instaweb/util/public/mock_message_handler.h"
+#include "net/instaweb/util/public/shared_mem_test_base.h"
+#include "net/instaweb/util/public/string_util.h"
+
+namespace net_instaweb {
+class SharedCircularBuffer;
+
+// This TestBase is added to pthread_shared_mem_test
+class SharedCircularBufferTestBase : public testing::Test {
+ protected:
+  typedef void (SharedCircularBufferTestBase::*TestMethod)();
+
+  explicit SharedCircularBufferTestBase(SharedMemTestEnv* test_env);
+
+  bool CreateChild(TestMethod method);
+
+  // Test basic initialization/writing/cleanup.
+  void TestCreate();
+  // Test writing from child process.
+  void TestAdd();
+  // Test cleanup from child process.
+  void TestClear();
+  // Test the shared memory circular buffer.
+  void TestCircular();
+
+ private:
+  // Helper functions.
+  void TestCreateChild();
+  void TestAddChild();
+  void TestClearChild();
+  // Write to SharedCircularBuffer in a child process.
+  void TestChildWrite();
+  // Check content of SharedCircularBuffer in a child process.
+  void TestChildBuff();
+
+  // Initialize SharedMemoryCircularBuffer from child process.
+  SharedCircularBuffer* ChildInit();
+  // Initialize SharedMemoryCircularBuffer from root process.
+  SharedCircularBuffer* ParentInit();
+
+  scoped_ptr<SharedMemTestEnv> test_env_;
+  scoped_ptr<AbstractSharedMem> shmem_runtime_;
+  MockMessageHandler handler_;
+  // Message to write in Child process.
+  // We can't pass in argument in callback functions in this TestBase,
+  // stick value to member variable instead.
+  StringPiece message_;
+  // Expected content of SharedCircularBuffer.
+  // Used to check buffer content in a child process.
+  StringPiece expected_result_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedCircularBufferTestBase);
+};
+
+template<typename ConcreteTestEnv>
+class SharedCircularBufferTestTemplate : public SharedCircularBufferTestBase {
+ public:
+  SharedCircularBufferTestTemplate()
+      : SharedCircularBufferTestBase(new ConcreteTestEnv) {
+  }
+};
+
+TYPED_TEST_CASE_P(SharedCircularBufferTestTemplate);
+
+TYPED_TEST_P(SharedCircularBufferTestTemplate, TestCreate) {
+  SharedCircularBufferTestBase::TestCreate();
+}
+
+TYPED_TEST_P(SharedCircularBufferTestTemplate, TestAdd) {
+  SharedCircularBufferTestBase::TestAdd();
+}
+
+TYPED_TEST_P(SharedCircularBufferTestTemplate, TestClear) {
+  SharedCircularBufferTestBase::TestClear();
+}
+
+TYPED_TEST_P(SharedCircularBufferTestTemplate, TestCircular) {
+  SharedCircularBufferTestBase::TestCircular();
+}
+
+REGISTER_TYPED_TEST_CASE_P(SharedCircularBufferTestTemplate, TestCreate,
+                           TestAdd, TestClear, TestCircular);
+
+}  // namespace net_instaweb
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_SHARED_CIRCULAR_BUFFER_TEST_BASE_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/shared_dynamic_string_map.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/shared_dynamic_string_map.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/shared_dynamic_string_map.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/shared_dynamic_string_map.h Thu May  1 11:43:36 2014
@@ -0,0 +1,238 @@
+/*
+ * 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: jhoch@google.com (Jason Hoch)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_SHARED_DYNAMIC_STRING_MAP_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_SHARED_DYNAMIC_STRING_MAP_H_
+
+#include <cstddef>
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/abstract_mutex.h"
+#include "net/instaweb/util/public/abstract_shared_mem.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_util.h"
+
+namespace net_instaweb {
+
+class MessageHandler;
+class Writer;
+
+struct Entry {
+  int value;
+  size_t string_offset;
+};
+
+// A shared memory string to int dictionary/map, no deletion.
+// Currently the map is designed to fill with number_of_strings strings of
+// average length average_string_length.  Once the map is full it ignores
+// attempts to add additional information.
+// TODO(jhoch): make map dynamically sized
+class SharedDynamicStringMap {
+ public:
+  // Number of strings will be rounded up to a power of 2.
+  // Average string length should include terminating null character.
+  // Map will be able to hold exactly number_of_strings * average_string_length
+  // chars worth of string data.
+  SharedDynamicStringMap(size_t number_of_strings,
+                         size_t average_string_length,
+                         AbstractSharedMem* shm_runtime,
+                         const GoogleString& filename_prefix,
+                         const GoogleString& filename_suffix);
+
+  // Initialize the shared memory segment.  This method should complete before
+  // any other methods are executed.
+  // parent = true means invoked in root process, initialize the shared memory
+  //        = false means invoked in child process -- attach to existing segment
+  bool InitSegment(bool parent, MessageHandler* message_handler);
+
+  // Increments value corresponding to given string by 1.
+  // Adds the string to the map with initial value 1 if the string is not
+  // present.
+  // Returns the new value corresponding to the element.
+  // If the map is full it does nothing and returns 0.
+  int IncrementElement(const StringPiece& string);
+
+  // Retrieve the value corresponding to the string (returns 0 if the string is
+  // not in the map)
+  int LookupElement(const StringPiece& string) const;
+
+  // Dumps table's strings into StringSet
+  void GetKeys(StringSet* strings);
+
+  // Retrieve the number of strings inserted into the table.
+  int GetNumberInserted() const;
+
+  // Destroy shared memory segment and other relevant clean-up
+  void GlobalCleanup(MessageHandler* message_handler);
+
+  // Iterates through the string data that is present at the time of calling
+  // and dumps out each string with its associated value.  The value produced
+  // for a given string is going to be the value present whenever that string
+  // is dumped.
+  void Dump(Writer* writer, MessageHandler* message_handler);
+
+ private:
+  void ClearSegment(MessageHandler* message_handler);
+
+  // ***If lock = true, locks the mutex associated with the returned entry***
+  //    (to be unlocked by caller)
+  // Finds the index of the entry with the given string, or the first empty
+  // entry encountered, which can either be used for insertion purposes or
+  // to know that the string is not present, since the table does not support
+  // deletion.
+  //   -1 is returned if the entire table is traversed without finding the
+  // string or an empty spot (this should not happen if the table never exceeds
+  // 50% capacity).
+  //   entry_pointer is an output parameter.
+  //   Note that lock must always be set to true for any writing operation, and
+  // setting write to false for a read operation can result in a false read,
+  // albeit in very rare circumstances.  The circumstance is that an entry "AB"
+  // is being added to the table, where A and B are arbitrary strings, and a
+  // read of "A" is occurring, and the read of "A" catches the write of "AB"
+  // mid-write at exactly the moment where it can only see "A."
+  //   The fact that looking up without locking is possible relies on the
+  // assumption that entries are not deleted and that null characters fill up
+  // the char space upon initialization.
+  //   If 100% accurate lookup is needed then a new LookupElement method could
+  // be added that calls FindEntry(lock = true).
+  int FindEntry(const StringPiece& string,
+                bool lock,
+                Entry** entry_pointer) const;
+  Entry* GetEntry(size_t n) const;
+  Entry* GetFirstEntry() const;
+
+  // Gets the mutex for the nth table entry.
+  AbstractMutex* GetMutex(size_t n) const;
+  // Inserts the given string into the table (if there is room), by adding it
+  // to char storage and setting the entry_pointer's char offset and value (the
+  // former to string_offset and the latter to 1), and returns the resulting
+  // value of the entry (1 if it was successfully inserted, 0 otherwise)
+  //   The entry should be locked when this method is called.
+  int InsertString(const StringPiece& string, Entry* entry_pointer);
+  char* GetStringAtOffset(size_t offset) const;
+
+  // Math utility function, returns the smallest power of two greater than or
+  // equal to the input.
+  static size_t NextPowerOfTwo(size_t n);
+
+  //                               |
+  // Structure content             | Offset
+  //                               |
+  //  ___________________________  | mutex_offset_ = 0
+  // | Mutex0                    | |  - memory location = segment_->Base()
+  // |                           | |
+  // | Mutex1                    | | mutex_offset_ + mutex_size
+  // |                           | |
+  // | Mutex2                    | | mutex_offset_ + mutex_size_ * 2
+  // | .                         | |
+  // | .                         | |   - each mutex has size mutex_size
+  // | .                         | |
+  // |                           | |
+  // | MutexN                    | | mutex_offset_ + mutex_size_ * N
+  // | .                         | |
+  // | .                         | |   - there are table_size_ + 1 mutexes
+  // | .                         | |       (last mutex is for string_offset
+  // | .                         | |        and number_inserted)
+  // | .                         | |
+  // |___________________________| | strings_offset_ = mutex_offset_ +
+  // | String0======= |            |     kTableSize * mutex_size_
+  // |                |            |   = String offset0
+  // |                |            |
+  // | String1======= |            | String offset1
+  // |           _____|            |
+  // |          |                  |
+  // | String2= |                  | String offset2
+  // |          |________________  |
+  // |                           | |
+  // | String3================== | | etc.
+  // |                  _________| |
+  // |                 |           |
+  // | String4======== |           |   - strings are variable length, null
+  // |                 |_          |       terminated
+  // |                   |         |
+  // | String5========== |         |   - total allocated space is
+  // |                  _|         |       number_of_strings times average
+  // |                 |           |       string length
+  // | String6======== |           |
+  // |                 |_          |   - there are as many strings as have been
+  // | .                 |         |       added
+  // | .                 |         |
+  // | .                 |         |   - location at which to add next string is
+  // |___________________|         |       stored at string_offset_offset_
+  // |                 |           |       (see below)
+  // |                 |           |
+  // |  String offset  |           | string_offset_offset_ = strings_offset_ +
+  // |_________________|           |     number_of_strings_ *
+  // |        |                    |     average_string_length_
+  // | Number |                    |
+  // |  Inse- |                    | number_inserted_offset_ =
+  // |   rted |                    |     string_offset_offset_ + kOffsetSize
+  // |        |                    |
+  // |________|________________    | table_offset_ = number_inserted_offset_ +
+  // | Value0 | String offset0 |   |     kIntSize
+  // |  (int) |  (size_t)      |   |
+  // |        |                |   |
+  // | Value1 | String offset1 |   | table_offset_ + kEntrySize
+  // |        |                |   |
+  // | Value2 | String offset2 |   | table_offset_ + kEntrySize* 2
+  // | .      | .              |   |
+  // | .      | .              |   |   - each value and string offset makes an
+  // | .      | .              |   |       Entry struct
+  // |        |                |   |
+  // | ValueN | String offsetN |   | table_offset_ + kEntrySize * N
+  // | .      | .              |   |
+  // | .      | .              |   |   - there are table_size entries
+  // | .      | .              |   |
+  // |________|________________|   |
+
+  size_t number_of_strings_;
+  size_t average_string_length_;
+  // Sizes of various portions of the memory
+  size_t mutex_size_;
+  size_t table_size_;
+  // Offset from segment_->Base() at which various portions of the structure
+  // begin (see above depiction).
+  //   mutex_offset_ is the beginning of the (table_size_ + 1) mutexes
+  //   strings_offset_ is the beginning of the strings
+  //   string_offset_offset_ is where the offset of the next string to be
+  //     inserted is located
+  //   number_inserted_offset_ is where the number of inserted strings is
+  //     located
+  //   table_offset_ is the beginning of the table_size_ entries
+  size_t mutex_offset_;
+  size_t strings_offset_;
+  size_t string_offset_offset_;
+  size_t number_inserted_offset_;
+  size_t table_offset_;
+  // Total size of shared memory segment
+  size_t total_size_;
+
+  // The mutex for inserting strings, i.e. the one shared by the
+  // string_offset_ and number_inserted_ values.
+  scoped_ptr<AbstractMutex> insert_string_mutex_;
+
+  const GoogleString segment_name_;
+  AbstractSharedMem* shm_runtime_;
+  scoped_ptr<AbstractSharedMemSegment> segment_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedDynamicStringMap);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_SHARED_DYNAMIC_STRING_MAP_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/shared_dynamic_string_map_test_base.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/shared_dynamic_string_map_test_base.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/shared_dynamic_string_map_test_base.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/shared_dynamic_string_map_test_base.h Thu May  1 11:43:36 2014
@@ -0,0 +1,131 @@
+// 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: jhoch@google.com (Jason Hoch)
+
+#ifndef NET_INSTAWEB_UTIL_PUBLIC_SHARED_DYNAMIC_STRING_MAP_TEST_BASE_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_SHARED_DYNAMIC_STRING_MAP_TEST_BASE_H_
+
+#include <vector>
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/abstract_shared_mem.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/gtest.h"
+#include "net/instaweb/util/public/mock_message_handler.h"
+#include "net/instaweb/util/public/shared_mem_test_base.h"
+#include "net/instaweb/util/public/string.h"
+
+namespace net_instaweb {
+class SharedDynamicStringMap;
+
+class SharedDynamicStringMapTestBase : public testing::Test {
+ protected:
+  typedef void (SharedDynamicStringMapTestBase::*TestMethod0)();
+  typedef void (SharedDynamicStringMapTestBase::*TestMethod2)(int, int);
+
+  explicit SharedDynamicStringMapTestBase(SharedMemTestEnv* test_env);
+
+  // Create child process for given method - the latter is used for TestFill
+  // methods, which require arguments
+  bool CreateChild(TestMethod0 method);
+  bool CreateFillChild(TestMethod2 method, int start, int number_of_strings);
+
+  // Test simple functionality using Dump(Writer*)
+  void TestSimple();
+  // Test the creation and use of a child process.
+  void TestCreate();
+  // Test the creation and use of two child processes.
+  void TestAdd();
+  // Test that no unwanted insertions are performed when filling the map 1/4 of
+  // the way by checking length of Dump result.
+  void TestQuarterFull();
+  // Test the filling of the string map.
+  void TestFillSingleThread();
+  // Test the filling of the string map by more than one thread;
+  // no two threads access the same string.
+  void TestFillMultipleNonOverlappingThreads();
+  // Test the filling of the string map by more than one thread;
+  // no two child threads access the same string, but parent process
+  // hits strings at the same time as the child threads.
+  void TestFillMultipleOverlappingThreads();
+
+ private:
+  void AddChild();
+  void AddFillChild(int start, int number_of_strings);
+  void AddToFullTable();
+
+  // Initialize child process object
+  SharedDynamicStringMap* ChildInit();
+  // Initialize parent process object
+  SharedDynamicStringMap* ParentInit();
+
+  std::vector<GoogleString> strings_;
+
+  scoped_ptr<SharedMemTestEnv> test_env_;
+  scoped_ptr<AbstractSharedMem> shmem_runtime_;
+  MockMessageHandler handler_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedDynamicStringMapTestBase);
+};
+
+template<typename ConcreteTestEnv>
+class SharedDynamicStringMapTestTemplate
+    : public SharedDynamicStringMapTestBase {
+ public:
+  SharedDynamicStringMapTestTemplate()
+      : SharedDynamicStringMapTestBase(new ConcreteTestEnv) {
+  }
+};
+
+TYPED_TEST_CASE_P(SharedDynamicStringMapTestTemplate);
+
+TYPED_TEST_P(SharedDynamicStringMapTestTemplate, TestSimple) {
+  SharedDynamicStringMapTestBase::TestSimple();
+}
+
+TYPED_TEST_P(SharedDynamicStringMapTestTemplate, TestCreate) {
+  SharedDynamicStringMapTestBase::TestCreate();
+}
+
+TYPED_TEST_P(SharedDynamicStringMapTestTemplate, TestAdd) {
+  SharedDynamicStringMapTestBase::TestAdd();
+}
+
+TYPED_TEST_P(SharedDynamicStringMapTestTemplate, TestQuarterFull) {
+  SharedDynamicStringMapTestBase::TestQuarterFull();
+}
+
+TYPED_TEST_P(SharedDynamicStringMapTestTemplate, TestFillSingleThread) {
+  SharedDynamicStringMapTestBase::TestFillSingleThread();
+}
+
+TYPED_TEST_P(SharedDynamicStringMapTestTemplate,
+             TestFillMultipleNonOverlappingThreads) {
+  SharedDynamicStringMapTestBase::TestFillMultipleNonOverlappingThreads();
+}
+
+TYPED_TEST_P(SharedDynamicStringMapTestTemplate,
+             TestFillMultipleOverlappingThreads) {
+  SharedDynamicStringMapTestBase::TestFillMultipleOverlappingThreads();
+}
+
+REGISTER_TYPED_TEST_CASE_P(SharedDynamicStringMapTestTemplate, TestSimple,
+                           TestCreate, TestAdd, TestQuarterFull,
+                           TestFillSingleThread,
+                           TestFillMultipleNonOverlappingThreads,
+                           TestFillMultipleOverlappingThreads);
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_SHARED_DYNAMIC_STRING_MAP_TEST_BASE_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/shared_mem_lock_manager.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/shared_mem_lock_manager.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/shared_mem_lock_manager.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/shared_mem_lock_manager.h Thu May  1 11:43:36 2014
@@ -0,0 +1,98 @@
+/*
+ * 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_SHARED_MEM_LOCK_MANAGER_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_SHARED_MEM_LOCK_MANAGER_H_
+
+#include <cstddef>
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/named_lock_manager.h"
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_util.h"
+
+namespace net_instaweb {
+
+class AbstractSharedMem;
+class AbstractSharedMemSegment;
+class Hasher;
+class MessageHandler;
+class Scheduler;
+
+namespace SharedMemLockData {
+
+struct Bucket;
+
+}  // namespace SharedMemLockData
+
+// A simple shared memory named locking manager, which uses scheduler alarms
+// (via SchedulerBasedAbstractLock) when it needs to block.
+//
+// TODO(morlovich): Implement condvars?
+class SharedMemLockManager : public NamedLockManager {
+ public:
+  // Note that you must call Initialize() in the root process, and Attach in
+  // child processes to finish the initialization.
+  //
+  // Locks created by this object must not live after it dies.
+  SharedMemLockManager(
+      AbstractSharedMem* shm, const GoogleString& path, Scheduler* scheduler,
+      Hasher* hasher, MessageHandler* handler);
+  virtual ~SharedMemLockManager();
+
+  // Sets up our shared state for use of all child processes. Returns
+  // whether successful.
+  bool Initialize();
+
+  // Connects to already initialized state from a child process.
+  // Returns whether successful.
+  bool Attach();
+
+  // This should be called from the root process as it is about to exit,
+  // with the same value as were passed to the constructor of any
+  // instance on which Initialize() was called, except the message_handler
+  // may be different (if for example the original one is no longer available
+  // due to the cleanup sequence).
+  static void GlobalCleanup(AbstractSharedMem* shm, const GoogleString& path,
+                            MessageHandler* message_handler);
+
+  virtual NamedLock* CreateNamedLock(const StringPiece& name);
+
+ private:
+  friend class SharedMemLock;
+
+  SharedMemLockData::Bucket* Bucket(size_t bucket);
+
+  // Offset of mutex wrt to segment base.
+  size_t MutexOffset(SharedMemLockData::Bucket*);
+
+  AbstractSharedMem* shm_runtime_;
+  GoogleString path_;
+
+  scoped_ptr<AbstractSharedMemSegment> seg_;
+  Scheduler* scheduler_;
+  Hasher* hasher_;
+  MessageHandler* handler_;
+  size_t lock_size_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedMemLockManager);
+};
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_SHARED_MEM_LOCK_MANAGER_H_

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

Added: httpd/mod_spdy/trunk/net/instaweb/util/public/shared_mem_lock_manager_test_base.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/trunk/net/instaweb/util/public/shared_mem_lock_manager_test_base.h?rev=1591622&view=auto
==============================================================================
--- httpd/mod_spdy/trunk/net/instaweb/util/public/shared_mem_lock_manager_test_base.h (added)
+++ httpd/mod_spdy/trunk/net/instaweb/util/public/shared_mem_lock_manager_test_base.h Thu May  1 11:43:36 2014
@@ -0,0 +1,97 @@
+// 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_SHARED_MEM_LOCK_MANAGER_TEST_BASE_H_
+#define NET_INSTAWEB_UTIL_PUBLIC_SHARED_MEM_LOCK_MANAGER_TEST_BASE_H_
+
+#include "base/scoped_ptr.h"
+#include "net/instaweb/util/public/abstract_shared_mem.h"
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/gtest.h"
+#include "net/instaweb/util/public/md5_hasher.h"
+#include "net/instaweb/util/public/mock_message_handler.h"
+#include "net/instaweb/util/public/mock_scheduler.h"
+#include "net/instaweb/util/public/mock_timer.h"
+#include "net/instaweb/util/public/shared_mem_lock_manager.h"
+#include "net/instaweb/util/public/shared_mem_test_base.h"
+#include "net/instaweb/util/public/thread_system.h"
+
+namespace net_instaweb {
+
+class SharedMemLockManagerTestBase : public testing::Test {
+ protected:
+  typedef void (SharedMemLockManagerTestBase::*TestMethod)();
+
+  explicit SharedMemLockManagerTestBase(SharedMemTestEnv* test_env);
+  virtual void SetUp();
+  virtual void TearDown();
+
+  void TestBasic();
+  void TestDestructorUnlock();
+  void TestSteal();
+
+ private:
+  bool CreateChild(TestMethod method);
+
+  SharedMemLockManager* CreateLockManager();
+  SharedMemLockManager* AttachDefault();
+
+  void TestBasicChild();
+  void TestStealChild();
+
+  scoped_ptr<SharedMemTestEnv> test_env_;
+  scoped_ptr<AbstractSharedMem> shmem_runtime_;
+  MockMessageHandler handler_;
+  MockTimer timer_;   // note: this is thread-unsafe, and if we are running in
+                      // a process-based environment it's not shared at all.
+                      // Therefore,  all advancement must be done in either
+                      // parent or kid but not both.
+  scoped_ptr<ThreadSystem> thread_system_;
+  MockScheduler scheduler_;
+  MD5Hasher hasher_;
+  scoped_ptr<SharedMemLockManager> root_lock_manager_;  // used for init only.
+
+  DISALLOW_COPY_AND_ASSIGN(SharedMemLockManagerTestBase);
+};
+
+template<typename ConcreteTestEnv>
+class SharedMemLockManagerTestTemplate : public SharedMemLockManagerTestBase {
+ public:
+  SharedMemLockManagerTestTemplate()
+      : SharedMemLockManagerTestBase(new ConcreteTestEnv) {
+  }
+};
+
+TYPED_TEST_CASE_P(SharedMemLockManagerTestTemplate);
+
+TYPED_TEST_P(SharedMemLockManagerTestTemplate, TestBasic) {
+  SharedMemLockManagerTestBase::TestBasic();
+}
+
+TYPED_TEST_P(SharedMemLockManagerTestTemplate, TestDestructorUnlock) {
+  SharedMemLockManagerTestBase::TestDestructorUnlock();
+}
+
+TYPED_TEST_P(SharedMemLockManagerTestTemplate, TestSteal) {
+  SharedMemLockManagerTestBase::TestSteal();
+}
+
+REGISTER_TYPED_TEST_CASE_P(SharedMemLockManagerTestTemplate, TestBasic,
+                           TestDestructorUnlock, TestSteal);
+
+}  // namespace net_instaweb
+
+#endif  // NET_INSTAWEB_UTIL_PUBLIC_SHARED_MEM_LOCK_MANAGER_TEST_BASE_H_

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