<commit_before>/*
 * Copyright © 2012 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/** @file brw_fs_register_coalesce.cpp
 *
 * Implements register coalescing: Checks if the two registers involved in a
 * raw move don't interfere, in which case they can both be stored in the same
 * place and the MOV removed.
 *
 * To do this, all uses of the source of the MOV in the shader are replaced
 * with the destination of the MOV. For example:
 *
 * add vgrf3:F, vgrf1:F, vgrf2:F
 * mov vgrf4:F, vgrf3:F
 * mul vgrf5:F, vgrf5:F, vgrf4:F
 *
 * becomes
 *
 * add vgrf4:F, vgrf1:F, vgrf2:F
 * mul vgrf5:F, vgrf5:F, vgrf4:F
 */

#include "brw_fs.h"
#include "brw_fs_live_variables.h"

static bool
is_coalesce_candidate(const fs_inst *inst, const int *virtual_grf_sizes)
{
   if (inst->opcode != BRW_OPCODE_MOV ||
       inst->is_partial_write() ||
       inst->saturate ||
       inst->src[0].file != GRF ||
       inst->src[0].negate ||
       inst->src[0].abs ||
       !inst->src[0].is_contiguous() ||
       inst->dst.file != GRF ||
       inst->dst.type != inst->src[0].type) {
      return false;
   }

   if (virtual_grf_sizes[inst->src[0].reg] >
       virtual_grf_sizes[inst->dst.reg])
      return false;

   return true;
}

static bool
can_coalesce_vars(brw::fs_live_variables *live_intervals,
                  const exec_list *instructions, const fs_inst *inst,
                  int var_to, int var_from)
{
   if (live_intervals->vars_interfere(var_from, var_to) &&
       !inst->dst.equals(inst->src[0])) {

      /* We know that the live ranges of A (var_from) and B (var_to)
       * interfere because of the ->vars_interfere() call above. If the end
       * of B's live range is after the end of A's range, then we know two
       * things:
       *  - the start of B's live range must be in A's live range (since we
       *    already know the two ranges interfere, this is the only remaining
       *    possibility)
       *  - the interference isn't of the form we're looking for (where B is
       *    entirely inside A)
       */
      if (live_intervals->end[var_to] > live_intervals->end[var_from])
         return false;

      int scan_ip = -1;

      foreach_list(n, instructions) {
         fs_inst *scan_inst = (fs_inst *)n;
         scan_ip++;

         if (scan_inst->is_control_flow())
            return false;

         if (scan_ip <= live_intervals->start[var_to])
            continue;

         if (scan_ip > live_intervals->end[var_to])
            break;

         if (scan_inst->dst.equals(inst->dst) ||
             scan_inst->dst.equals(inst->src[0]))
            return false;
      }
   }

   return true;
}

bool
fs_visitor::register_coalesce()
{
   bool progress = false;

   calculate_live_intervals();

   int src_size = 0;
   int channels_remaining = 0;
   int reg_from = -1, reg_to = -1;
   int reg_to_offset[MAX_SAMPLER_MESSAGE_SIZE];
   fs_inst *mov[MAX_SAMPLER_MESSAGE_SIZE];
   int var_to[MAX_SAMPLER_MESSAGE_SIZE];
   int var_from[MAX_SAMPLER_MESSAGE_SIZE];

   foreach_list(node, &this->instructions) {
      fs_inst *inst = (fs_inst *)node;

      if (!is_coalesce_candidate(inst, virtual_grf_sizes))
         continue;

      if (reg_from != inst->src[0].reg) {
         reg_from = inst->src[0].reg;

         src_size = virtual_grf_sizes[inst->src[0].reg];
         assert(src_size <= MAX_SAMPLER_MESSAGE_SIZE);

         channels_remaining = src_size;
         memset(mov, 0, sizeof(mov));

         reg_to = inst->dst.reg;
      }

      if (reg_to != inst->dst.reg)
         continue;

      const int offset = inst->src[0].reg_offset;
      reg_to_offset[offset] = inst->dst.reg_offset;
      mov[offset] = inst;
      channels_remaining--;

      if (channels_remaining)
         continue;

      bool can_coalesce = true;
      for (int i = 0; i < src_size; i++) {
         var_to[i] = live_intervals->var_from_vgrf[reg_to] + reg_to_offset[i];
         var_from[i] = live_intervals->var_from_vgrf[reg_from] + i;

         if (!can_coalesce_vars(live_intervals, &instructions, inst,
                                var_to[i], var_from[i])) {
            can_coalesce = false;
            reg_from = -1;
            break;
         }
      }

      if (!can_coalesce)
         continue;

      progress = true;

      for (int i = 0; i < src_size; i++) {
         if (mov[i]) {
            mov[i]->opcode = BRW_OPCODE_NOP;
            mov[i]->conditional_mod = BRW_CONDITIONAL_NONE;
            mov[i]->dst = reg_undef;
            mov[i]->src[0] = reg_undef;
            mov[i]->src[1] = reg_undef;
            mov[i]->src[2] = reg_undef;
         }
      }

      foreach_list(node, &this->instructions) {
         fs_inst *scan_inst = (fs_inst *)node;

         for (int i = 0; i < src_size; i++) {
            if (mov[i]) {
               if (scan_inst->dst.file == GRF &&
                   scan_inst->dst.reg == reg_from &&
                   scan_inst->dst.reg_offset == i) {
                  scan_inst->dst.reg = reg_to;
                  scan_inst->dst.reg_offset = reg_to_offset[i];
               }
               for (int j = 0; j < 3; j++) {
                  if (scan_inst->src[j].file == GRF &&
                      scan_inst->src[j].reg == reg_from &&
                      scan_inst->src[j].reg_offset == i) {
                     scan_inst->src[j].reg = reg_to;
                     scan_inst->src[j].reg_offset = reg_to_offset[i];
                  }
               }
            }
         }
      }

      for (int i = 0; i < src_size; i++) {
         live_intervals->start[var_to[i]] =
            MIN2(live_intervals->start[var_to[i]],
                 live_intervals->start[var_from[i]]);
         live_intervals->end[var_to[i]] =
            MAX2(live_intervals->end[var_to[i]],
                 live_intervals->end[var_from[i]]);
      }
      reg_from = -1;
   }

   if (progress) {
      foreach_list_safe(node, &this->instructions) {
         fs_inst *inst = (fs_inst *)node;

         if (inst->opcode == BRW_OPCODE_NOP) {
            inst->remove();
         }
      }

      invalidate_live_intervals();
   }

   return progress;
}
<commit_msg>i965/fs: Recognize nop-MOV instructions early.<commit_after>/*
 * Copyright © 2012 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/** @file brw_fs_register_coalesce.cpp
 *
 * Implements register coalescing: Checks if the two registers involved in a
 * raw move don't interfere, in which case they can both be stored in the same
 * place and the MOV removed.
 *
 * To do this, all uses of the source of the MOV in the shader are replaced
 * with the destination of the MOV. For example:
 *
 * add vgrf3:F, vgrf1:F, vgrf2:F
 * mov vgrf4:F, vgrf3:F
 * mul vgrf5:F, vgrf5:F, vgrf4:F
 *
 * becomes
 *
 * add vgrf4:F, vgrf1:F, vgrf2:F
 * mul vgrf5:F, vgrf5:F, vgrf4:F
 */

#include "brw_fs.h"
#include "brw_fs_live_variables.h"

static bool
is_nop_mov(const fs_inst *inst)
{
   if (inst->opcode == BRW_OPCODE_MOV) {
      return inst->dst.equals(inst->src[0]);
   }

   return false;
}

static bool
is_coalesce_candidate(const fs_inst *inst, const int *virtual_grf_sizes)
{
   if (inst->opcode != BRW_OPCODE_MOV ||
       inst->is_partial_write() ||
       inst->saturate ||
       inst->src[0].file != GRF ||
       inst->src[0].negate ||
       inst->src[0].abs ||
       !inst->src[0].is_contiguous() ||
       inst->dst.file != GRF ||
       inst->dst.type != inst->src[0].type) {
      return false;
   }

   if (virtual_grf_sizes[inst->src[0].reg] >
       virtual_grf_sizes[inst->dst.reg])
      return false;

   return true;
}

static bool
can_coalesce_vars(brw::fs_live_variables *live_intervals,
                  const exec_list *instructions, const fs_inst *inst,
                  int var_to, int var_from)
{
   if (live_intervals->vars_interfere(var_from, var_to)) {
      /* We know that the live ranges of A (var_from) and B (var_to)
       * interfere because of the ->vars_interfere() call above. If the end
       * of B's live range is after the end of A's range, then we know two
       * things:
       *  - the start of B's live range must be in A's live range (since we
       *    already know the two ranges interfere, this is the only remaining
       *    possibility)
       *  - the interference isn't of the form we're looking for (where B is
       *    entirely inside A)
       */
      if (live_intervals->end[var_to] > live_intervals->end[var_from])
         return false;

      int scan_ip = -1;

      foreach_list(n, instructions) {
         fs_inst *scan_inst = (fs_inst *)n;
         scan_ip++;

         if (scan_inst->is_control_flow())
            return false;

         if (scan_ip <= live_intervals->start[var_to])
            continue;

         if (scan_ip > live_intervals->end[var_to])
            break;

         if (scan_inst->dst.equals(inst->dst) ||
             scan_inst->dst.equals(inst->src[0]))
            return false;
      }
   }

   return true;
}

