Coverage for /Syzygy/kasko/upload_thread.cc

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

Coverage information generated Thu Jan 14 17:40:38 2016.