Coverage for /Syzygy/kasko/upload_thread.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%0099.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 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/kasko/upload_thread.h"
  16    :  
  17    :  #include <windows.h>
  18    :  #include "base/logging.h"
  19    :  #include "base/files/file_path.h"
  20    :  #include "base/strings/string16.h"
  21    :  #include "base/strings/string_util.h"
  22    :  #include "syzygy/kasko/waitable_timer.h"
  23    :  
  24  m :  namespace kasko {
  25    :  
  26    :  // static
  27  m :  std::unique_ptr<UploadThread> UploadThread::Create(
  28  m :      const base::FilePath& exclusive_path,
  29  m :      std::unique_ptr<WaitableTimer> waitable_timer,
  30  m :      const base::Closure& uploader) {
  31  m :    std::unique_ptr<UploadThread> instance;
  32    :  
  33    :    // '\' is the only character not permitted in mutex names.
  34  m :    base::string16 escaped_path;
  35  m :    base::ReplaceChars(exclusive_path.value(), L"\\", L"/", &escaped_path);
  36  m :    base::string16 mutex_name = L"Local\\kasko_uploader_mutex_" + escaped_path;
  37  m :    base::string16 wake_event_name =
  38  m :        L"Local\\kasko_uploader_wake_event_" + escaped_path;
  39  m :    base::win::ScopedHandle mutex(::CreateMutex(NULL, FALSE, mutex_name.c_str()));
  40  m :    DPCHECK(mutex.Get());
  41  m :    base::win::ScopedHandle stop_event(::CreateEvent(NULL, TRUE, FALSE, NULL));
  42  m :    DPCHECK(stop_event.Get());
  43  m :    base::win::ScopedHandle wake_event(
  44  m :        ::CreateEvent(NULL, FALSE, FALSE, wake_event_name.c_str()));
  45  m :    DPCHECK(wake_event.Get());
  46  m :    if (mutex.Get() && stop_event.Get() && wake_event.Get()) {
  47  m :      instance.reset(new UploadThread(std::move(mutex), std::move(stop_event),
  48  m :                                      std::move(wake_event),
  49  m :                                      std::move(waitable_timer), uploader));
  50  m :    }
  51    :  
  52  m :    return std::move(instance);
  53  m :  }
  54    :  
  55  m :  UploadThread::~UploadThread() {
  56    :    // It's a bad idea to shut down without stopping the service. It's also a bad
  57    :    // idea to block unexpectedly in our destructor.
  58  m :    CHECK(!thread_impl_.HasBeenStarted() || thread_impl_.HasBeenJoined());
  59  m :  }
  60    :  
  61  m :  void UploadThread::Start() {
  62  m :    thread_impl_.Start();
  63  m :  }
  64    :  
  65  m :  void UploadThread::Stop() {
  66  m :    BOOL result = ::SetEvent(stop_event_.Get());
  67  m :    PCHECK(result)
  68  m :        << "Failed to signal stop event. Terminating to avoid deadlock.";
  69  m :  }
  70    :  
  71  m :  void UploadThread::Join() {
  72  m :    Stop();
  73  m :    thread_impl_.Join();
  74  m :  }
  75    :  
  76  m :  void UploadThread::UploadOneNowAsync() {
  77  m :    BOOL result = ::SetEvent(wake_event_.Get());
  78  m :    DPCHECK(result);
  79  m :  }
  80    :  
  81  m :  UploadThread::ThreadImpl::ThreadImpl(UploadThread* owner)
  82  m :      : base::SimpleThread("upload_thread"), owner_(owner) {
  83  m :  }
  84    :  
  85  m :  UploadThread::ThreadImpl::~ThreadImpl(){}
  86    :  
  87  m :  void UploadThread::ThreadImpl::Run() {
  88  m :    HANDLE handles_pre_mutex[] = {
  89  m :        owner_->mutex_.Get(),
  90  m :        owner_->stop_event_.Get()
  91  m :    };
  92  m :    DWORD wait_result = ::WaitForMultipleObjects(
  93  m :        arraysize(handles_pre_mutex), handles_pre_mutex, FALSE, INFINITE);
  94  m :    switch (wait_result) {
  95  m :      case WAIT_OBJECT_0:
  96  m :      case WAIT_ABANDONED_0:
  97    :        // mutex_
  98  m :        break;
  99  m :      case WAIT_OBJECT_0 + 1:
 100    :        // stop_event_
 101  m :        return;
 102  m :      default:
 103  m :        DPLOG(ERROR) << "WaitForMultipleObjects failed.";
 104  m :        return;
 105  m :    }
 106    :  
 107    :    // We have the mutex now. We will wait on the wake event, the stop event, and
 108    :    // the timer.
 109  m :    HANDLE handles_post_mutex[] = {owner_->wake_event_.Get(),
 110  m :                                   owner_->stop_event_.Get(),
 111  m :                                   owner_->waitable_timer_->GetHANDLE()};
 112    :  
 113  m :    while (true) {
 114  m :      owner_->waitable_timer_->Start();
 115  m :      wait_result = ::WaitForMultipleObjects(arraysize(handles_post_mutex),
 116  m :                                             handles_post_mutex, FALSE, INFINITE);
 117  m :      switch (wait_result) {
 118  m :        case WAIT_OBJECT_0:
 119    :          // wake_event_
 120  m :          break;
 121  m :        case WAIT_OBJECT_0 + 1:
 122    :          // stop_event_
 123  m :          return;
 124  m :        case WAIT_OBJECT_0 + 2:
 125    :          // waitable_timer_
 126  m :          break;
 127  m :        default:
 128  m :          DPLOG(ERROR) << "WaitForMultipleObjects failed.";
 129  m :          return;
 130  m :      }
 131  m :      owner_->uploader_.Run();
 132  m :    }
 133  m :  }
 134    :  
 135  m :  UploadThread::UploadThread(base::win::ScopedHandle mutex,
 136  m :                             base::win::ScopedHandle stop_event,
 137  m :                             base::win::ScopedHandle wake_event,
 138  m :                             std::unique_ptr<WaitableTimer> waitable_timer,
 139  m :                             const base::Closure& uploader)
 140  m :      : mutex_(mutex.Take()),
 141  m :        stop_event_(stop_event.Take()),
 142  m :        wake_event_(wake_event.Take()),
 143  m :        waitable_timer_(std::move(waitable_timer)),
 144  m :        uploader_(uploader),
 145  m :        thread_impl_(this) {
 146  m :  }
 147    :  
 148  m :  }  // namespace kasko

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