bool
fs_visitor::register_coalesce()
{
   bool progress = false;

   calculate_live_intervals();

   int src_size = 0;
   int channels_remaining = 0;
   int reg_from = -1, reg_to = -1;
   int reg_to_offset[MAX_SAMPLER_MESSAGE_SIZE];
   fs_inst *mov[MAX_SAMPLER_MESSAGE_SIZE];
   int var_to[MAX_SAMPLER_MESSAGE_SIZE];
   int var_from[MAX_SAMPLER_MESSAGE_SIZE];

   foreach_list(node, &this->instructions) {
      fs_inst *inst = (fs_inst *)node;

      if (!is_coalesce_candidate(inst, virtual_grf_sizes))
         continue;

      if (is_nop_mov(inst)) {
         inst->opcode = BRW_OPCODE_NOP;
         progress = true;
         continue;
      }

      if (reg_from != inst->src[0].reg) {
         reg_from = inst->src[0].reg;

         src_size = virtual_grf_sizes[inst->src[0].reg];
         assert(src_size <= MAX_SAMPLER_MESSAGE_SIZE);

         channels_remaining = src_size;
         memset(mov, 0, sizeof(mov));

         reg_to = inst->dst.reg;
      }

      if (reg_to != inst->dst.reg)
         continue;

      const int offset = inst->src[0].reg_offset;
      reg_to_offset[offset] = inst->dst.reg_offset;
      mov[offset] = inst;
      channels_remaining--;

      if (channels_remaining)
         continue;

      bool can_coalesce = true;
      for (int i = 0; i < src_size; i++) {
         var_to[i] = live_intervals->var_from_vgrf[reg_to] + reg_to_offset[i];
         var_from[i] = live_intervals->var_from_vgrf[reg_from] + i;

         if (!can_coalesce_vars(live_intervals, &instructions, inst,
                                var_to[i], var_from[i])) {
            can_coalesce = false;
            reg_from = -1;
            break;
         }
      }

      if (!can_coalesce)
         continue;

      progress = true;

      for (int i = 0; i < src_size; i++) {
         if (mov[i]) {
            mov[i]->opcode = BRW_OPCODE_NOP;
            mov[i]->conditional_mod = BRW_CONDITIONAL_NONE;
            mov[i]->dst = reg_undef;
            mov[i]->src[0] = reg_undef;
            mov[i]->src[1] = reg_undef;
            mov[i]->src[2] = reg_undef;
         }
      }

      foreach_list(node, &this->instructions) {
         fs_inst *scan_inst = (fs_inst *)node;

         for (int i = 0; i < src_size; i++) {
            if (mov[i]) {
               if (scan_inst->dst.file == GRF &&
                   scan_inst->dst.reg == reg_from &&
                   scan_inst->dst.reg_offset == i) {
                  scan_inst->dst.reg = reg_to;
                  scan_inst->dst.reg_offset = reg_to_offset[i];
               }
               for (int j = 0; j < 3; j++) {
                  if (scan_inst->src[j].file == GRF &&
                      scan_inst->src[j].reg == reg_from &&
                      scan_inst->src[j].reg_offset == i) {
                     scan_inst->src[j].reg = reg_to;
                     scan_inst->src[j].reg_offset = reg_to_offset[i];
                  }
               }
            }
         }
      }

      for (int i = 0; i < src_size; i++) {
         live_intervals->start[var_to[i]] =
            MIN2(live_intervals->start[var_to[i]],
                 live_intervals->start[var_from[i]]);
         live_intervals->end[var_to[i]] =
            MAX2(live_intervals->end[var_to[i]],
                 live_intervals->end[var_from[i]]);
      }
      reg_from = -1;
   }

   if (progress) {
      foreach_list_safe(node, &this->instructions) {
         fs_inst *inst = (fs_inst *)node;

         if (inst->opcode == BRW_OPCODE_NOP) {
            inst->remove();
         }
      }

      invalidate_live_intervals();
   }

   return progress;
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This is a simple application that stress-tests the crash recovery of the disk
// cache. The main application starts a copy of itself on a loop, checking the
// exit code of the child process. When the child dies in an unexpected way,
// the main application quits.

// The child application has two threads: one to exercise the cache in an
// infinite loop, and another one to asynchronously kill the process.

#include <windows.h>
#include <string>

#include "base/at_exit.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/disk_cache_test_util.h"

const int kError = -1;
const int kExpectedCrash = 1000000;

// Starts a new process.
int RunSlave(int iteration) {
  std::wstring exe;
  PathService::Get(base::FILE_EXE, &exe);

  std::wstring command = StringPrintf(L"%ls %d", exe.c_str(), iteration);

  STARTUPINFO startup_info = {0};
  startup_info.cb = sizeof(startup_info);
  PROCESS_INFORMATION process_info;

  // I really don't care about this call modifying the string.
  if (!::CreateProcess(exe.c_str(), const_cast<wchar_t*>(command.c_str()), NULL,
                       NULL, FALSE, 0, NULL, NULL, &startup_info,
                       &process_info)) {
    printf("Unable to run test\n");
    return kError;
  }

  DWORD reason = ::WaitForSingleObject(process_info.hProcess, INFINITE);

  int code;
  bool ok = ::GetExitCodeProcess(process_info.hProcess,
                                 reinterpret_cast<PDWORD>(&code)) ? true :
                                                                    false;

  ::CloseHandle(process_info.hProcess);
  ::CloseHandle(process_info.hThread);

  if (!ok) {
    printf("Unable to get return code\n");
    return kError;
  }

  return code;
}

// Main loop for the master process.
int MasterCode() {
  for (int i = 0; i < 100000; i++) {
    int ret = RunSlave(i);
    if (kExpectedCrash != ret)
      return ret;
  }

  printf("More than enough...\n");

  return 0;
}

// -----------------------------------------------------------------------

// This thread will loop forever, adding and removing entries from the cache.
// iteration is the current crash cycle, so the entries on the cache are marked
// to know which instance of the application wrote them.
void StressTheCache(int iteration) {
  int cache_size = 0x800000;  // 8MB
  std::wstring path = GetCachePath();
  path.append(L"_stress");
  disk_cache::Backend* cache = disk_cache::CreateCacheBackend(path, false,
                                                              cache_size);
  if (NULL == cache) {
    printf("Unable to initialize cache.\n");
    return;
  }
  printf("Iteration %d, initial entries: %d\n", iteration,
         cache->GetEntryCount());

  int seed = static_cast<int>(Time::Now().ToInternalValue());
  srand(seed);

  const int kNumKeys = 5000;
  const int kNumEntries = 30;
  std::string keys[kNumKeys];
  disk_cache::Entry* entries[kNumEntries] = {0};

  for (int i = 0; i < kNumKeys; i++) {
    keys[i] = GenerateKey(true);
  }

  const int kDataLen = 4000;
  char data[kDataLen];
  memset(data, 'k', kDataLen);

  for (int i = 0;; i++) {
    int slot = rand() % kNumEntries;
    int key = rand() % kNumKeys;

    if (entries[slot])
      entries[slot]->Close();

    if (!cache->OpenEntry(keys[key], &entries[slot]))
      CHECK(cache->CreateEntry(keys[key], &entries[slot]));

    sprintf_s(data, "%d %d", iteration, i);
    CHECK(kDataLen == entries[slot]->WriteData(0, 0, data, kDataLen, NULL,
                                               false));

    if (rand() % 100 > 80) {
      key = rand() % kNumKeys;
      cache->DoomEntry(keys[key]);
    }

    if (!(i % 100))
      printf("Entries: %d    \r", i);
  }
}

// We want to prevent the timer thread from killing the process while we are
// waiting for the debugger to attach.
bool g_crashing = false;

class CrashTask : public Task {
 public:
  CrashTask() {}
  ~CrashTask() {}

  virtual void Run() {
    if (g_crashing)
      return;

    if (rand() % 100 > 1) {
      printf("sweet death...\n");
      TerminateProcess(GetCurrentProcess(), kExpectedCrash);
    }
  }
};

// We leak everything here :)
bool StartCrashThread() {
  Thread* thread = new Thread("party_crasher");
  if (!thread->Start())
    return false;

  // Create a recurrent timer of 10 secs.
  int timer_delay = 10000;
  CrashTask* task = new CrashTask();
  thread->message_loop()->timer_manager()->StartTimer(timer_delay, task, true);

  return true;
}

void CrashHandler(const std::string& str) {
  g_crashing = true;
  __debugbreak();
}

// -----------------------------------------------------------------------

int main(int argc, const char* argv[]) {
  // Setup an AtExitManager so Singleton objects will be destructed.
  base::AtExitManager at_exit_manager;

  if (argc < 2)
    return MasterCode();

  logging::SetLogAssertHandler(CrashHandler);

  // Some time for the memory manager to flush stuff.
  Sleep(3000);
  MessageLoop message_loop;

  char* end;
  long int iteration = strtol(argv[1], &end, 0);

  if (!StartCrashThread()) {
    printf("failed to start thread\n");
    return kError;
  }

  StressTheCache(iteration);
  return 0;
}

<commit_msg>fix build<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This is a simple application that stress-tests the crash recovery of the disk
// cache. The main application starts a copy of itself on a loop, checking the
// exit code of the child process. When the child dies in an unexpected way,
// the main application quits.

// The child application has two threads: one to exercise the cache in an
// infinite loop, and another one to asynchronously kill the process.

#include <windows.h>
#include <string>

#include "base/at_exit.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/disk_cache_test_util.h"

const int kError = -1;
const int kExpectedCrash = 1000000;

// Starts a new process.
int RunSlave(int iteration) {
  std::wstring exe;
  PathService::Get(base::FILE_EXE, &exe);

  std::wstring command = StringPrintf(L"%ls %d", exe.c_str(), iteration);

  STARTUPINFO startup_info = {0};
  startup_info.cb = sizeof(startup_info);
  PROCESS_INFORMATION process_info;

  // I really don't care about this call modifying the string.
  if (!::CreateProcess(exe.c_str(), const_cast<wchar_t*>(command.c_str()), NULL,
                       NULL, FALSE, 0, NULL, NULL, &startup_info,
                       &process_info)) {
    printf("Unable to run test\n");
    return kError;
  }

  DWORD reason = ::WaitForSingleObject(process_info.hProcess, INFINITE);

  int code;
  bool ok = ::GetExitCodeProcess(process_info.hProcess,
                                 reinterpret_cast<PDWORD>(&code)) ? true :
                                                                    false;

  ::CloseHandle(process_info.hProcess);
  ::CloseHandle(process_info.hThread);

  if (!ok) {
    printf("Unable to get return code\n");
    return kError;
  }

  return code;
}

// Main loop for the master process.
int MasterCode() {
  for (int i = 0; i < 100000; i++) {
    int ret = RunSlave(i);
    if (kExpectedCrash != ret)
      return ret;
  }

  printf("More than enough...\n");

  return 0;
}

// -----------------------------------------------------------------------

// This thread will loop forever, adding and removing entries from the cache.
// iteration is the current crash cycle, so the entries on the cache are marked
// to know which instance of the application wrote them.
void StressTheCache(int iteration) {
  int cache_size = 0x800000;  // 8MB
  std::wstring path = GetCachePath();
  path.append(L"_stress");
  disk_cache::Backend* cache = disk_cache::CreateCacheBackend(path, false,
                                                              cache_size);
  if (NULL == cache) {
    printf("Unable to initialize cache.\n");
    return;
  }
  printf("Iteration %d, initial entries: %d\n", iteration,
         cache->GetEntryCount());

  int seed = static_cast<int>(Time::Now().ToInternalValue());
  srand(seed);

  const int kNumKeys = 5000;
  const int kNumEntries = 30;
  std::string keys[kNumKeys];
  disk_cache::Entry* entries[kNumEntries] = {0};

  for (int i = 0; i < kNumKeys; i++) {
    keys[i] = GenerateKey(true);
  }

  const int kDataLen = 4000;
  char data[kDataLen];
  memset(data, 'k', kDataLen);

  for (int i = 0;; i++) {
    int slot = rand() % kNumEntries;
    int key = rand() % kNumKeys;

    if (entries[slot])
      entries[slot]->Close();

    if (!cache->OpenEntry(keys[key], &entries[slot]))
      CHECK(cache->CreateEntry(keys[key], &entries[slot]));

    sprintf_s(data, "%d %d", iteration, i);
    CHECK(kDataLen == entries[slot]->WriteData(0, 0, data, kDataLen, NULL,
                                               false));

    if (rand() % 100 > 80) {
      key = rand() % kNumKeys;
      cache->DoomEntry(keys[key]);
    }

    if (!(i % 100))
      printf("Entries: %d    \r", i);
  }
}

// We want to prevent the timer thread from killing the process while we are
// waiting for the debugger to attach.
bool g_crashing = false;

class CrashTask : public Task {
 public:
  CrashTask() {}
  ~CrashTask() {}

  virtual void Run() {
    if (g_crashing)
      return;

    if (rand() % 100 > 1) {
      printf("sweet death...\n");
      TerminateProcess(GetCurrentProcess(), kExpectedCrash);
    }
  }
};

// We leak everything here :)
bool StartCrashThread() {
  base::Thread* thread = new base::Thread("party_crasher");
  if (!thread->Start())
    return false;

  // Create a recurrent timer of 10 secs.
  int timer_delay = 10000;
  CrashTask* task = new CrashTask();
  thread->message_loop()->timer_manager()->StartTimer(timer_delay, task, true);

  return true;
}

void CrashHandler(const std::string& str) {
  g_crashing = true;
  __debugbreak();
}

// -----------------------------------------------------------------------

int main(int argc, const char* argv[]) {
  // Setup an AtExitManager so Singleton objects will be destructed.
  base::AtExitManager at_exit_manager;

  if (argc < 2)
    return MasterCode();

  logging::SetLogAssertHandler(CrashHandler);

  // Some time for the memory manager to flush stuff.
  Sleep(3000);
  MessageLoop message_loop;

  char* end;
  long int iteration = strtol(argv[1], &end, 0);

  if (!StartCrashThread()) {
    printf("failed to start thread\n");
    return kError;
  }

  StressTheCache(iteration);
  return 0;
}

<|endoftext|>


<commit_before>/*
@version: 0.5
@author: Sudheer K. <scifi1947 at gmail.com>
@license: GNU General Public License

Based on Telepathy-SNOM with copyright notice below.
*/

/*
 * Telepathy SNOM VoIP phone connection manager
 * Copyright (C) 2006 by basyskom GmbH
 *  @author Tobias Hunger <info@basyskom.de>
 *
 * This library is free software; you can redisQObject::tribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is disQObject::tributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin SQObject::treet, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <iostream>
#include <fstream>

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>

#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMetaType>
#include <QtDBus/QDBusInterface>
#include <QDateTime>

#include "names.h"
#include "connectionmanager.h"
#include "basetypes.h"
#include "connectionmanagertypes.h"
#include "connectiontypes.h"
#include "connectioninterfacerequeststypes.h"
#include "connectioninterfacecapabilitiestypes.h"

using namespace std;

ofstream logfile;

void MyOutputHandler(QtMsgType type, const char *msg) {
    switch (type) {
        case QtDebugMsg:
            logfile << QTime::currentTime().toString().toAscii().data() << " Debug: " << msg << "\n";
            break;
        case QtCriticalMsg:
            logfile << QTime::currentTime().toString().toAscii().data() << " Critical: " << msg << "\n";
            break;
        case QtWarningMsg:
            logfile << QTime::currentTime().toString().toAscii().data() << " Warning: " << msg << "\n";
            break;
        case QtFatalMsg:
            logfile << QTime::currentTime().toString().toAscii().data() <<  " Fatal: " << msg << "\n";
            abort();
    }
}

int main(int argc, char ** argv)
{

//    logfile.open("/var/log/logfile.txt", ios::app);
//    #ifndef QT_NO_DEBUG_OUTPUT
//    qInstallMsgHandler(MyOutputHandler);
//    #endif

    QCoreApplication app(argc, argv);

    // register types:
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ParameterDefinition>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ParameterDefinitionList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ChannelInfo>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ChannelInfoList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ChannelDetails>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ChannelDetailsList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ContactCapabilities>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ContactCapabilitiesList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::CapabilityPair>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::CapabilityPairList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::CapabilityChange>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::CapabilityChangeList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::RequestableChannelClass>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::RequestableChannelClassList>();

    QDBusConnection connection = QDBusConnection::sessionBus();

    if (!connection.interface()->isServiceRegistered(cm_service_name))
    {

        // register CM on D-BUS:
        if (connection.registerService(cm_service_name)){
            qDebug(qPrintable(QObject::tr("Service %1 registered with session bus.").
                       arg(cm_service_name)));
        }
        else{
            qDebug(qPrintable(QObject::tr("Unable to register service %1 with session bus.").
                       arg(cm_service_name)));
        }

    }

    ConnectionManager connection_mgr(&app);
    if (!connection.registerObject(cm_object_path,&connection_mgr)){
        qDebug(qPrintable(QObject::tr("Unable to register VICaR connection manager at path %1 with session bus.").
                   arg(cm_object_path)));
    }

    qDebug(qPrintable(QObject::tr("Entering main loop.")));
//    logfile.close();
    return app.exec();
}
<commit_msg>save the logs somewhere<commit_after>/*
@version: 0.5
@author: Sudheer K. <scifi1947 at gmail.com>
@license: GNU General Public License

Based on Telepathy-SNOM with copyright notice below.
*/

/*
 * Telepathy SNOM VoIP phone connection manager
 * Copyright (C) 2006 by basyskom GmbH
 *  @author Tobias Hunger <info@basyskom.de>
 *
 * This library is free software; you can redisQObject::tribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is disQObject::tributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin SQObject::treet, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <iostream>
#include <fstream>

#include <QtCore>
#include <QtDBus>

#include "names.h"
#include "connectionmanager.h"
#include "basetypes.h"
#include "connectionmanagertypes.h"
#include "connectiontypes.h"
#include "connectioninterfacerequeststypes.h"
#include "connectioninterfacecapabilitiestypes.h"

using namespace std;

ofstream logfile;

void dbgHandler(QtMsgType type, const char *msg)
{
    QDateTime dt = QDateTime::currentDateTime ();
    int level = 0;

    switch (type) {
        case QtDebugMsg:
            level = 3;
            break;
        case QtWarningMsg:
            level = 2;
            break;
        case QtCriticalMsg:
            level = 1;
            break;
        case QtFatalMsg:
            level = 0;
            break;
    }

    QString strLog = QString("%1 : %2 : %3")
                     .arg(dt.toString ("yyyy-MM-dd hh:mm:ss.zzz"))
                     .arg(level)
                     .arg(msg);
    logfile << strLog.toAscii().data() << endl;
    cout << strLog.toAscii().data() << endl;

    if (QtFatalMsg == type) {
        abort ();
    }
}

int main(int argc, char ** argv)
{
    logfile.open("/var/log/qgv-tp.log", ios::app);
    qInstallMsgHandler(dbgHandler);

    QCoreApplication app(argc, argv);

    // register types:
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ParameterDefinition>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ParameterDefinitionList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ChannelInfo>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ChannelInfoList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ChannelDetails>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ChannelDetailsList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ContactCapabilities>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::ContactCapabilitiesList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::CapabilityPair>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::CapabilityPairList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::CapabilityChange>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::CapabilityChangeList>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::RequestableChannelClass>();
    qDBusRegisterMetaType<org::freedesktop::Telepathy::RequestableChannelClassList>();

    QDBusConnection connection = QDBusConnection::sessionBus();

    if (!connection.interface()->isServiceRegistered(cm_service_name))
    {

        // register CM on D-BUS:
        if (connection.registerService(cm_service_name)){
            qDebug(qPrintable(QObject::tr("Service %1 registered with session bus.")
                        .arg(cm_service_name)));
        }
        else{
            qDebug(qPrintable(QObject::tr("Unable to register service %1 with session bus.")
                        .arg(cm_service_name)));
        }

    }

    ConnectionManager connection_mgr(&app);
    if (!connection.registerObject(cm_object_path,&connection_mgr)){
        qDebug(qPrintable(QObject::tr("Unable to register VICaR connection manager at path %1 with session bus.")
                    .arg(cm_object_path)));
    }

    qDebug(qPrintable(QObject::tr("Entering main loop.")));
    int rv = app.exec();
    logfile.close();
    return rv;
}//main
<|endoftext|>


<commit_before>//===- CGSCCPassManagerTest.cpp -------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace {

class TestModuleAnalysis {
public:
  struct Result {
    Result(int Count) : FunctionCount(Count) {}
    int FunctionCount;
  };

  static void *ID() { return (void *)&PassID; }
  static StringRef name() { return "TestModuleAnalysis"; }

  TestModuleAnalysis(int &Runs) : Runs(Runs) {}

  Result run(Module &M, ModuleAnalysisManager &AM) {
    ++Runs;
    return Result(M.size());
  }

private:
  static char PassID;

  int &Runs;
};

char TestModuleAnalysis::PassID;

class TestSCCAnalysis {
public:
  struct Result {
    Result(int Count) : FunctionCount(Count) {}
    int FunctionCount;
  };

  static void *ID() { return (void *)&PassID; }
  static StringRef name() { return "TestSCCAnalysis"; }

  TestSCCAnalysis(int &Runs) : Runs(Runs) {}

  Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) {
    ++Runs;
    return Result(C.size());
  }

private:
  static char PassID;

  int &Runs;
};

char TestSCCAnalysis::PassID;

class TestFunctionAnalysis {
public:
  struct Result {
    Result(int Count) : InstructionCount(Count) {}
    int InstructionCount;
  };

  static void *ID() { return (void *)&PassID; }
  static StringRef name() { return "TestFunctionAnalysis"; }

  TestFunctionAnalysis(int &Runs) : Runs(Runs) {}

  Result run(Function &F, FunctionAnalysisManager &AM) {
    ++Runs;
    int Count = 0;
    for (Instruction &I : instructions(F)) {
      (void)I;
      ++Count;
    }
    return Result(Count);
  }

private:
  static char PassID;

  int &Runs;
};

char TestFunctionAnalysis::PassID;

class TestImmutableFunctionAnalysis {
public:
  struct Result {
    bool invalidate(Function &, const PreservedAnalyses &) { return false; }
  };

  static void *ID() { return (void *)&PassID; }
  static StringRef name() { return "TestImmutableFunctionAnalysis"; }

  TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}

  Result run(Function &F, FunctionAnalysisManager &AM) {
    ++Runs;
    return Result();
  }

private:
  static char PassID;

  int &Runs;
};

char TestImmutableFunctionAnalysis::PassID;

struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
  template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
  // We have to explicitly define all the special member functions because MSVC
  // refuses to generate them.
  LambdaSCCPass(LambdaSCCPass &&Arg) : Func(std::move(Arg.Func)) {}
  LambdaSCCPass &operator=(LambdaSCCPass &&RHS) {
    Func = std::move(RHS.Func);
    return *this;
  }

  PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
                        LazyCallGraph &CG, CGSCCUpdateResult &UR) {
    return Func(C, AM, CG, UR);
  }

  std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
                                  LazyCallGraph &, CGSCCUpdateResult &)>
      Func;
};

struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
  template <typename T> LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
  // We have to explicitly define all the special member functions because MSVC
  // refuses to generate them.
  LambdaFunctionPass(LambdaFunctionPass &&Arg) : Func(std::move(Arg.Func)) {}
  LambdaFunctionPass &operator=(LambdaFunctionPass &&RHS) {
    Func = std::move(RHS.Func);
    return *this;
  }

  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
    return Func(F, AM);
  }

  std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
};

std::unique_ptr<Module> parseIR(const char *IR) {
  // We just use a static context here. This is never called from multiple
  // threads so it is harmless no matter how it is implemented. We just need
  // the context to outlive the module which it does.
  static LLVMContext C;
  SMDiagnostic Err;
  return parseAssemblyString(IR, Err, C);
}

class CGSCCPassManagerTest : public ::testing::Test {
protected:
  LLVMContext Context;
  std::unique_ptr<Module> M;

public:
  CGSCCPassManagerTest()
      : M(parseIR("define void @f() {\n"
                  "entry:\n"
                  "  call void @g()\n"
                  "  call void @h1()\n"
                  "  ret void\n"
                  "}\n"
                  "define void @g() {\n"
                  "entry:\n"
                  "  call void @g()\n"
                  "  call void @x()\n"
                  "  ret void\n"
                  "}\n"
                  "define void @h1() {\n"
                  "entry:\n"
                  "  call void @h2()\n"
                  "  ret void\n"
                  "}\n"
                  "define void @h2() {\n"
                  "entry:\n"
                  "  call void @h3()\n"
                  "  call void @x()\n"
                  "  ret void\n"
                  "}\n"
                  "define void @h3() {\n"
                  "entry:\n"
                  "  call void @h1()\n"
                  "  ret void\n"
                  "}\n"
                  "define void @x() {\n"
                  "entry:\n"
                  "  ret void\n"
                  "}\n")) {}
};

TEST_F(CGSCCPassManagerTest, Basic) {
  FunctionAnalysisManager FAM(/*DebugLogging*/ true);
  int FunctionAnalysisRuns = 0;
  FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
  int ImmutableFunctionAnalysisRuns = 0;
  FAM.registerPass([&] {
    return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
  });

  CGSCCAnalysisManager CGAM(/*DebugLogging*/ true);
  int SCCAnalysisRuns = 0;
  CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });

  ModuleAnalysisManager MAM(/*DebugLogging*/ true);
  int ModuleAnalysisRuns = 0;
  MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
  MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });

  MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
  MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
  CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); });
  CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
  FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
  FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });

  ModulePassManager MPM(/*DebugLogging*/ true);
  MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());

  CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  int SCCPassRunCount1 = 0;
  int AnalyzedInstrCount1 = 0;
  int AnalyzedSCCFunctionCount1 = 0;
  int AnalyzedModuleFunctionCount1 = 0;
  CGPM1.addPass(
      LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
                        LazyCallGraph &CG, CGSCCUpdateResult &UR) {
        ++SCCPassRunCount1;

        const ModuleAnalysisManager &MAM =
            AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
        FunctionAnalysisManager &FAM =
            AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
        if (TestModuleAnalysis::Result *TMA =
                MAM.getCachedResult<TestModuleAnalysis>(
                    *C.begin()->getFunction().getParent()))
          AnalyzedModuleFunctionCount1 += TMA->FunctionCount;

        TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
        AnalyzedSCCFunctionCount1 += AR.FunctionCount;
        for (LazyCallGraph::Node &N : C) {
          TestFunctionAnalysis::Result &FAR =
              FAM.getResult<TestFunctionAnalysis>(N.getFunction());
          AnalyzedInstrCount1 += FAR.InstructionCount;

          // Just ensure we get the immutable results.
          (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
        }

        return PreservedAnalyses::all();
      }));

  FunctionPassManager FPM1(/*DebugLogging*/ true);
  int FunctionPassRunCount1 = 0;
  FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
    ++FunctionPassRunCount1;
    return PreservedAnalyses::all();
  }));
  CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
  MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));

  MPM.run(*M, MAM);

  EXPECT_EQ(1, ModuleAnalysisRuns);
  EXPECT_EQ(4, SCCAnalysisRuns);
  EXPECT_EQ(6, FunctionAnalysisRuns);
  EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);

  EXPECT_EQ(4, SCCPassRunCount1);
  EXPECT_EQ(14, AnalyzedInstrCount1);
  EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
  EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
}

}
<commit_msg>[PM] Add a unittest for invalidating module analyses with an SCC pass.<commit_after>//===- CGSCCPassManagerTest.cpp -------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace {

