Coverage for /Syzygy/bard/story.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
90.4%1421570.C++source

Line-by-line coverage:

   1    :  // Copyright 2015 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/bard/story.h"
  16    :  
  17    :  #include "base/bind.h"
  18    :  #include "base/synchronization/condition_variable.h"
  19    :  #include "syzygy/bard/events/heap_alloc_event.h"
  20    :  #include "syzygy/bard/events/heap_create_event.h"
  21    :  #include "syzygy/bard/events/heap_destroy_event.h"
  22    :  #include "syzygy/bard/events/heap_free_event.h"
  23    :  #include "syzygy/bard/events/heap_realloc_event.h"
  24    :  #include "syzygy/bard/events/heap_set_information_event.h"
  25    :  #include "syzygy/bard/events/heap_size_event.h"
  26    :  #include "syzygy/bard/events/linked_event.h"
  27    :  
  28    :  namespace bard {
  29    :  
  30    :  namespace {
  31    :  
  32    :  using events::LinkedEvent;
  33    :  
  34    :  }  // namespace
  35    :  
  36  E :  Story::PlotLine* Story::AddPlotLine(std::unique_ptr<PlotLine> plot_line) {
  37  E :    PlotLine* pl = plot_line.get();
  38  E :    plot_lines_.push_back(plot_line.release());
  39  E :    return pl;
  40  E :  }
  41    :  
  42  E :  Story::PlotLine* Story::CreatePlotLine() {
  43  E :    PlotLine* plot_line = new PlotLine();
  44  E :    plot_lines_.push_back(plot_line);
  45  E :    return plot_line;
  46  E :  }
  47    :  
  48  E :  bool Story::Save(core::OutArchive* out_archive) const {
  49  E :    std::map<const LinkedEvent*, size_t> linked_event_ids;
  50    :  
  51    :    // Serialize the number of plot lines.
  52  E :    out_archive->Save(plot_lines_.size());
  53    :  
  54    :    // Save each plot line.
  55  E :    for (PlotLine* plot_line : plot_lines_) {
  56  E :      if (!out_archive->Save(plot_line->size())) {
  57  i :        return false;
  58    :      }
  59    :  
  60  E :      for (const EventInterface* event : *plot_line) {
  61  E :        if (!EventInterface::Save(event, out_archive))
  62  i :          return false;
  63    :  
  64    :        // Assign an integer ID to linked events so that the connections
  65    :        // between them can be expressed.
  66  E :        if (event->type() == EventInterface::kLinkedEvent) {
  67    :          const LinkedEvent* linked_event =
  68  E :              reinterpret_cast<const LinkedEvent*>(event);
  69  E :          linked_event_ids.insert(
  70    :              std::make_pair(linked_event, linked_event_ids.size()));
  71    :        }
  72  E :      }
  73  E :    }
  74    :  
  75    :    // Serialize the linked event connections.
  76  E :    for (auto event_id_pair : linked_event_ids) {
  77  E :      const LinkedEvent* linked_event = event_id_pair.first;
  78    :  
  79    :      // Save the ID of this event and the number of input dependencies.
  80  E :      if (!out_archive->Save(event_id_pair.second))
  81  i :        return false;
  82  E :      if (!out_archive->Save(linked_event->deps().size()))
  83  i :        return false;
  84    :  
  85    :      // Save the ID of each input dependency.
  86  E :      for (auto dep : linked_event->deps()) {
  87  E :        auto it = linked_event_ids.find(dep);
  88  E :        DCHECK(it != linked_event_ids.end());
  89  E :        if (!out_archive->Save(it->second))
  90  i :          return false;
  91  E :      }
  92  E :    }
  93    :  
  94  E :    return true;
  95  E :  }
  96    :  
  97  E :  bool Story::Load(core::InArchive* in_archive) {
  98  E :    std::vector<LinkedEvent*> linked_events_by_id;
  99    :  
 100  E :    size_t plot_line_count = 0;
 101  E :    if (!in_archive->Load(&plot_line_count))
 102  i :      return false;
 103    :  
 104    :    // Read the plot lines.
 105  E :    for (size_t i = 0; i < plot_line_count; ++i) {
 106  E :      std::unique_ptr<PlotLine> plot_line(new PlotLine());
 107    :  
 108    :      // Read the events.
 109  E :      size_t event_count = 0;
 110  E :      if (!in_archive->Load(&event_count))
 111  i :        return false;
 112  E :      for (size_t j = 0; j < event_count; ++j) {
 113  E :        std::unique_ptr<EventInterface> event = EventInterface::Load(in_archive);
 114  E :        if (!event.get())
 115  i :          return false;
 116    :  
 117  E :        if (event->type() == EventInterface::kLinkedEvent) {
 118  E :          LinkedEvent* linked_event = reinterpret_cast<LinkedEvent*>(event.get());
 119  E :          linked_events_by_id.push_back(linked_event);
 120    :        }
 121    :  
 122  E :        plot_line->push_back(event.release());
 123  E :      }
 124    :  
 125  E :      plot_lines_.push_back(plot_line.release());
 126  E :    }
 127    :  
 128    :    // Deserialize event dependencies.
 129  E :    for (size_t i = 0; i < linked_events_by_id.size(); ++i) {
 130  E :      size_t event_id = 0;
 131  E :      if (!in_archive->Load(&event_id))
 132  i :        return false;
 133  E :      DCHECK_GT(linked_events_by_id.size(), event_id);
 134  E :      LinkedEvent* event = linked_events_by_id[event_id];
 135    :  
 136  E :      size_t dep_count = 0;
 137  E :      if (!in_archive->Load(&dep_count))
 138  i :        return false;
 139    :  
 140    :      // Deserialize the dependencies and emit them.
 141  E :      for (size_t j = 0; j < dep_count; ++j) {
 142  E :        size_t dep_id = 0;
 143  E :        if (!in_archive->Load(&dep_id))
 144  i :          return false;
 145  E :        DCHECK_GT(linked_events_by_id.size(), dep_id);
 146  E :        LinkedEvent* dep = linked_events_by_id[dep_id];
 147  E :        event->AddDep(dep);
 148  E :      }
 149  E :    }
 150    :  
 151  E :    return true;
 152  E :  }
 153    :  
 154    :  namespace {
 155    :  
 156    :  struct RunnerInfo {
 157  E :    RunnerInfo() : cv(&lock), completed_count(0), failed(nullptr) {}
 158    :  
 159    :    base::Lock lock;
 160    :    base::ConditionVariable cv;
 161    :    size_t completed_count;
 162    :    Story::PlotLineRunner* failed;
 163    :  };
 164    :  
 165    :  // Callback used to keep track of which runners have finished.
 166  E :  void OnComplete(RunnerInfo* info, Story::PlotLineRunner* runner) {
 167  E :    DCHECK_NE(static_cast<RunnerInfo*>(nullptr), info);
 168  E :    DCHECK_NE(static_cast<Story::PlotLineRunner*>(nullptr), runner);
 169    :  
 170  E :    base::AutoLock auto_lock(info->lock);
 171  E :    ++info->completed_count;
 172  E :    if (runner->Failed())
 173  E :      info->failed = runner;
 174  E :    info->cv.Signal();
 175  E :  }
 176    :  
 177    :  }  // namespace
 178    :  
 179  E :  bool Story::Play(void* backdrop) {
 180    :    // Set up the callback for each runner to invoke.
 181  E :    RunnerInfo info;
 182  E :    auto on_complete = base::Bind(&OnComplete, base::Unretained(&info));
 183    :  
 184    :    // Create all of the runners and threads for them.
 185  E :    ScopedVector<PlotLineRunner> runners;
 186  E :    for (auto plot_line : plot_lines_) {
 187  E :      auto runner = new PlotLineRunner(backdrop, plot_line);
 188  E :      runner->set_on_complete(on_complete);
 189  E :      runners.push_back(runner);
 190  E :    }
 191    :  
 192    :    // Start the threads.
 193  E :    for (auto runner : runners)
 194  E :      runner->Start();
 195    :  
 196    :    // Wait for all threads to finish successfully, or for one to fail.
 197  E :    bool success = true;
 198  E :    while (true) {
 199    :      // Wait for at least one runner to complete.
 200  E :      base::AutoLock auto_lock(info.lock);
 201  E :      info.cv.Wait();
 202    :  
 203  E :      if (info.failed) {
 204  E :        success = false;
 205  E :        break;
 206    :      }
 207    :  
 208  E :      if (info.completed_count == runners.size())
 209  E :        break;
 210  E :    }
 211    :  
 212  E :    return success;
 213  E :  }
 214    :  
 215  E :  bool Story::operator==(const Story& story) const {
 216  E :    if (plot_lines().size() != story.plot_lines().size())
 217  i :      return false;
 218  E :    for (size_t i = 0; i < plot_lines().size(); ++i) {
 219  E :      if (!(*plot_lines()[i] == *story.plot_lines()[i]))
 220  i :        return false;
 221  E :    }
 222  E :    return true;
 223  E :  }
 224    :  
 225    :  Story::PlotLineRunner::PlotLineRunner(void* backdrop, PlotLine* plot_line)
 226  E :      : backdrop_(backdrop),
 227  E :        plot_line_(plot_line),
 228  E :        failed_event_(nullptr) {
 229  E :  }
 230    :  
 231  E :  void Story::PlotLineRunner::ThreadMain() {
 232  E :    base::PlatformThread::SetName("PlotLineRunner");
 233  E :    RunImpl();
 234  E :    if (!on_complete_.is_null())
 235  E :      on_complete_.Run(this);
 236  E :  }
 237    :  
 238  E :  void Story::PlotLineRunner::Start() {
 239  E :    DCHECK(handle_.is_null());
 240  E :    CHECK(base::PlatformThread::Create(0, this, &handle_));
 241  E :  }
 242    :  
 243  E :  void Story::PlotLineRunner::Join() {
 244  E :    DCHECK(!handle_.is_null());
 245  E :    base::PlatformThread::Join(handle_);
 246  E :  }
 247    :  
 248  E :  void Story::PlotLineRunner::RunImpl() {
 249  E :    for (size_t i = 0; i < plot_line_->size(); ++i) {
 250  E :      auto evt = (*plot_line_)[i];
 251  E :      if (!evt->Play(backdrop_)) {
 252  E :        failed_event_ = evt;
 253  E :        return;
 254    :      }
 255  E :    }
 256  E :  }
 257    :  
 258    :  }  // namespace bard
 259    :  
 260    :  bool operator==(const bard::Story::PlotLine& pl1,
 261  E :                  const bard::Story::PlotLine& pl2) {
 262  E :    if (pl1.size() != pl2.size())
 263  i :      return false;
 264  E :    for (size_t i = 0; i < pl1.size(); ++i) {
 265  E :      if (!pl1[i]->Equals(pl2[i]))
 266  i :        return false;
 267  E :    }
 268  E :    return true;
 269  E :  }

Coverage information generated Fri Jul 29 11:00:21 2016.