/*
 * Copyright 2012 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)

// Thread-synchronization utility class for reproducing races in unit tests.

#include "pagespeed/kernel/thread/thread_synchronizer.h"

#include "base/logging.h"
#include "strings/stringpiece_utils.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/condvar.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/stl_util.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/base/timer.h"

namespace net_instaweb {

class ThreadSynchronizer::SyncPoint {
 public:
  SyncPoint(ThreadSystem* thread_system, const GoogleString& key)
      : mutex_(thread_system->NewMutex()),
        condvar_(mutex_->NewCondvar()),
        signal_count_(0),
        key_(key),
        allow_sloppy_(false) {
  }

  ~SyncPoint() {
    // TODO(jmarantz): This highlights that further generality is
    // likely needed here as adoption of this race-injection
    // methodology grows.  Perhaps enabling should be key-specific
    // in addition to applying to the whole class.
    if (!allow_sloppy_) {
      CHECK_EQ(0, signal_count_) << key_;
    }
  }

  void Wait() {
    ScopedMutex lock(condvar_->mutex());
    while (signal_count_ <= 0) {
      condvar_->Wait();
    }
    --signal_count_;
  }

  void TimedWait(int64 timeout_ms, Timer* timer) {
    ScopedMutex lock(condvar_->mutex());
    int64 now_ms = timer->NowMs();
    int64 end_ms = now_ms + timeout_ms;
    while ((signal_count_ <= 0) && (now_ms < end_ms)) {
      condvar_->TimedWait(end_ms - now_ms);
      now_ms = timer->NowMs();
    }

    // Note: we decrement signal even if we exited the loop via
    // timeout.  This is because we still expect Signal/*Wait to be
    // balanced.  We can allow SloppyTermination in cases where that
    // doesn't work, although then we must be careful of desired
    // semantics if a signal is never delivered for the first
    // call to TimedWait, but is delivered for the second one.
    --signal_count_;
  }

  void Signal() {
    ScopedMutex lock(condvar_->mutex());
    ++signal_count_;
    condvar_->Signal();
  }

  void AllowSloppyTermination() { allow_sloppy_ = true; }

 private:
  scoped_ptr<ThreadSystem::CondvarCapableMutex> mutex_;
  scoped_ptr<ThreadSystem::Condvar> condvar_;
  int signal_count_;
  GoogleString key_;  // for debugging;
  bool allow_sloppy_;

  DISALLOW_COPY_AND_ASSIGN(SyncPoint);
};

ThreadSynchronizer::ThreadSynchronizer(ThreadSystem* thread_system)
    : enabled_(false),
      thread_system_(thread_system),
      map_mutex_(thread_system->NewMutex()),
      timer_(thread_system->NewTimer()) {
}

ThreadSynchronizer::~ThreadSynchronizer() {
  STLDeleteValues(&sync_map_);
}

ThreadSynchronizer::SyncPoint* ThreadSynchronizer::GetSyncPoint(
    const GoogleString& key) {
  ScopedMutex lock(map_mutex_.get());
  SyncPoint* sync_point = sync_map_[key];
  if (sync_point == NULL) {
    sync_point = new SyncPoint(thread_system_, key);
    sync_map_[key] = sync_point;
  }
  return sync_point;
}

void ThreadSynchronizer::DoWait(const char* key) {
  if (MatchesPrefix(key)) {
    GetSyncPoint(key)->Wait();
  }
}

void ThreadSynchronizer::DoTimedWait(const char* key, int64 timeout_ms) {
  if (MatchesPrefix(key)) {
    GetSyncPoint(key)->TimedWait(timeout_ms, timer_.get());
  }
}

void ThreadSynchronizer::DoSignal(const char* key) {
  if (MatchesPrefix(key)) {
    GetSyncPoint(key)->Signal();
  }
}

bool ThreadSynchronizer::MatchesPrefix(const char* key) const {
  StringPiece key_piece(key);
  for (int i = 0, n = prefixes_.size(); i < n; ++i) {
    if (strings::StartsWith(key_piece, prefixes_[i])) {
      return true;
    }
  }
  return false;
}

void ThreadSynchronizer::AllowSloppyTermination(const char* key) {
  if (MatchesPrefix(key)) {
    GetSyncPoint(key)->AllowSloppyTermination();
  }
}

}  // namespace net_instaweb