class TestModuleAnalysis {
public:
  struct Result {
    Result(int Count) : FunctionCount(Count) {}
    int FunctionCount;
  };

  static void *ID() { return (void *)&PassID; }
  static StringRef name() { return "TestModuleAnalysis"; }

  TestModuleAnalysis(int &Runs) : Runs(Runs) {}

  Result run(Module &M, ModuleAnalysisManager &AM) {
    ++Runs;
    return Result(M.size());
  }

private:
  static char PassID;

  int &Runs;
};

char TestModuleAnalysis::PassID;

class TestSCCAnalysis {
public:
  struct Result {
    Result(int Count) : FunctionCount(Count) {}
    int FunctionCount;
  };

  static void *ID() { return (void *)&PassID; }
  static StringRef name() { return "TestSCCAnalysis"; }

  TestSCCAnalysis(int &Runs) : Runs(Runs) {}

  Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) {
    ++Runs;
    return Result(C.size());
  }

private:
  static char PassID;

  int &Runs;
};

char TestSCCAnalysis::PassID;

class TestFunctionAnalysis {
public:
  struct Result {
    Result(int Count) : InstructionCount(Count) {}
    int InstructionCount;
  };

  static void *ID() { return (void *)&PassID; }
  static StringRef name() { return "TestFunctionAnalysis"; }

  TestFunctionAnalysis(int &Runs) : Runs(Runs) {}

  Result run(Function &F, FunctionAnalysisManager &AM) {
    ++Runs;
    int Count = 0;
    for (Instruction &I : instructions(F)) {
      (void)I;
      ++Count;
    }
    return Result(Count);
  }

private:
  static char PassID;

  int &Runs;
};

char TestFunctionAnalysis::PassID;

class TestImmutableFunctionAnalysis {
public:
  struct Result {
    bool invalidate(Function &, const PreservedAnalyses &) { return false; }
  };

  static void *ID() { return (void *)&PassID; }
  static StringRef name() { return "TestImmutableFunctionAnalysis"; }

  TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}

  Result run(Function &F, FunctionAnalysisManager &AM) {
    ++Runs;
    return Result();
  }

private:
  static char PassID;

  int &Runs;
};

char TestImmutableFunctionAnalysis::PassID;

struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
  template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
  // We have to explicitly define all the special member functions because MSVC
  // refuses to generate them.
  LambdaSCCPass(LambdaSCCPass &&Arg) : Func(std::move(Arg.Func)) {}
  LambdaSCCPass &operator=(LambdaSCCPass &&RHS) {
    Func = std::move(RHS.Func);
    return *this;
  }

  PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
                        LazyCallGraph &CG, CGSCCUpdateResult &UR) {
    return Func(C, AM, CG, UR);
  }

  std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
                                  LazyCallGraph &, CGSCCUpdateResult &)>
      Func;
};

struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
  template <typename T> LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
  // We have to explicitly define all the special member functions because MSVC
  // refuses to generate them.
  LambdaFunctionPass(LambdaFunctionPass &&Arg) : Func(std::move(Arg.Func)) {}
  LambdaFunctionPass &operator=(LambdaFunctionPass &&RHS) {
    Func = std::move(RHS.Func);
    return *this;
  }

  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
    return Func(F, AM);
  }

  std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
};

std::unique_ptr<Module> parseIR(const char *IR) {
  // We just use a static context here. This is never called from multiple
  // threads so it is harmless no matter how it is implemented. We just need
  // the context to outlive the module which it does.
  static LLVMContext C;
  SMDiagnostic Err;
  return parseAssemblyString(IR, Err, C);
}

class CGSCCPassManagerTest : public ::testing::Test {
protected:
  LLVMContext Context;
  std::unique_ptr<Module> M;

public:
  CGSCCPassManagerTest()
      : M(parseIR("define void @f() {\n"
                  "entry:\n"
                  "  call void @g()\n"
                  "  call void @h1()\n"
                  "  ret void\n"
                  "}\n"
                  "define void @g() {\n"
                  "entry:\n"
                  "  call void @g()\n"
                  "  call void @x()\n"
                  "  ret void\n"
                  "}\n"
                  "define void @h1() {\n"
                  "entry:\n"
                  "  call void @h2()\n"
                  "  ret void\n"
                  "}\n"
                  "define void @h2() {\n"
                  "entry:\n"
                  "  call void @h3()\n"
                  "  call void @x()\n"
                  "  ret void\n"
                  "}\n"
                  "define void @h3() {\n"
                  "entry:\n"
                  "  call void @h1()\n"
                  "  ret void\n"
                  "}\n"
                  "define void @x() {\n"
                  "entry:\n"
                  "  ret void\n"
                  "}\n")) {}
};

TEST_F(CGSCCPassManagerTest, Basic) {
  FunctionAnalysisManager FAM(/*DebugLogging*/ true);
  int FunctionAnalysisRuns = 0;
  FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
  int ImmutableFunctionAnalysisRuns = 0;
  FAM.registerPass([&] {
    return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
  });

  CGSCCAnalysisManager CGAM(/*DebugLogging*/ true);
  int SCCAnalysisRuns = 0;
  CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });

  ModuleAnalysisManager MAM(/*DebugLogging*/ true);
  int ModuleAnalysisRuns = 0;
  MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
  MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });

  MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
  MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
  CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); });
  CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
  FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
  FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });

  ModulePassManager MPM(/*DebugLogging*/ true);
  MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());

  CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  int SCCPassRunCount1 = 0;
  int AnalyzedInstrCount1 = 0;
  int AnalyzedSCCFunctionCount1 = 0;
  int AnalyzedModuleFunctionCount1 = 0;
  CGPM1.addPass(
      LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
                        LazyCallGraph &CG, CGSCCUpdateResult &UR) {
        ++SCCPassRunCount1;

        const ModuleAnalysisManager &MAM =
            AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
        FunctionAnalysisManager &FAM =
            AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
        if (TestModuleAnalysis::Result *TMA =
                MAM.getCachedResult<TestModuleAnalysis>(
                    *C.begin()->getFunction().getParent()))
          AnalyzedModuleFunctionCount1 += TMA->FunctionCount;

        TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
        AnalyzedSCCFunctionCount1 += AR.FunctionCount;
        for (LazyCallGraph::Node &N : C) {
          TestFunctionAnalysis::Result &FAR =
              FAM.getResult<TestFunctionAnalysis>(N.getFunction());
          AnalyzedInstrCount1 += FAR.InstructionCount;

          // Just ensure we get the immutable results.
          (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
        }

        return PreservedAnalyses::all();
      }));

  FunctionPassManager FPM1(/*DebugLogging*/ true);
  int FunctionPassRunCount1 = 0;
  FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
    ++FunctionPassRunCount1;
    return PreservedAnalyses::all();
  }));
  CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
  MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));

  MPM.run(*M, MAM);

  EXPECT_EQ(1, ModuleAnalysisRuns);
  EXPECT_EQ(4, SCCAnalysisRuns);
  EXPECT_EQ(6, FunctionAnalysisRuns);
  EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);

  EXPECT_EQ(4, SCCPassRunCount1);
  EXPECT_EQ(14, AnalyzedInstrCount1);
  EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
  EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
}

// Test that an SCC pass which fails to preserve a module analysis does in fact
// invalidate that module analysis.
TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
  FunctionAnalysisManager FAM(/*DebugLogging*/ true);
  CGSCCAnalysisManager CGAM(/*DebugLogging*/ true);
  ModuleAnalysisManager MAM(/*DebugLogging*/ true);
  MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
  MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
  CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); });
  CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
  FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
  FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
  MAM.registerPass([&] { return LazyCallGraphAnalysis(); });

  int ModuleAnalysisRuns = 0;
  MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });

  ModulePassManager MPM(/*DebugLogging*/ true);
  MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());

  // The first CGSCC run we preserve everything and make sure that works and
  // the module analysis is available in the second CGSCC run from the one
  // required module pass above.
  CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  int CountFoundModuleAnalysis1 = 0;
  CGPM1.addPass(
      LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
                        LazyCallGraph &CG, CGSCCUpdateResult &UR) {
        const auto &MAM =
            AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
        auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
            *C.begin()->getFunction().getParent());

        if (TMA)
          ++CountFoundModuleAnalysis1;

        return PreservedAnalyses::all();
      }));
  MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));

  // The second CGSCC run checks that the module analysis got preserved the
  // previous time and in one SCC fails to preserve it.
  CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  int CountFoundModuleAnalysis2 = 0;
  CGPM2.addPass(
      LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
                        LazyCallGraph &CG, CGSCCUpdateResult &UR) {
        const auto &MAM =
            AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
        auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
            *C.begin()->getFunction().getParent());

        if (TMA)
          ++CountFoundModuleAnalysis2;

        // Only fail to preserve analyses on one SCC and make sure that gets
        // propagated.
        return C.getName() == "(g)" ? PreservedAnalyses::none()
                                  : PreservedAnalyses::all();
      }));
  MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));

  // The third CGSCC run should fail to find a cached module analysis as it
  // should have been invalidated by the above CGSCC run.
  CGSCCPassManager CGPM3(/*DebugLogging*/ true);
  int CountFoundModuleAnalysis3 = 0;
  CGPM3.addPass(
      LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
                        LazyCallGraph &CG, CGSCCUpdateResult &UR) {
        const auto &MAM =
            AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
        auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
            *C.begin()->getFunction().getParent());

        if (TMA)
          ++CountFoundModuleAnalysis3;

        return PreservedAnalyses::none();
      }));
  MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));

  MPM.run(*M, MAM);

  EXPECT_EQ(1, ModuleAnalysisRuns);
  EXPECT_EQ(4, CountFoundModuleAnalysis1);
  EXPECT_EQ(4, CountFoundModuleAnalysis2);
  EXPECT_EQ(0, CountFoundModuleAnalysis3);
}

}
<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "HeatConductionOutflow.h"

template<>
InputParameters validParams<HeatConductionOutflow>()
{
  InputParameters params = validParams<IntegratedBC>();
  return params;
}

HeatConductionOutflow::HeatConductionOutflow(const InputParameters & parameters) :
  IntegratedBC(parameters),
  // IntegratedBCs can retrieve material properties!
  _thermal_conductivity(getMaterialProperty<Real>("thermal_conductivity"))
{}

Real
HeatConductionOutflow::computeQpResidual()
{
  return -_test[_i][_qp]*_thermal_conductivity[_qp]*_grad_u[_qp]*_normals[_qp];
}

Real
HeatConductionOutflow::computeQpJacobian()
{
  // Derivative of the residual with respect to "u"
  return -_test[_i][_qp]*_thermal_conductivity[_qp]*_grad_phi[_j][_qp]*_normals[_qp];
}
<commit_msg>Tutorial: Fix operator spacing in HeatConductionOutflow.C.<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "HeatConductionOutflow.h"

template<>
InputParameters validParams<HeatConductionOutflow>()
{
  InputParameters params = validParams<IntegratedBC>();
  return params;
}

HeatConductionOutflow::HeatConductionOutflow(const InputParameters & parameters) :
  IntegratedBC(parameters),
  // IntegratedBCs can retrieve material properties!
  _thermal_conductivity(getMaterialProperty<Real>("thermal_conductivity"))
{}

Real
HeatConductionOutflow::computeQpResidual()
{
  return -_test[_i][_qp] * _thermal_conductivity[_qp] * _grad_u[_qp] * _normals[_qp];
}

Real
HeatConductionOutflow::computeQpJacobian()
{
  // Derivative of the residual with respect to "u"
  return -_test[_i][_qp] * _thermal_conductivity[_qp] * _grad_phi[_j][_qp] * _normals[_qp];
}
<|endoftext|>


<commit_before>#include "variant/platform.hpp"

#include "hal.h"

#include "drivers/h3lis331dl.hpp"
#include "drivers/mpu9250.hpp"
#include "drivers/ms5611.hpp"
#include "drivers/ublox_neo7.hpp"
#include "variant/digital_platform.hpp"
#include "variant/i2c_platform.hpp"
#include "variant/pwm_platform.hpp"
#include "variant/spi_platform.hpp"
#include "variant/usart_platform.hpp"

// H3LIS331DL SPI configuration
static const SPIConfig H3LIS331DL_CONFIG {
  NULL,
  GPIOA,
  4,
  SPI_CR1_BR_1 | SPI_CR1_BR_0   // 42000000/2^3 = 5250000
};

// MPU9250 SPI configuration
static const SPIConfig MPU9250_CONFIG {
  NULL,
  GPIOC,
  14,
  SPI_CR1_BR_1   // 42000000/2^2 = 10500000
};

// MS5611 SPI configuration
static const SPIConfig MS5611_CONFIG {
  NULL,
  GPIOC,
  13,
  SPI_CR1_BR_1   // 42000000/2^2 = 10500000
};

Platform::Platform() {
}

template <>
H3LIS331DL& Platform::get() {
  static H3LIS331DL acc(&SPID2, &H3LIS331DL_CONFIG);
  return acc;
}

template <>
MPU9250& Platform::get() {
  static MPU9250 imu(&SPID1, &MPU9250_CONFIG);
  return imu;
}

template <>
MS5611& Platform::get() {
  static MS5611 bar(&SPID1, &MS5611_CONFIG);
  return bar;
}

template <>
UBloxNEO7& Platform::get() {
  static UBloxNEO7 gps(&SD6);
  return gps;
}

template <> Accelerometer& Platform::getIdx(int idx) {
  if (idx == 1)                           { return get<H3LIS331DL>(); }
  else                                    { return get<MPU9250>(); }
}
template <> Barometer&    Platform::get() { return get<MS5611>(); }
template <> GPS&          Platform::get() { return get<UBloxNEO7>(); }
template <> Gyroscope&    Platform::get() { return get<MPU9250>(); }
template <> Magnetometer& Platform::get() { return get<MPU9250>(); }

template <>
DigitalPlatform& Platform::get() {
  static DigitalPlatform digitalPlatform;
  return digitalPlatform;
}

template <>
I2CPlatform& Platform::get() {
  static I2CPlatform i2cPlatform;
  return i2cPlatform;
}

template <>
PWMPlatform& Platform::get() {
  static PWMPlatform pwmPlatform;
  return pwmPlatform;
}

template <>
SPIPlatform& Platform::get() {
  static SPIPlatform spiPlatform;
  return spiPlatform;
}

template <>
USARTPlatform& Platform::get() {
  static USARTPlatform usartPlatform;
  return usartPlatform;
}

void Platform::init() {
  get<DigitalPlatform>();
  get<I2CPlatform>();
  get<PWMPlatform>();
  get<SPIPlatform>();
  get<USARTPlatform>();   // Do this last so the 500ms delay hack doesn't mess with other stuff.

  // Initialize sensors
  get<H3LIS331DL>().init();
  get<MPU9250>().init();
  get<MS5611>().init();
  get<UBloxNEO7>().init();
}
<commit_msg>Use correct pin for high-g accelerometer SPI SS.<commit_after>#include "variant/platform.hpp"

#include "hal.h"

#include "drivers/h3lis331dl.hpp"
#include "drivers/mpu9250.hpp"
#include "drivers/ms5611.hpp"
#include "drivers/ublox_neo7.hpp"
#include "variant/digital_platform.hpp"
#include "variant/i2c_platform.hpp"
#include "variant/pwm_platform.hpp"
#include "variant/spi_platform.hpp"
#include "variant/usart_platform.hpp"

// H3LIS331DL SPI configuration
static const SPIConfig H3LIS331DL_CONFIG {
  NULL,
  GPIOC,
  15,
  SPI_CR1_BR_1 | SPI_CR1_BR_0   // 42000000/2^3 = 5250000
};

// MPU9250 SPI configuration
static const SPIConfig MPU9250_CONFIG {
  NULL,
  GPIOC,
  14,
  SPI_CR1_BR_1   // 42000000/2^2 = 10500000
};

// MS5611 SPI configuration
static const SPIConfig MS5611_CONFIG {
  NULL,
  GPIOC,
  13,
  SPI_CR1_BR_1   // 42000000/2^2 = 10500000
};

Platform::Platform() {
}

template <>
H3LIS331DL& Platform::get() {
  static H3LIS331DL acc(&SPID2, &H3LIS331DL_CONFIG);
  return acc;
}

template <>
MPU9250& Platform::get() {
  static MPU9250 imu(&SPID1, &MPU9250_CONFIG);
  return imu;
}

template <>
MS5611& Platform::get() {
  static MS5611 bar(&SPID1, &MS5611_CONFIG);
  return bar;
}

template <>
UBloxNEO7& Platform::get() {
  static UBloxNEO7 gps(&SD6);
  return gps;
}

template <> Accelerometer& Platform::getIdx(int idx) {
  if (idx == 1)                           { return get<H3LIS331DL>(); }
  else                                    { return get<MPU9250>(); }
}
template <> Barometer&    Platform::get() { return get<MS5611>(); }
template <> GPS&          Platform::get() { return get<UBloxNEO7>(); }
template <> Gyroscope&    Platform::get() { return get<MPU9250>(); }
template <> Magnetometer& Platform::get() { return get<MPU9250>(); }

template <>
DigitalPlatform& Platform::get() {
  static DigitalPlatform digitalPlatform;
  return digitalPlatform;
}

template <>
I2CPlatform& Platform::get() {
  static I2CPlatform i2cPlatform;
  return i2cPlatform;
}

template <>
PWMPlatform& Platform::get() {
  static PWMPlatform pwmPlatform;
  return pwmPlatform;
}

template <>
SPIPlatform& Platform::get() {
  static SPIPlatform spiPlatform;
  return spiPlatform;
}

template <>
USARTPlatform& Platform::get() {
  static USARTPlatform usartPlatform;
  return usartPlatform;
}

void Platform::init() {
  get<DigitalPlatform>();
  get<I2CPlatform>();
  get<PWMPlatform>();
  get<SPIPlatform>();
  get<USARTPlatform>();   // Do this last so the 500ms delay hack doesn't mess with other stuff.

  // Initialize sensors
  get<H3LIS331DL>().init();
  get<MPU9250>().init();
  get<MS5611>().init();
  get<UBloxNEO7>().init();
}
<|endoftext|>


<commit_before>#ifndef CONTAINERS_ITERATORS_HPP_
#define CONTAINERS_ITERATORS_HPP_

#include <algorithm>
#include <functional>
#include <queue>
#include <set>
#include <vector>

#include "utils.hpp"
#include <boost/function.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>

template <typename T>
struct one_way_iterator_t {
    virtual ~one_way_iterator_t() { }
    virtual typename boost::optional<T> next() = 0; // next() can block until it can read the next value
    virtual void prefetch() = 0;    // Fetch all the necessary data to be able to give the next value without blocking.
                                    // prefetch() is assumed to be asynchronous. Thus if next() is called before the data
                                    // is available, next() can still block.
};

template <class T, class U>
struct transform_iterator_t : public one_way_iterator_t<U> {
    transform_iterator_t(const boost::function<U(T&)>& _func, one_way_iterator_t<T> *_ownee) : func(_func), ownee(_ownee) { }
    virtual ~transform_iterator_t() {
        delete ownee;
    }
    virtual typename boost::optional<U> next() {
        boost::optional<T> value = ownee->next();
        if (!value) {
            return boost::none;
        } else {
            return boost::make_optional(func(value.get()));
        }
    }
    void prefetch() {
        ownee->prefetch();
    }

    boost::function<U(T&)> func;
    one_way_iterator_t<T> *ownee;
};

template <class T>
struct filter_iterator_t : public one_way_iterator_t<T> {
    filter_iterator_t(const boost::function<bool(T&)>& _predicate, one_way_iterator_t<T> *_ownee) : predicate(_predicate), ownee(_ownee) { }
    virtual ~filter_iterator_t() {
        delete ownee;
    }
    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                return boost::none;
            } else {
                if (predicate(value.get())) {
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // Unfortunately we don't feel like really implementing this
        // function right now.  It would require running the filter
        // operation on return values, consuming ahead into the
        // iterator.  Also some other one_way_iterator_t
        // implementations blow this off, so why not us.
        ownee->prefetch();
    }

    boost::function<bool(T&)> predicate;
    one_way_iterator_t<T> *ownee;
};

template <typename F, typename S, typename Cmp = std::less<F> >
struct first_greater {
    typedef F first_argument_type;
    typedef S second_argument_type;
    bool operator()(std::pair<F, S> l, std::pair<F, S> r) {
        return Cmp()(r.first, l.first);
    }
};

template <typename T, typename Cmp = std::less<T> >
class merge_ordered_data_iterator_t : public one_way_iterator_t<T> {
public:
    typedef boost::shared_ptr<one_way_iterator_t<T> > mergee_t;

    merge_ordered_data_iterator_t() : mergees(), next_to_pop_from(),
        merge_heap(first_greater<T, mergee_t, Cmp>(), std::vector<std::pair<T, mergee_t> >()) { }

    virtual ~merge_ordered_data_iterator_t() {
        done();
    }

    void add_mergee(mergee_t mergee) {
        rassert(!next_to_pop_from.get());
        mergees.insert(mergee);
    }

    void add_mergee(one_way_iterator_t<T> *mergee) {
        boost::shared_ptr<one_way_iterator_t<T> > _mergee(mergee);
        add_mergee(_mergee);
    }

    typename boost::optional<T> next() {
        // if we are getting the first element, we have to request the data from all of the mergees
        if (!next_to_pop_from.get()) {
            prefetch();
            for (typename std::set<mergee_t>::iterator it = mergees.begin(); it != mergees.end();) {
                mergee_t mergee = *it;
                typename boost::optional<T> mergee_next = mergee->next();
                if (mergee_next) {
                    merge_heap.push(std::make_pair(mergee_next.get(), mergee));
                    it++;
                } else {
                    mergee.reset();          // nothing more in this iterator, delete it
                    mergees.erase(it++);    // Note: this increments the iterator, erases the element
                                            // at the old iterator position, and then updates the 'it' value
                }
            }
        } else {
            typename boost::optional<T> next_val = next_to_pop_from->next();
            if (next_val) {
                merge_heap.push(std::make_pair(next_val.get(), next_to_pop_from));
            } else {
                mergees.erase(next_to_pop_from);
                next_to_pop_from.reset();    // relinquish our hold
            }
        }
        if (merge_heap.size() == 0) {
            done();
            return boost::none;
        }

        std::pair<T, mergee_t> top = merge_heap.top();
        merge_heap.pop();
        next_to_pop_from = top.second;

        // issue the async prefetch, so that we don't need to block on next has_next/next call
        next_to_pop_from->prefetch();
        return boost::make_optional(top.first);
    }
    void prefetch() {
        typename std::set<mergee_t>::iterator it;
        for (it = mergees.begin(); it != mergees.end(); it++) {
            (*it)->prefetch();
        }
    }
private:
    void done() {
        mergees.clear();
    }
    std::set<mergee_t> mergees;
    mergee_t next_to_pop_from;
    typename std::priority_queue<std::pair<T, mergee_t>, std::vector<std::pair<T, mergee_t> >, first_greater<T, mergee_t, Cmp> > merge_heap;

};

/*
unique_iterator_t removes duplicates. It requires the input iterator to be sorted.
T has to implement operator==().

Note: Union of sets can be implemented as a unque iterator around a merge iterator.
*/
template <class T>
class unique_filter_iterator_t : public one_way_iterator_t<T> {
public:
    explicit unique_filter_iterator_t(one_way_iterator_t<T> *_ownee) : previous(boost::none), ownee(_ownee) { }
    virtual ~unique_filter_iterator_t() {
        delete ownee;
    }
    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                previous = value;
                return boost::none;
            } else {
                // Is this element different from what we had before?
                if (!previous || !(previous.get() == value.get())) {
                    previous = value;
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // TODO: Should we implement this?
        ownee->prefetch();
    }

private:
    boost::optional<T> previous;
    one_way_iterator_t<T> *ownee;
};

/* repetition_filter_iterator_t produces an element whenever it was repeated
n_repetitions times in the input iterator. T has to implement operator==().
If a element is repeated more than n_repetitions times, repetition_filter_iterator_t
will output the element once per n_repetitions repetitions.

Note: Intersection of sets can be implemented as a repetition iterator around a merge iterator,
 where n_repetitions must be set to the number of input sets. This works as
 long as the input iterators are sorted and don't produce any element more than once.
 */
template <class T>
class repetition_filter_iterator_t : public one_way_iterator_t<T> {
public:
    repetition_filter_iterator_t(one_way_iterator_t<T> *_ownee, int _n_repetitions) : previous(boost::none), previous_repetitions(0), ownee(_ownee), n_repetitions(_n_repetitions) {
        rassert(n_repetitions > 0);
    }
    virtual ~repetition_filter_iterator_t() {
        delete ownee;
    }
    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                previous = value;
                previous_repetitions = 0;
                return boost::none;
            } else {
                // Is this element different from what we had before?
                if (!previous || !(previous.get() == value.get())) {
                    // Different, start over
                    previous_repetitions = 1;
                    previous = value;
                } else {
                    // The same, increment counter
                    ++previous_repetitions;
                }

                // Have we got enough repetitions?
                rassert(previous_repetitions <= n_repetitions);
                if (previous_repetitions == n_repetitions) {
                    previous_repetitions = 0;
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // TODO: Should we implement this?
        ownee->prefetch();
    }

private:
    boost::optional<T> previous;
    int previous_repetitions;
    one_way_iterator_t<T> *ownee;
    int n_repetitions;
};

/*
 diff_filter_iterator_t implements set difference semantics. It's output
 are all the keys from ownee_left that are not in ownee_right, assuming
 that they are both sorted. T has to implement operator==() and operator<().
*/
// TODO / WARNING: As of Jul 28th, this has not been thoroughly
// tested. (daniel) If you use this and stuff fails, consider
// diff_filter_iterator_t to be potentially faulty.
template <class T>
class diff_filter_iterator_t : public one_way_iterator_t<T> {
public:
    diff_filter_iterator_t(one_way_iterator_t<T> *_ownee_left, one_way_iterator_t<T> *_ownee_right) : ownee_left(_ownee_left), ownee_right(_ownee_right), prefetched_right(boost::none) { }
    virtual ~diff_filter_iterator_t() {
        delete ownee_left;
        delete ownee_right;
    }
    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee_left->next();
            if (!value) {
                return boost::none;
            } else {
                // Is this element the same as prefetched_right?
                if (prefetched_right && prefetched_right.get() == value.get()) {
                    // It is, skip value.
                } else {
                    // Fetch new elements from ownee_right until they pass value
                    if (!prefetched_right || prefetched_right.get() < value.get()) {
                        do {
                            prefetched_right = ownee_right->next();
                        } while (prefetched_right && prefetched_right.get() < value.get());
                    }

                    // Now check again...
                    if (prefetched_right && prefetched_right.get() == value.get()) {
                        // Ok, it's the same as value. Skip value.
                    } else {
                        // no element like value in prefetched_right, return value
                        return value;
                    }
                }
            }
        }
    }
    void prefetch() {
        // TODO: Should we implement this?
        ownee_left->prefetch();
        ownee_right->prefetch();
    }

private:
    one_way_iterator_t<T> *ownee_left;
    one_way_iterator_t<T> *ownee_right;
    boost::optional<T> prefetched_right;
};

#endif /* CONTAINERS_ITERATORS_HPP_ */
<commit_msg>Removed diff_filter_iterator_t, which was unused, for a long time.  And made iterators use non-manual memory management.<commit_after>#ifndef CONTAINERS_ITERATORS_HPP_
#define CONTAINERS_ITERATORS_HPP_

#include <algorithm>
#include <functional>
#include <queue>
#include <set>
#include <vector>

#include "utils.hpp"
#include <boost/function.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>

#include "containers/scoped.hpp"

template <typename T>
struct one_way_iterator_t {
    virtual ~one_way_iterator_t() { }
    virtual typename boost::optional<T> next() = 0; // next() can block until it can read the next value
    virtual void prefetch() = 0;    // Fetch all the necessary data to be able to give the next value without blocking.
                                    // prefetch() is assumed to be asynchronous. Thus if next() is called before the data
                                    // is available, next() can still block.
};

template <class T, class U>
struct transform_iterator_t : public one_way_iterator_t<U> {
    transform_iterator_t(const boost::function<U(T&)>& _func, one_way_iterator_t<T> *_ownee) : func(_func), ownee(_ownee) { }
    virtual ~transform_iterator_t() { }

    virtual typename boost::optional<U> next() {
        boost::optional<T> value = ownee->next();
        if (!value) {
            return boost::none;
        } else {
            return boost::make_optional(func(value.get()));
        }
    }
    void prefetch() {
        ownee->prefetch();
    }

    boost::function<U(T&)> func;
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
};

template <class T>
struct filter_iterator_t : public one_way_iterator_t<T> {
    filter_iterator_t(const boost::function<bool(T&)>& _predicate, one_way_iterator_t<T> *_ownee) : predicate(_predicate), ownee(_ownee) { }
    virtual ~filter_iterator_t() { }

    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                return boost::none;
            } else {
                if (predicate(value.get())) {
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // Unfortunately we don't feel like really implementing this
        // function right now.  It would require running the filter
        // operation on return values, consuming ahead into the
        // iterator.  Also some other one_way_iterator_t
        // implementations blow this off, so why not us.
        ownee->prefetch();
    }

    boost::function<bool(T&)> predicate;
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
};

template <typename F, typename S, typename Cmp = std::less<F> >
struct first_greater {
    typedef F first_argument_type;
    typedef S second_argument_type;
    bool operator()(std::pair<F, S> l, std::pair<F, S> r) {
        return Cmp()(r.first, l.first);
    }
};

template <typename T, typename Cmp = std::less<T> >
class merge_ordered_data_iterator_t : public one_way_iterator_t<T> {
public:
    typedef boost::shared_ptr<one_way_iterator_t<T> > mergee_t;

    merge_ordered_data_iterator_t() : mergees(), next_to_pop_from(),
        merge_heap(first_greater<T, mergee_t, Cmp>(), std::vector<std::pair<T, mergee_t> >()) { }

    virtual ~merge_ordered_data_iterator_t() {
        done();
    }

    void add_mergee(mergee_t mergee) {
        rassert(!next_to_pop_from.get());
        mergees.insert(mergee);
    }

    void add_mergee(one_way_iterator_t<T> *mergee) {
        boost::shared_ptr<one_way_iterator_t<T> > _mergee(mergee);
        add_mergee(_mergee);
    }

    typename boost::optional<T> next() {
        // if we are getting the first element, we have to request the data from all of the mergees
        if (!next_to_pop_from.get()) {
            prefetch();
            for (typename std::set<mergee_t>::iterator it = mergees.begin(); it != mergees.end();) {
                mergee_t mergee = *it;
                typename boost::optional<T> mergee_next = mergee->next();
                if (mergee_next) {
                    merge_heap.push(std::make_pair(mergee_next.get(), mergee));
                    it++;
                } else {
                    mergee.reset();          // nothing more in this iterator, delete it
                    mergees.erase(it++);    // Note: this increments the iterator, erases the element
                                            // at the old iterator position, and then updates the 'it' value
                }
            }
        } else {
            typename boost::optional<T> next_val = next_to_pop_from->next();
            if (next_val) {
                merge_heap.push(std::make_pair(next_val.get(), next_to_pop_from));
            } else {
                mergees.erase(next_to_pop_from);
                next_to_pop_from.reset();    // relinquish our hold
            }
        }
        if (merge_heap.size() == 0) {
            done();
            return boost::none;
        }

        std::pair<T, mergee_t> top = merge_heap.top();
        merge_heap.pop();
        next_to_pop_from = top.second;

        // issue the async prefetch, so that we don't need to block on next has_next/next call
        next_to_pop_from->prefetch();
        return boost::make_optional(top.first);
    }
    void prefetch() {
        typename std::set<mergee_t>::iterator it;
        for (it = mergees.begin(); it != mergees.end(); it++) {
            (*it)->prefetch();
        }
    }
private:
    void done() {
        mergees.clear();
    }
    std::set<mergee_t> mergees;
    mergee_t next_to_pop_from;
    typename std::priority_queue<std::pair<T, mergee_t>, std::vector<std::pair<T, mergee_t> >, first_greater<T, mergee_t, Cmp> > merge_heap;

};

/*
unique_iterator_t removes duplicates. It requires the input iterator to be sorted.
T has to implement operator==().

Note: Union of sets can be implemented as a unque iterator around a merge iterator.
*/
template <class T>
class unique_filter_iterator_t : public one_way_iterator_t<T> {
public:
    explicit unique_filter_iterator_t(one_way_iterator_t<T> *_ownee) : previous(boost::none), ownee(_ownee) { }
    virtual ~unique_filter_iterator_t() {
        delete ownee;
    }
    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                previous = value;
                return boost::none;
            } else {
                // Is this element different from what we had before?
                if (!previous || !(previous.get() == value.get())) {
                    previous = value;
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // TODO: Should we implement this?
        ownee->prefetch();
    }

private:
    boost::optional<T> previous;
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
};

/* repetition_filter_iterator_t produces an element whenever it was repeated
n_repetitions times in the input iterator. T has to implement operator==().
If a element is repeated more than n_repetitions times, repetition_filter_iterator_t
will output the element once per n_repetitions repetitions.

Note: Intersection of sets can be implemented as a repetition iterator around a merge iterator,
 where n_repetitions must be set to the number of input sets. This works as
 long as the input iterators are sorted and don't produce any element more than once.
 */
template <class T>
class repetition_filter_iterator_t : public one_way_iterator_t<T> {
public:
    repetition_filter_iterator_t(one_way_iterator_t<T> *_ownee, int _n_repetitions) : previous(boost::none), previous_repetitions(0), ownee(_ownee), n_repetitions(_n_repetitions) {
        rassert(n_repetitions > 0);
    }
    virtual ~repetition_filter_iterator_t() { }

    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                previous = value;
                previous_repetitions = 0;
                return boost::none;
            } else {
                // Is this element different from what we had before?
                if (!previous || !(previous.get() == value.get())) {
                    // Different, start over
                    previous_repetitions = 1;
                    previous = value;
                } else {
                    // The same, increment counter
                    ++previous_repetitions;
                }

                // Have we got enough repetitions?
                rassert(previous_repetitions <= n_repetitions);
                if (previous_repetitions == n_repetitions) {
                    previous_repetitions = 0;
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // TODO: Should we implement this?
        ownee->prefetch();
    }

private:
    boost::optional<T> previous;
    int previous_repetitions;
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
    int n_repetitions;
};

#endif /* CONTAINERS_ITERATORS_HPP_ */
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "DicomView.h"

#include "org_mitk_example_gui_customviewer_views_Activator.h"

#include "mitkIDataStorageService.h"
#include "mitkDicomSeriesReader.h"

#include <berryIWorkbench.h>
#include <berryIWorkbenchWindow.h>
#include <berryIWorkbenchPage.h>

const std::string DicomView::VIEW_ID = "org.mitk.customviewer.views.dicomview";

DicomView::DicomView()
  : m_Parent(0)
{
}

DicomView::~DicomView()
{
}

// //! [DicomViewCreatePartControl]
void DicomView::CreateQtPartControl(QWidget *parent)
{
  // create GUI widgets
  m_Parent = parent;
  m_Controls.setupUi(parent);

  //remove unused widgets
  QPushButton* downloadButton = parent->findChild<QPushButton*>("downloadButton");
  downloadButton->setVisible(false);
  QDockWidget* searchWidget = parent->findChild<QDockWidget*>("ExternalSearchDockWidget");
  searchWidget->setVisible(false);

  connect(m_Controls.importButton, SIGNAL(clicked()), m_Controls.widget, SLOT(OnFolderCDImport()));
  connect(m_Controls.widget, SIGNAL(SignalDicomToDataManager(const QStringList&)), this, SLOT(AddDataNodeFromDICOM(const QStringList&)));

  m_Parent->setEnabled(true);
}
// //! [DicomViewCreatePartControl]

// //! [DicomViewCreateAddDataNodeInformation]
void DicomView::AddDataNodeFromDICOM(const QStringList& Properties)
{
  QString seriesUID = Properties.at(3);
  QString path = Properties.at(5);
// //! [DicomViewCreateAddDataNodeInformation]
// //! [DicomViewCreateAddDataNodeLoadSeries]
  mitk::DicomSeriesReader::StringContainer seriesToLoad;
  std::size_t found;

  mitk::DicomSeriesReader::FileNamesGrouping dicomSeriesMap = mitk::DicomSeriesReader::GetSeries(path.toStdString(),false);
  mitk::DicomSeriesReader::FileNamesGrouping::const_iterator qualifiedSeriesInstanceUIDIterator;

  for(qualifiedSeriesInstanceUIDIterator = dicomSeriesMap.begin();
      qualifiedSeriesInstanceUIDIterator != dicomSeriesMap.end();
      ++qualifiedSeriesInstanceUIDIterator)
  {
      found = qualifiedSeriesInstanceUIDIterator->second.GetSeriesInstanceUID().find(seriesUID.toStdString());
      if(found != std::string::npos)
      {
          seriesToLoad = qualifiedSeriesInstanceUIDIterator->second.GetFilenames();
      }
  }

  mitk::DataNode::Pointer node = mitk::DicomSeriesReader::LoadDicomSeries(seriesToLoad);
// //! [DicomViewCreateAddDataNodeLoadSeries]
  if (node.IsNull())
  {
      MITK_ERROR << "Could not load series: " << seriesUID.toStdString();
  }
  else
  {
// //! [DicomViewCreateAddDataNode]
      this->GetDataStorage()->Add(node);
// //! [DicomViewCreateAddDataNode]
      mitk::RenderingManager::GetInstance()->SetDataStorage(this->GetDataStorage());
      mitk::RenderingManager::GetInstance()->RequestUpdateAll();

// //! [DicomViewCreateAddDataNodeActivatePersp]
      berry::IWorkbenchWindow::Pointer window = this->GetSite()->GetWorkbenchWindow();
      std::string perspectiveId = "org.mitk.example.viewerperspective";
      window->GetWorkbench()->ShowPerspective(perspectiveId, berry::IWorkbenchWindow::Pointer(window));
// //! [DicomViewCreateAddDataNodeActivatePersp]
  }
}

void DicomView::SetFocus ()
{
}
<commit_msg>COMP: Added missing include<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "DicomView.h"

#include "org_mitk_example_gui_customviewer_views_Activator.h"

#include "mitkIDataStorageService.h"
#include "mitkDicomSeriesReader.h"

#include <berryIWorkbench.h>
#include <berryIWorkbenchWindow.h>
#include <berryIWorkbenchPage.h>

#include "QDockWidget"

const std::string DicomView::VIEW_ID = "org.mitk.customviewer.views.dicomview";

DicomView::DicomView()
  : m_Parent(0)
{
}

DicomView::~DicomView()
{
}

// //! [DicomViewCreatePartControl]
void DicomView::CreateQtPartControl(QWidget *parent)
{
  // create GUI widgets
  m_Parent = parent;
  m_Controls.setupUi(parent);

  //remove unused widgets
  QPushButton* downloadButton = parent->findChild<QPushButton*>("downloadButton");
  downloadButton->setVisible(false);
  QDockWidget* searchWidget = parent->findChild<QDockWidget*>("ExternalSearchDockWidget");
  searchWidget->setVisible(false);

  connect(m_Controls.importButton, SIGNAL(clicked()), m_Controls.widget, SLOT(OnFolderCDImport()));
  connect(m_Controls.widget, SIGNAL(SignalDicomToDataManager(const QStringList&)), this, SLOT(AddDataNodeFromDICOM(const QStringList&)));

  m_Parent->setEnabled(true);
}
// //! [DicomViewCreatePartControl]

// //! [DicomViewCreateAddDataNodeInformation]
void DicomView::AddDataNodeFromDICOM(const QStringList& Properties)
{
  QString seriesUID = Properties.at(3);
  QString path = Properties.at(5);
// //! [DicomViewCreateAddDataNodeInformation]
// //! [DicomViewCreateAddDataNodeLoadSeries]
  mitk::DicomSeriesReader::StringContainer seriesToLoad;
  std::size_t found;

  mitk::DicomSeriesReader::FileNamesGrouping dicomSeriesMap = mitk::DicomSeriesReader::GetSeries(path.toStdString(),false);
  mitk::DicomSeriesReader::FileNamesGrouping::const_iterator qualifiedSeriesInstanceUIDIterator;

  for(qualifiedSeriesInstanceUIDIterator = dicomSeriesMap.begin();
      qualifiedSeriesInstanceUIDIterator != dicomSeriesMap.end();
      ++qualifiedSeriesInstanceUIDIterator)
  {
      found = qualifiedSeriesInstanceUIDIterator->second.GetSeriesInstanceUID().find(seriesUID.toStdString());
      if(found != std::string::npos)
      {
          seriesToLoad = qualifiedSeriesInstanceUIDIterator->second.GetFilenames();
      }
  }

  mitk::DataNode::Pointer node = mitk::DicomSeriesReader::LoadDicomSeries(seriesToLoad);
// //! [DicomViewCreateAddDataNodeLoadSeries]
  if (node.IsNull())
  {
      MITK_ERROR << "Could not load series: " << seriesUID.toStdString();
  }
  else
  {
// //! [DicomViewCreateAddDataNode]
      this->GetDataStorage()->Add(node);
// //! [DicomViewCreateAddDataNode]
      mitk::RenderingManager::GetInstance()->SetDataStorage(this->GetDataStorage());
      mitk::RenderingManager::GetInstance()->RequestUpdateAll();

// //! [DicomViewCreateAddDataNodeActivatePersp]
      berry::IWorkbenchWindow::Pointer window = this->GetSite()->GetWorkbenchWindow();
      std::string perspectiveId = "org.mitk.example.viewerperspective";
      window->GetWorkbench()->ShowPerspective(perspectiveId, berry::IWorkbenchWindow::Pointer(window));
// //! [DicomViewCreateAddDataNodeActivatePersp]
  }
}

void DicomView::SetFocus ()
{
}
<|endoftext|>