<commit_before>// Copyright (c) 2017 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <chrono>
#include <functional>
#include <iostream>
#include <set>
#include <mutex>
#include <thread>
#include <Chaos/Types.h>
#include <Chaos/Logging/Logging.h>
#include "object.h"
#include "parallel_sweep.h"

namespace gc {

class Worker {
  int order_{};
  bool stop_{};
  bool run_tracing_{};
  std::mutex mutex_;
  std::unique_ptr<std::thread> thread_;
  std::vector<BaseObject*> roots_;
  std::vector<BaseObject*> mark_objects_;

  friend class ParallelSweep;

  void acquire_work(void) {
    if (!mark_objects_.empty())
      return;

    {
      std::unique_lock<std::mutex> g(mutex_);
      transfer(roots_.size() / 2, mark_objects_);
    }

    if (mark_objects_.empty())
      ParallelSweep::get_instance().acquire_work(order_, mark_objects_);
  }

  void perform_work(void) {
    while (!mark_objects_.empty()) {
      auto* obj = mark_objects_.back();
      mark_objects_.pop_back();

      obj->set_marked();
      if (obj->is_pair()) {
        auto append_fn = [this](BaseObject* o) {
          if (o != nullptr && !o->is_marked()) {
            o->set_marked(); mark_objects_.push_back(o);
          }
        };

        append_fn(Chaos::down_cast<Pair*>(obj)->first());
        append_fn(Chaos::down_cast<Pair*>(obj)->second());
      }
    }
  }

  void generate_work(void) {
    if (roots_.empty()) {
      std::unique_lock<std::mutex> g(mutex_);
      std::copy(mark_objects_.begin(),
          mark_objects_.end(), std::back_inserter(roots_));
      mark_objects_.clear();
    }
  }

  void worker_routine(void) {
    while (!stop_) {
      if (run_tracing_) {
        acquire_work();
        perform_work();
        generate_work();
      }
      if (run_tracing_ && mark_objects_.empty())
        run_tracing_ = false;

      std::this_thread::sleep_for(std::chrono::microseconds(10));
    }
  }
public:
  Worker(int order)
    : order_(order)
    , thread_(new std::thread(std::bind(&Worker::worker_routine, this)))
  {}
  ~Worker(void) { stop(); thread_->join(); }
  void stop(void) { stop_ = true; }
  void run_tracing(void) { run_tracing_ = true; }
  void put_in(BaseObject* obj) { roots_.push_back(obj); }

  BaseObject* fetch_out(void) {
    auto* obj = roots_.back();
    roots_.pop_back();
    return obj;
  }

  void transfer(std::size_t n, std::vector<BaseObject*>& objects) {
    std::copy_n(roots_.begin(), n, std::back_inserter(objects));
    roots_.erase(roots_.begin(), roots_.begin() + n);
  }
};

ParallelSweep::ParallelSweep(void) {
  start_workers();
}

ParallelSweep::~ParallelSweep(void) {
  stop_workers();
}

void ParallelSweep::start_workers(int nworkers) {
  nworkers_ = nworkers;
  for (auto i = 0; i < nworkers_; ++i)
    workers_.emplace_back(new Worker(i));
}

void ParallelSweep::stop_workers(void) {
  for (auto i = 0; i < nworkers_; ++i)
    workers_[i]->stop();
}

int ParallelSweep::put_in_order(void) {
  int r = order_;
  order_ = (order_ + 1) % nworkers_;
  return r;
}

int ParallelSweep::fetch_out_order(void) {
  order_ = (order_ - 1 + nworkers_) % nworkers_;
  return order_;
}

void ParallelSweep::sweep(void) {
  for (auto it = objects_.begin(); it != objects_.end();) {
    if (!(*it)->is_marked()) {
      delete *it;
      objects_.erase(it++);
    }
    else {
      (*it)->unset_marked();
      ++it;
    }
  }
}

ParallelSweep& ParallelSweep::get_instance(void) {
  static ParallelSweep ins;
  return ins;
}

void ParallelSweep::acquire_work(
    int own_order, std::vector<BaseObject*>& objects) {
  for (auto i = 0; i < nworkers_; ++i) {
    if (i == own_order)
      continue;

    if (workers_[i]->mutex_.try_lock()) {
      workers_[i]->transfer(workers_[i]->roots_.size() / 2, objects);
      workers_[i]->mutex_.unlock();
      break;
    }
  }
}

void ParallelSweep::collect(void) {
  auto old_count = objects_.size();

  for (auto i = 0; i < nworkers_; ++i)
    workers_[i]->run_tracing();

  std::set<int> finished;
  while (true) {
    for (auto i = 0; i < nworkers_; ++i) {
      if (!workers_[i]->run_tracing_)
        finished.insert(i);
    }

    if (finished.size() == static_cast<std::size_t>(nworkers_))
      break;
    std::this_thread::sleep_for(std::chrono::microseconds(10));
  }
  finished.clear();

  sweep();

  std::cout
    << "[" << old_count - objects_.size() << "] objects collected, "
    << "[" << objects_.size() << "] objects remaining." << std::endl;
}

BaseObject* ParallelSweep::put_in(int value) {
  if (objects_.size() >= kMaxObjects)
    collect();

  auto* obj = new Int();
  obj->set_value(value);

  auto order = put_in_order();
  workers_[order]->put_in(obj);
  objects_.push_back(obj);

  return obj;
}

BaseObject* ParallelSweep::put_in(BaseObject* first, BaseObject* second) {
  if (objects_.size() >= kMaxObjects)
    collect();

  auto* obj = new Pair();
  if (first != nullptr)
    obj->set_first(first);
  if (second != nullptr)
    obj->set_second(second);

  auto order = put_in_order();
  workers_[order]->put_in(obj);
  objects_.push_back(obj);

  return obj;
}

BaseObject* ParallelSweep::fetch_out(void) {
  auto order = fetch_out_order();
  return workers_[order]->fetch_out();
}

}
<commit_msg>:bug: fix(ParallelSweep): fixed including error<commit_after>// Copyright (c) 2017 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <chrono>
#include <functional>
#include <iostream>
#include <iterator>
#include <set>
#include <mutex>
#include <thread>
#include <Chaos/Types.h>
#include "object.h"
#include "parallel_sweep.h"

namespace gc {

class Worker {
  int order_{};
  bool stop_{};
  bool run_tracing_{};
  std::mutex mutex_;
  std::unique_ptr<std::thread> thread_;
  std::vector<BaseObject*> roots_;
  std::vector<BaseObject*> mark_objects_;

  friend class ParallelSweep;

  void acquire_work(void) {
    if (!mark_objects_.empty())
      return;

    {
      std::unique_lock<std::mutex> g(mutex_);
      transfer(roots_.size() / 2, mark_objects_);
    }

    if (mark_objects_.empty())
      ParallelSweep::get_instance().acquire_work(order_, mark_objects_);
  }

  void perform_work(void) {
    while (!mark_objects_.empty()) {
      auto* obj = mark_objects_.back();
      mark_objects_.pop_back();

      obj->set_marked();
      if (obj->is_pair()) {
        auto append_fn = [this](BaseObject* o) {
          if (o != nullptr && !o->is_marked()) {
            o->set_marked(); mark_objects_.push_back(o);
          }
        };

        append_fn(Chaos::down_cast<Pair*>(obj)->first());
        append_fn(Chaos::down_cast<Pair*>(obj)->second());
      }
    }
  }

  void generate_work(void) {
    if (roots_.empty()) {
      std::unique_lock<std::mutex> g(mutex_);
      std::copy(mark_objects_.begin(),
          mark_objects_.end(), std::back_inserter(roots_));
      mark_objects_.clear();
    }
  }

  void worker_routine(void) {
    while (!stop_) {
      if (run_tracing_) {
        acquire_work();
        perform_work();
        generate_work();
      }
      if (run_tracing_ && mark_objects_.empty())
        run_tracing_ = false;

      std::this_thread::sleep_for(std::chrono::microseconds(10));
    }
  }
public:
  Worker(int order)
    : order_(order)
    , thread_(new std::thread(std::bind(&Worker::worker_routine, this)))
  {}
  ~Worker(void) { stop(); thread_->join(); }
  void stop(void) { stop_ = true; }
  void run_tracing(void) { run_tracing_ = true; }
  void put_in(BaseObject* obj) { roots_.push_back(obj); }

  BaseObject* fetch_out(void) {
    auto* obj = roots_.back();
    roots_.pop_back();
    return obj;
  }

  void transfer(std::size_t n, std::vector<BaseObject*>& objects) {
    std::copy_n(roots_.begin(), n, std::back_inserter(objects));
    roots_.erase(roots_.begin(), roots_.begin() + n);
  }
};

ParallelSweep::ParallelSweep(void) {
  start_workers();
}

ParallelSweep::~ParallelSweep(void) {
  stop_workers();
}

void ParallelSweep::start_workers(int nworkers) {
  nworkers_ = nworkers;
  for (auto i = 0; i < nworkers_; ++i)
    workers_.emplace_back(new Worker(i));
}

void ParallelSweep::stop_workers(void) {
  for (auto i = 0; i < nworkers_; ++i)
    workers_[i]->stop();
}

int ParallelSweep::put_in_order(void) {
  int r = order_;
  order_ = (order_ + 1) % nworkers_;
  return r;
}

int ParallelSweep::fetch_out_order(void) {
  order_ = (order_ - 1 + nworkers_) % nworkers_;
  return order_;
}

void ParallelSweep::sweep(void) {
  for (auto it = objects_.begin(); it != objects_.end();) {
    if (!(*it)->is_marked()) {
      delete *it;
      objects_.erase(it++);
    }
    else {
      (*it)->unset_marked();
      ++it;
    }
  }
}

ParallelSweep& ParallelSweep::get_instance(void) {
  static ParallelSweep ins;
  return ins;
}

void ParallelSweep::acquire_work(
    int own_order, std::vector<BaseObject*>& objects) {
  for (auto i = 0; i < nworkers_; ++i) {
    if (i == own_order)
      continue;

    if (workers_[i]->mutex_.try_lock()) {
      workers_[i]->transfer(workers_[i]->roots_.size() / 2, objects);
      workers_[i]->mutex_.unlock();
      break;
    }
  }
}

void ParallelSweep::collect(void) {
  auto old_count = objects_.size();

  for (auto i = 0; i < nworkers_; ++i)
    workers_[i]->run_tracing();

  std::set<int> finished;
  while (true) {
    for (auto i = 0; i < nworkers_; ++i) {
      if (!workers_[i]->run_tracing_)
        finished.insert(i);
    }

    if (finished.size() == static_cast<std::size_t>(nworkers_))
      break;
    std::this_thread::sleep_for(std::chrono::microseconds(10));
  }
  finished.clear();

  sweep();

  std::cout
    << "[" << old_count - objects_.size() << "] objects collected, "
    << "[" << objects_.size() << "] objects remaining." << std::endl;
}

BaseObject* ParallelSweep::put_in(int value) {
  if (objects_.size() >= kMaxObjects)
    collect();

  auto* obj = new Int();
  obj->set_value(value);

  auto order = put_in_order();
  workers_[order]->put_in(obj);
  objects_.push_back(obj);

  return obj;
}

BaseObject* ParallelSweep::put_in(BaseObject* first, BaseObject* second) {
  if (objects_.size() >= kMaxObjects)
    collect();

  auto* obj = new Pair();
  if (first != nullptr)
    obj->set_first(first);
  if (second != nullptr)
    obj->set_second(second);

  auto order = put_in_order();
  workers_[order]->put_in(obj);
  objects_.push_back(obj);

  return obj;
}

BaseObject* ParallelSweep::fetch_out(void) {
  auto order = fetch_out_order();
  return workers_[order]->fetch_out();
}

}
<|endoftext|>


<commit_before>/** \brief Utility for checking which ISBNS can be found on archive.org.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2021 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <atomic>
#include <chrono>
#include <iostream>
#include <deque>
#include <mutex>
#include <thread>
#include <cstdio>
#include <cstdlib>
#include "Downloader.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "MARC.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--summarize-tags] [--verbose] worker_thread_count marc_data isbn_list_output");
}

std::atomic<bool> work_available(true);

void WorkerThread(Downloader * const downloader, std::deque<std::set<std::string>> * const task_queue,
                  std::mutex * const task_queue_mutex, unsigned * const isbn_found_count, File * const isbn_list_output,
                  std::mutex * const output_mutex)
{
    std::set<std::string> isbns;
    while (work_available) {
        {
            std::lock_guard<std::mutex> task_queue_mutex_locker(*task_queue_mutex);
            if (not task_queue->empty()) {
                isbns = task_queue->front();
                task_queue->pop_front();
            }
        }

        if (isbns.empty()) {
            std::this_thread::sleep_for(std::chrono::seconds(20));
            continue;
        }

        for (const auto &isbn : isbns) {
            const std::string url("https://archive.org/metadata/isbn_" + isbn + "/created");
            if (not downloader->newUrl(url)) {
                LOG_WARNING("URL \"" + url + " failed to download!");
                continue;
            }

            if (downloader->getMessageBody().find("result") != std::string::npos) {
                std::lock_guard<std::mutex> output_mutex_locker(*output_mutex);
                isbn_list_output->writeln(isbn);
                ++*isbn_found_count;
                std::cout << *isbn_found_count << '\n';
                break;
            }
        }

        isbns.clear();
    }
}

void ProcessRecords(MARC::Reader * const marc_reader, std::deque<std::set<std::string>> * const task_queue,
                    std::mutex * const task_queue_mutex, unsigned * const isbn_found_count)
{
    Downloader downloader;
    unsigned record_count(0), monographs_with_isbns_found_count(0);
    while (const MARC::Record record = marc_reader->read()) {
        ++record_count;
        const auto isbns(record.getISBNs());
        if (isbns.empty())
            continue;

        ++monographs_with_isbns_found_count;

        std::lock_guard<std::mutex> task_queue_mutex_locker(*task_queue_mutex);
        task_queue->push_back(isbns);
    }
    work_available = false; // Let our worker threads return.

    LOG_INFO("Processed " + std::to_string(record_count) + " record(s) and found "
             + std::to_string(*isbn_found_count) + " ISBN('s) that are/is present on archive.org.");
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 4)
        Usage();

    const unsigned WORKER_THREAD_COUNT(StringUtil::ToUnsigned(argv[1]));
    std::vector<std::thread> thread_pool((WORKER_THREAD_COUNT));
    std::deque<std::set<std::string>> task_queue;
    std::mutex task_queue_mutex, output_mutex;
    unsigned isbn_found_count(0);
    auto isbn_list_output(FileUtil::OpenOutputFileOrDie(argv[3]));
    for (size_t i(0); i < WORKER_THREAD_COUNT; ++i)
        thread_pool[i] = std::thread(WorkerThread, new Downloader(), &task_queue, &task_queue_mutex,
                                     &isbn_found_count, isbn_list_output.get(), &output_mutex);

    auto marc_reader(MARC::Reader::Factory(argv[2]));
    ProcessRecords(marc_reader.get(), &task_queue, &task_queue_mutex, &isbn_found_count);

    for (size_t i(0); i < WORKER_THREAD_COUNT; ++i)
        thread_pool[i].join();

    return EXIT_SUCCESS;
}
<commit_msg>This one actually seems to work.<commit_after>/** \brief Utility for checking which ISBNS can be found on archive.org.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2021 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <atomic>
#include <chrono>
#include <iostream>
#include <deque>
#include <mutex>
#include <thread>
#include <cstdio>
#include <cstdlib>
#include "Downloader.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "MARC.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--summarize-tags] [--verbose] worker_thread_count marc_data isbn_list_output");
}

std::atomic<bool> work_available(true);

void WorkerThread(Downloader * const downloader, std::deque<std::set<std::string>> * const task_queue,
                  std::mutex * const task_queue_mutex, unsigned * const isbn_found_count, File * const isbn_list_output,
                  std::mutex * const output_mutex)
{
    std::set<std::string> isbns;
    for (;;) {
        {
            std::lock_guard<std::mutex> task_queue_mutex_locker(*task_queue_mutex);
            if (not task_queue->empty()) {
                isbns = task_queue->front();
                task_queue->pop_front();
            }
        }

        if (isbns.empty()) {
            if (not work_available)
                return;
            std::this_thread::sleep_for(std::chrono::seconds(20));
            continue;
        }

        for (const auto &isbn : isbns) {
            const std::string url("https://archive.org/metadata/isbn_" + isbn + "/created");
            if (not downloader->newUrl(url)) {
                std::lock_guard<std::mutex> output_mutex_locker(*output_mutex);
                LOG_WARNING("URL \"" + url + " failed to download! ("
                            + downloader->getLastErrorMessage() + ")");
                continue;
            }

            if (downloader->getMessageBody().find("result") != std::string::npos) {
                std::lock_guard<std::mutex> output_mutex_locker(*output_mutex);
                isbn_list_output->writeln(isbn);
                ++*isbn_found_count;
                std::cout << *isbn_found_count << '\n';
                break;
            }
        }

        isbns.clear();
    }
}

void ProcessRecords(MARC::Reader * const marc_reader, std::deque<std::set<std::string>> * const task_queue,
                    std::mutex * const task_queue_mutex)
{
    unsigned record_count(0);
    while (const MARC::Record record = marc_reader->read()) {
        ++record_count;
        const auto isbns(record.getISBNs());
        if (isbns.empty())
            continue;

        std::lock_guard<std::mutex> task_queue_mutex_locker(*task_queue_mutex);
        task_queue->push_back(isbns);
    }
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 4)
        Usage();

    const unsigned WORKER_THREAD_COUNT(StringUtil::ToUnsigned(argv[1]));
    std::vector<std::thread> thread_pool((WORKER_THREAD_COUNT));
    std::deque<std::set<std::string>> task_queue;
    std::mutex task_queue_mutex, output_mutex;
    unsigned isbn_found_count(0);
    auto isbn_list_output(FileUtil::OpenOutputFileOrDie(argv[3]));
    for (size_t i(0); i < WORKER_THREAD_COUNT; ++i)
        thread_pool[i] = std::thread(WorkerThread, new Downloader(), &task_queue, &task_queue_mutex,
                                     &isbn_found_count, isbn_list_output.get(), &output_mutex);

    auto marc_reader(MARC::Reader::Factory(argv[2]));
    ProcessRecords(marc_reader.get(), &task_queue, &task_queue_mutex);

    work_available = false; // Let our worker threads return.
    for (size_t i(0); i < WORKER_THREAD_COUNT; ++i)
        thread_pool[i].join();
    LOG_INFO("Found " + std::to_string(isbn_found_count) + " monographs on Archive.org.");

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

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 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.
*/

#include <hip/hip_runtime.h>
#include <hip/hcc_detail/texture_types.h>
#include "hip_internal.hpp"

struct hipTexture {
    hipResourceDesc resDesc;
    hipTextureDesc texDesc;
    hipResourceViewDesc resViewDesc;
    hsa_ext_image_t image;
    hsa_ext_sampler_t sampler;
};

hipError_t hipCreateTextureObject(hipTextureObject_t* pTexObject, const hipResourceDesc* pResDesc,
                                  const hipTextureDesc* pTexDesc,
                                  const hipResourceViewDesc* pResViewDesc) {
  HIP_INIT_API(pTexObject, pResDesc, pTexDesc, pResViewDesc);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDestroyTextureObject(hipTextureObject_t textureObject) {
  HIP_INIT_API(textureObject);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetTextureObjectResourceDesc(hipResourceDesc* pResDesc,
                                           hipTextureObject_t textureObject) {
  HIP_INIT_API(pResDesc, textureObject);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetTextureObjectResourceViewDesc(hipResourceViewDesc* pResViewDesc,
                                               hipTextureObject_t textureObject) {
  HIP_INIT_API(pResViewDesc, textureObject);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetTextureObjectTextureDesc(hipTextureDesc* pTexDesc,
                                          hipTextureObject_t textureObject) {
  HIP_INIT_API(pTexDesc, textureObject);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipBindTexture(size_t* offset, textureReference* tex, const void* devPtr,
                          const hipChannelFormatDesc* desc, size_t size) {
  HIP_INIT_API(offset, tex, devPtr, desc, size);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipBindTexture2D(size_t* offset, textureReference* tex, const void* devPtr,
                            const hipChannelFormatDesc* desc, size_t width, size_t height,
                            size_t pitch) {
  HIP_INIT_API(offset, tex, devPtr, desc, width, height, pitch);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipBindTextureToArray(textureReference* tex, hipArray_const_t array,
                                 const hipChannelFormatDesc* desc) {
  HIP_INIT_API(tex, array, desc);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipBindTextureToMipmappedArray(textureReference* tex,
                                          hipMipmappedArray_const_t mipmappedArray,
                                          const hipChannelFormatDesc* desc) {
  HIP_INIT_API(tex, mipmappedArray, desc);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipUnbindTexture(const textureReference* tex) {
  HIP_INIT_API(tex);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetChannelDesc(hipChannelFormatDesc* desc, hipArray_const_t array) {
  HIP_INIT_API(desc, array);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetTextureAlignmentOffset(size_t* offset, const textureReference* tex) {
  HIP_INIT_API(offset, tex);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetTextureReference(const textureReference** tex, const void* symbol) {
  HIP_INIT_API(tex, symbol);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetFormat(textureReference* tex, hipArray_Format fmt, int NumPackedComponents) {
  HIP_INIT_API(tex, fmt, NumPackedComponents);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetFlags(textureReference* tex, unsigned int flags) {
  HIP_INIT_API(tex, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetFilterMode(textureReference* tex, hipTextureFilterMode fm) {
    HIP_INIT_API(tex, fm);
}

hipError_t hipTexRefSetAddressMode(textureReference* tex, int dim, hipTextureAddressMode am) {
  HIP_INIT_API(tex, dim, am);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetArray(textureReference* tex, hipArray_const_t array, unsigned int flags) {
  HIP_INIT_API(tex, array, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetAddress(size_t* offset, textureReference* tex, hipDeviceptr_t devPtr,
                               size_t size) {
  HIP_INIT_API(offset, tex, devPtr, size);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetAddress2D(textureReference* tex, const HIP_ARRAY_DESCRIPTOR* desc,
                                 hipDeviceptr_t devPtr, size_t pitch) {
  HIP_INIT_API(tex, desc, devPtr, pitch);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}<commit_msg>P4 to Git Change 1537232 by skudchad@skudchad_rocm on 2018/04/05 15:00:24<commit_after>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

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 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.
*/

#include <hip/hip_runtime.h>
#include <hip/hcc_detail/texture_types.h>
#include "hip_internal.hpp"

hipError_t hipCreateTextureObject(hipTextureObject_t* pTexObject, const hipResourceDesc* pResDesc,
                                  const hipTextureDesc* pTexDesc,
                                  const hipResourceViewDesc* pResViewDesc) {
  HIP_INIT_API(pTexObject, pResDesc, pTexDesc, pResViewDesc);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDestroyTextureObject(hipTextureObject_t textureObject) {
  HIP_INIT_API(textureObject);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetTextureObjectResourceDesc(hipResourceDesc* pResDesc,
                                           hipTextureObject_t textureObject) {
  HIP_INIT_API(pResDesc, textureObject);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetTextureObjectResourceViewDesc(hipResourceViewDesc* pResViewDesc,
                                               hipTextureObject_t textureObject) {
  HIP_INIT_API(pResViewDesc, textureObject);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetTextureObjectTextureDesc(hipTextureDesc* pTexDesc,
                                          hipTextureObject_t textureObject) {
  HIP_INIT_API(pTexDesc, textureObject);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipBindTexture(size_t* offset, textureReference* tex, const void* devPtr,
                          const hipChannelFormatDesc* desc, size_t size) {
  HIP_INIT_API(offset, tex, devPtr, desc, size);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipBindTexture2D(size_t* offset, textureReference* tex, const void* devPtr,
                            const hipChannelFormatDesc* desc, size_t width, size_t height,
                            size_t pitch) {
  HIP_INIT_API(offset, tex, devPtr, desc, width, height, pitch);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipBindTextureToArray(textureReference* tex, hipArray_const_t array,
                                 const hipChannelFormatDesc* desc) {
  HIP_INIT_API(tex, array, desc);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipBindTextureToMipmappedArray(textureReference* tex,
                                          hipMipmappedArray_const_t mipmappedArray,
                                          const hipChannelFormatDesc* desc) {
  HIP_INIT_API(tex, mipmappedArray, desc);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipUnbindTexture(const textureReference* tex) {
  HIP_INIT_API(tex);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetChannelDesc(hipChannelFormatDesc* desc, hipArray_const_t array) {
  HIP_INIT_API(desc, array);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetTextureAlignmentOffset(size_t* offset, const textureReference* tex) {
  HIP_INIT_API(offset, tex);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipGetTextureReference(const textureReference** tex, const void* symbol) {
  HIP_INIT_API(tex, symbol);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetFormat(textureReference* tex, hipArray_Format fmt, int NumPackedComponents) {
  HIP_INIT_API(tex, fmt, NumPackedComponents);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetFlags(textureReference* tex, unsigned int flags) {
  HIP_INIT_API(tex, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetFilterMode(textureReference* tex, hipTextureFilterMode fm) {
  HIP_INIT_API(tex, fm);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetAddressMode(textureReference* tex, int dim, hipTextureAddressMode am) {
  HIP_INIT_API(tex, dim, am);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetArray(textureReference* tex, hipArray_const_t array, unsigned int flags) {
  HIP_INIT_API(tex, array, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetAddress(size_t* offset, textureReference* tex, hipDeviceptr_t devPtr,
                               size_t size) {
  HIP_INIT_API(offset, tex, devPtr, size);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipTexRefSetAddress2D(textureReference* tex, const HIP_ARRAY_DESCRIPTOR* desc,
                                 hipDeviceptr_t devPtr, size_t pitch) {
  HIP_INIT_API(tex, desc, devPtr, pitch);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}<|endoftext|>


<commit_before>#include <Windows.h>
#include <stdint.h> // Types indpendent de la plateforme

// Pour bien comprendre la diffrence de fonctionnement des variables statiques en C en fonction du scope
#define internal static // fonctions non visible depuis l'extrieur de ce fichier
#define local_persist static     // variable visibles juste dans le scope o elle dfinie
#define global_variable static   // variable visible dans tous le fichiers (globale)

typedef unsigned char uint8;
typedef uint8_t uint8; // comme un unsigned char, un 8 bits
typedef int16_t uint16;
typedef int32_t uint32;
typedef int64_t uint64;

/* Struct sui reprsente un backbuffer qui nous permet de dessiner */
struct win32_offscreen_buffer {
  BITMAPINFO Info;
  void *Memory;
  int Width;
  int Height;
  int BytesPerPixel;
  int Pitch; // Pitch reprsente la taille d'une ligne en octets
};

// variables globales pour le moment, on grera autrement plus tard
global_variable bool Running;
global_variable win32_offscreen_buffer GlobalBackBuffer;

struct win32_window_dimension
{
  int Width;
  int Height;
};

win32_window_dimension
Win32GetWindowDimension(HWND Window) {
  win32_window_dimension Result;
  RECT ClientRect;
  GetClientRect(Window, &ClientRect);
  Result.Width = ClientRect.right - ClientRect.left;
  Result.Height = ClientRect.bottom - ClientRect.top;
  return(Result);
}

internal void
RenderWeirdGradient(win32_offscreen_buffer *Buffer, int XOffset, int YOffset)
{
  uint8 *Row = (uint8 *)Buffer->Memory; // on va se dplacer dans la mmoire par pas de 8 bits
  for (int Y = 0; Y < Buffer->Height; ++Y)
  {
    uint32 *Pixel = (uint32 *)Row; // Pixel par pixel, on commence par le premier de la ligne
    for (int X = 0; X < Buffer->Width; ++X)
    {
      /*
        Pixels en little endian architecture
                             0  1  2  3 ...
        Pixels en mmoire : 00 00 00 00 ...
        Couleur             BB GG RR XX
        en hexa: 0xXXRRGGBB
      */
      uint8 Blue = (X + XOffset);
      uint8 Green = (Y + YOffset);
      uint8 Red = (X + Y);
      // *Pixel = 0xFF00FF00;
      *Pixel++ = ((Red << 16) | (Green << 8) | Blue); // ce qui quivaut en hexa  0x00BBGG00
    }
    Row += Buffer->Pitch; // Ligne suivante
  }
}

/**
 * DIB: Device Independent Bitmap
 **/
internal void
Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height)
{
  if (Buffer->Memory)
  {
    VirtualFree(Buffer->Memory, 0, MEM_RELEASE); // cf. VirtualProtect, utile pour debug
  }

  Buffer->Width = Width;
  Buffer->Height = Height;
  Buffer->BytesPerPixel = 4;

  Buffer->Info.bmiHeader.biSize = sizeof(Buffer->Info.bmiHeader);
  Buffer->Info.bmiHeader.biWidth = Buffer->Width;
  Buffer->Info.bmiHeader.biHeight = -Buffer->Height; // Attention au sens des coordonnes, du bas vers le haut (d'o le moins)
  Buffer->Info.bmiHeader.biPlanes = 1;
  Buffer->Info.bmiHeader.biBitCount = 32;
  Buffer->Info.bmiHeader.biCompression = BI_RGB;

  int BitmapMemorySize = (Buffer->Width * Buffer->Height) * Buffer->BytesPerPixel;
  Buffer->Memory = VirtualAlloc(0, BitmapMemorySize, MEM_COMMIT, PAGE_READWRITE); // cf. aussi HeapAlloc

  Buffer->Pitch = Width * Buffer->BytesPerPixel;
}

/**
 * Ici au dbut on passait ClientRect par rfrence avec un pointeur (*ClientRect)
 * cependant comme la structure est petite le passer par valeur est suffisant
 **/
internal void
Win32DisplayBufferInWindow(
  HDC DeviceContext,
  int WindowWidth,
  int WindowHeight,
  win32_offscreen_buffer *Buffer)
{
  StretchDIBits( // copie d'un rectangle vers un autre (scaling si ncessaire, bit oprations...)
    DeviceContext,
    0, 0, WindowWidth, WindowHeight,
    0, 0, Buffer->Width, Buffer->Height,
    Buffer->Memory,
    &Buffer->Info,
    DIB_RGB_COLORS,
    SRCCOPY // BitBlt: bit-block transfer of the color data => voir les autres modes dans la MSDN
  );
}

LRESULT CALLBACK
Win32MainWindowCallback(
  HWND Window,
  UINT Message,
  WPARAM WParam,
  LPARAM LParam)
{
  LRESULT Result = 0;
  switch(Message)
  {
    case WM_SIZE:
      {
        OutputDebugStringA("WM_SIZE\n");
      }
      break;
    case WM_DESTROY:
      {
        // PostQuitMessage(0); // Va permettre de sortir de la boucle infinie en dessous
        Running = false;
        OutputDebugStringA("WM_DESTROY\n");
      }
      break;
    case WM_CLOSE:
      {
        // DestroyWindow(Window);
        Running = false;
        OutputDebugStringA("WM_CLOSE\n");
      }
      break;
    case WM_ACTIVATEAPP:
      {
        OutputDebugStringA("WM_ACTIVATEAPP\n");
      }
      break;
    case WM_PAINT:
      {
        PAINTSTRUCT Paint;
        HDC DeviceContext = BeginPaint(Window, &Paint);
        win32_window_dimension Dimension = Win32GetWindowDimension(Window);
        Win32DisplayBufferInWindow(DeviceContext, Dimension.Width, Dimension.Height, &GlobalBackBuffer);
        EndPaint(Window, &Paint);
      }
      break;
    default:
      {
        // OutputDebugStringA("default\n");
        Result = DefWindowProc(Window, Message, WParam, LParam);
      }
      break;
  }
  return(Result);
}

int CALLBACK
WinMain(
  HINSTANCE Instance,
  HINSTANCE PrevInstance,
  LPSTR CommandLine,
  int ShowCode)
{
  // Cration de la fentre principale
  WNDCLASSA WindowClass = {}; // initialisation par dfaut, ANSI version de WNDCLASSA

  Win32ResizeDIBSection(&GlobalBackBuffer, 800, 600);

  // On ne configure que les membres que l'on veut
  WindowClass.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC; // indique que l'on veut rafraichir la fentre entire lors d'un resize (horizontal et vertical)
  WindowClass.lpfnWndProc = Win32MainWindowCallback;
  WindowClass.hInstance = Instance;
  // WindowClass.hIcon;
  WindowClass.lpszClassName = "FaitmainHerosWindowClass"; // nom pour retrouver la fentre

  // Ouverture de la fentre
  if (RegisterClassA(&WindowClass))
  {
    HWND Window = CreateWindowExA( // ANSI version de CreateWindowEx
      0, // dwExStyle : options de la fentre
      WindowClass.lpszClassName,
      "FaitmainHeros",
      WS_OVERLAPPEDWINDOW|WS_VISIBLE, //dwStyle : overlapped window, visible par dfaut
      CW_USEDEFAULT, // X
      CW_USEDEFAULT, // Y
      CW_USEDEFAULT, // nWidth
      CW_USEDEFAULT, // nHeight
      0, // hWndParent : 0 pour dire que c'est une fentre top
      0, // hMenu : 0 pour dire pas de menu
      Instance,
      0 // Pas de passage de paramtres  la fentre
    );
    if (Window)
    {
      // Comme on a spcifi CS_OWNDC on peut initialiser un seul HDC
      // et s'en servir indfiniment car on ne le partage pas
      HDC DeviceContext = GetDC(Window);

      int XOffset = 0;
      int YOffset = 0;
      MSG Message;
      Running = true;

      while (Running) // boucle infinie pour traiter tous les messages
      {
        while(PeekMessageA(&Message, 0, 0, 0, PM_REMOVE)) // On utilise PeekMessage au lieu de GetMessage qui est bloquant
        {
          if (Message.message == WM_QUIT) Running = false;
          TranslateMessage(&Message); // On demande  Windows de traiter le message
          DispatchMessage(&Message); // Envoie le message au main WindowCallback, que l'on a dfini et dclar au dessus
        }

        // Grce  PeekMessage on a tout le temps CPU que l'on veut et on peut dessiner ici
        RenderWeirdGradient(&GlobalBackBuffer, XOffset, YOffset);
        ++XOffset;

        // On doit alors crire dans la fentre  chaque fois que l'on veut rendre
        // On en fera une fonction propre
        win32_window_dimension Dimension = Win32GetWindowDimension(Window);
        Win32DisplayBufferInWindow(
          DeviceContext,
          Dimension.Width, Dimension.Height,
          &GlobalBackBuffer);
        ReleaseDC(Window, DeviceContext);

        // Pour animer diffremment le gradient
        ++XOffset;
        YOffset += 2;
      }
    }
    else
    {
      OutputDebugStringA("Error: CreateWindowEx\n");
    }
  }
  else
  {
    OutputDebugStringA("Error: RegisterClass\n");
  }

  return(0);
};<commit_msg>Début de gestion de la manette<commit_after>#include <Windows.h>
#include <stdint.h> // Types indpendent de la plateforme
#include <Xinput.h> // Pour la gestion des entres (manette...)

// Pour bien comprendre la diffrence de fonctionnement des variables statiques en C en fonction du scope
#define internal static // fonctions non visible depuis l'extrieur de ce fichier
#define local_persist static     // variable visibles juste dans le scope o elle dfinie
#define global_variable static   // variable visible dans tous le fichiers (globale)

typedef unsigned char uint8;
typedef uint8_t uint8; // comme un unsigned char, un 8 bits
typedef int16_t uint16;
typedef int32_t uint32;
typedef int64_t uint64;

/* Struct sui reprsente un backbuffer qui nous permet de dessiner */
struct win32_offscreen_buffer {
  BITMAPINFO Info;
  void *Memory;
  int Width;
  int Height;
  int BytesPerPixel;
  int Pitch; // Pitch reprsente la taille d'une ligne en octets
};

// variables globales pour le moment, on grera autrement plus tard
global_variable bool Running;
global_variable win32_offscreen_buffer GlobalBackBuffer;

struct win32_window_dimension
{
  int Width;
  int Height;
};

win32_window_dimension
Win32GetWindowDimension(HWND Window) {
  win32_window_dimension Result;
  RECT ClientRect;
  GetClientRect(Window, &ClientRect);
  Result.Width = ClientRect.right - ClientRect.left;
  Result.Height = ClientRect.bottom - ClientRect.top;
  return(Result);
}

internal void
RenderWeirdGradient(win32_offscreen_buffer *Buffer, int XOffset, int YOffset)
{
  uint8 *Row = (uint8 *)Buffer->Memory; // on va se dplacer dans la mmoire par pas de 8 bits
  for (int Y = 0; Y < Buffer->Height; ++Y)
  {
    uint32 *Pixel = (uint32 *)Row; // Pixel par pixel, on commence par le premier de la ligne
    for (int X = 0; X < Buffer->Width; ++X)
    {
      /*
        Pixels en little endian architecture
                             0  1  2  3 ...
        Pixels en mmoire : 00 00 00 00 ...
        Couleur             BB GG RR XX
        en hexa: 0xXXRRGGBB
      */
      uint8 Blue = (X + XOffset);
      uint8 Green = (Y + YOffset);
      uint8 Red = (X + Y);
      // *Pixel = 0xFF00FF00;
      *Pixel++ = ((Red << 16) | (Green << 8) | Blue); // ce qui quivaut en hexa  0x00BBGG00
    }
    Row += Buffer->Pitch; // Ligne suivante
  }
}

/**
 * DIB: Device Independent Bitmap
 **/
internal void
Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height)
{
  if (Buffer->Memory)
  {
    VirtualFree(Buffer->Memory, 0, MEM_RELEASE); // cf. VirtualProtect, utile pour debug
  }

  Buffer->Width = Width;
  Buffer->Height = Height;
  Buffer->BytesPerPixel = 4;

  Buffer->Info.bmiHeader.biSize = sizeof(Buffer->Info.bmiHeader);
  Buffer->Info.bmiHeader.biWidth = Buffer->Width;
  Buffer->Info.bmiHeader.biHeight = -Buffer->Height; // Attention au sens des coordonnes, du bas vers le haut (d'o le moins)
  Buffer->Info.bmiHeader.biPlanes = 1;
  Buffer->Info.bmiHeader.biBitCount = 32;
  Buffer->Info.bmiHeader.biCompression = BI_RGB;

  int BitmapMemorySize = (Buffer->Width * Buffer->Height) * Buffer->BytesPerPixel;
  Buffer->Memory = VirtualAlloc(0, BitmapMemorySize, MEM_COMMIT, PAGE_READWRITE); // cf. aussi HeapAlloc

  Buffer->Pitch = Width * Buffer->BytesPerPixel;
}

/**
 * Ici au dbut on passait ClientRect par rfrence avec un pointeur (*ClientRect)
 * cependant comme la structure est petite le passer par valeur est suffisant
 **/
internal void
Win32DisplayBufferInWindow(
  HDC DeviceContext,
  int WindowWidth,
  int WindowHeight,
  win32_offscreen_buffer *Buffer)
{
  StretchDIBits( // copie d'un rectangle vers un autre (scaling si ncessaire, bit oprations...)
    DeviceContext,
    0, 0, WindowWidth, WindowHeight,
    0, 0, Buffer->Width, Buffer->Height,
    Buffer->Memory,
    &Buffer->Info,
    DIB_RGB_COLORS,
    SRCCOPY // BitBlt: bit-block transfer of the color data => voir les autres modes dans la MSDN
  );
}

LRESULT CALLBACK
Win32MainWindowCallback(
  HWND Window,
  UINT Message,
  WPARAM WParam,
  LPARAM LParam)
{
  LRESULT Result = 0;
  switch(Message)
  {
    case WM_SIZE:
      {
        OutputDebugStringA("WM_SIZE\n");
      }
      break;
    case WM_DESTROY:
      {
        // PostQuitMessage(0); // Va permettre de sortir de la boucle infinie en dessous
        Running = false;
        OutputDebugStringA("WM_DESTROY\n");
      }
      break;
    case WM_CLOSE:
      {
        // DestroyWindow(Window);
        Running = false;
        OutputDebugStringA("WM_CLOSE\n");
      }
      break;
    case WM_ACTIVATEAPP:
      {
        OutputDebugStringA("WM_ACTIVATEAPP\n");
      }
      break;
    case WM_PAINT:
      {
        PAINTSTRUCT Paint;
        HDC DeviceContext = BeginPaint(Window, &Paint);
        win32_window_dimension Dimension = Win32GetWindowDimension(Window);
        Win32DisplayBufferInWindow(DeviceContext, Dimension.Width, Dimension.Height, &GlobalBackBuffer);
        EndPaint(Window, &Paint);
      }
      break;
    default:
      {
        // OutputDebugStringA("default\n");
        Result = DefWindowProc(Window, Message, WParam, LParam);
      }
      break;
  }
  return(Result);
}

int CALLBACK
WinMain(
  HINSTANCE Instance,
  HINSTANCE PrevInstance,
  LPSTR CommandLine,
  int ShowCode)
{
  // Cration de la fentre principale
  WNDCLASSA WindowClass = {}; // initialisation par dfaut, ANSI version de WNDCLASSA

  Win32ResizeDIBSection(&GlobalBackBuffer, 800, 600);

  // On ne configure que les membres que l'on veut
  WindowClass.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC; // indique que l'on veut rafraichir la fentre entire lors d'un resize (horizontal et vertical)
  WindowClass.lpfnWndProc = Win32MainWindowCallback;
  WindowClass.hInstance = Instance;
  // WindowClass.hIcon;
  WindowClass.lpszClassName = "FaitmainHerosWindowClass"; // nom pour retrouver la fentre

  // Ouverture de la fentre
  if (RegisterClassA(&WindowClass))
  {
    HWND Window = CreateWindowExA( // ANSI version de CreateWindowEx
      0, // dwExStyle : options de la fentre
      WindowClass.lpszClassName,
      "FaitmainHeros",
      WS_OVERLAPPEDWINDOW|WS_VISIBLE, //dwStyle : overlapped window, visible par dfaut
      CW_USEDEFAULT, // X
      CW_USEDEFAULT, // Y
      CW_USEDEFAULT, // nWidth
      CW_USEDEFAULT, // nHeight
      0, // hWndParent : 0 pour dire que c'est une fentre top
      0, // hMenu : 0 pour dire pas de menu
      Instance,
      0 // Pas de passage de paramtres  la fentre
    );
    if (Window)
    {
      // Comme on a spcifi CS_OWNDC on peut initialiser un seul HDC
      // et s'en servir indfiniment car on ne le partage pas
      HDC DeviceContext = GetDC(Window);

      int XOffset = 0;
      int YOffset = 0;
      Running = true;

      while (Running) // boucle infinie pour traiter tous les messages
      {
        MSG Message;
        while(PeekMessageA(&Message, 0, 0, 0, PM_REMOVE)) // On utilise PeekMessage au lieu de GetMessage qui est bloquant
        {
          if (Message.message == WM_QUIT) Running = false;
          TranslateMessage(&Message); // On demande  Windows de traiter le message
          DispatchMessage(&Message); // Envoie le message au main WindowCallback, que l'on a dfini et dclar au dessus
        }

        // Gestion des entres, pour le moment on gre a  chaque image, il faudra peut-tre le faire plus frquemment
        // surtout si le nombre d'images par seconde chute
        for (DWORD ControllerIndex = 0; ControllerIndex < XUSER_MAX_COUNT; ++ControllerIndex)
        {
          XINPUT_STATE ControllerState;
          if (XInputGetState(ControllerIndex, &ControllerState) == ERROR_SUCCESS)
          {
            // Le controller est branch
            XINPUT_GAMEPAD *Pad = &ControllerState.Gamepad;

            bool Up = (Pad->wButtons & XINPUT_GAMEPAD_DPAD_UP);
            bool Down = (Pad->wButtons & XINPUT_GAMEPAD_DPAD_DOWN);
            bool Left = (Pad->wButtons & XINPUT_GAMEPAD_DPAD_LEFT);
            bool Right = (Pad->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT);
            bool Start = (Pad->wButtons & XINPUT_GAMEPAD_START);
            bool Back = (Pad->wButtons & XINPUT_GAMEPAD_BACK);
            bool LeftShoulder = (Pad->wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER);
            bool RightShoulder = (Pad->wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER);
            bool AButton = (Pad->wButtons & XINPUT_GAMEPAD_A);
            bool BButton = (Pad->wButtons & XINPUT_GAMEPAD_B);
            bool XButton = (Pad->wButtons & XINPUT_GAMEPAD_X);
            bool YButton = (Pad->wButtons & XINPUT_GAMEPAD_Y);

            uint16 StickX = Pad->sThumbLX;
            uint16 StickY = Pad->sThumbLY;
          }
          else
          {
            // Le controlleur n'est pas branch
          }
        }

        // Grce  PeekMessage on a tout le temps CPU que l'on veut et on peut dessiner ici
        RenderWeirdGradient(&GlobalBackBuffer, XOffset, YOffset);
        ++XOffset;

        // On doit alors crire dans la fentre  chaque fois que l'on veut rendre
        // On en fera une fonction propre
        win32_window_dimension Dimension = Win32GetWindowDimension(Window);
        Win32DisplayBufferInWindow(
          DeviceContext,
          Dimension.Width, Dimension.Height,
          &GlobalBackBuffer);
        ReleaseDC(Window, DeviceContext);

        // Pour animer diffremment le gradient
        ++XOffset;
        YOffset += 2;
      }
    }
    else
    {
      OutputDebugStringA("Error: CreateWindowEx\n");
    }
  }
  else
  {
    OutputDebugStringA("Error: RegisterClass\n");
  }

  return(0);
};<|endoftext|>


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

  Library: CTK

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

#include "ctkPluginContext.h"
#include "ctkPluginContext_p.h"

#include "ctkPluginPrivate_p.h"
#include "ctkPluginFrameworkContext_p.h"
#include "ctkServices_p.h"
#include "ctkServiceRegistration.h"
#include "ctkServiceReference.h"
#include "ctkServiceReferencePrivate.h"

#include <stdexcept>

//----------------------------------------------------------------------------
ctkPluginContextPrivate::ctkPluginContextPrivate(ctkPluginPrivate* plugin)
  : plugin(plugin)
{}

//----------------------------------------------------------------------------
void ctkPluginContextPrivate::isPluginContextValid() const
{
  if (!plugin) {
    throw std::logic_error("This plugin context is no longer valid");
  }
}

//----------------------------------------------------------------------------
void ctkPluginContextPrivate::invalidate()
{
  plugin = 0;
}

//----------------------------------------------------------------------------
ctkPluginContext::ctkPluginContext(ctkPluginPrivate* plugin)
  : d_ptr(new ctkPluginContextPrivate(plugin))
{}

//----------------------------------------------------------------------------
ctkPluginContext::~ctkPluginContext()
{
  Q_D(ctkPluginContext);
  delete d;
}

//----------------------------------------------------------------------------
QVariant ctkPluginContext::getProperty(const QString& key) const
{
  Q_D(const ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->props.value(key);
}

//----------------------------------------------------------------------------
QSharedPointer<ctkPlugin> ctkPluginContext::getPlugin() const
{
  Q_D(const ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->q_func();
}

//----------------------------------------------------------------------------
QSharedPointer<ctkPlugin> ctkPluginContext::getPlugin(long id) const
{
  Q_D(const ctkPluginContext);
  return d->plugin->fwCtx->plugins->getPlugin(id);
}

//----------------------------------------------------------------------------
QList<QSharedPointer<ctkPlugin> > ctkPluginContext::getPlugins() const
{
  Q_D(const ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->plugins->getPlugins();
}

//----------------------------------------------------------------------------
QSharedPointer<ctkPlugin> ctkPluginContext::installPlugin(const QUrl& location, QIODevice* in)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->plugins->install(location, in);
}

//----------------------------------------------------------------------------
QFileInfo ctkPluginContext::getDataFile(const QString& filename)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  QDir dataRoot(d->plugin->getDataRoot().absolutePath());
  if (!dataRoot.exists())
  {
    if (!dataRoot.mkpath(dataRoot.absolutePath()))
    {
      qWarning() << "Could not create persistent storage area:" << dataRoot.absolutePath();
    }
  }

  return QFileInfo(dataRoot, filename);
}

//----------------------------------------------------------------------------
ctkServiceRegistration ctkPluginContext::registerService(const QStringList& clazzes, QObject* service, const ctkDictionary& properties)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->services->registerService(d->plugin, clazzes, service, properties);
}

//----------------------------------------------------------------------------
ctkServiceRegistration ctkPluginContext::registerService(const char* clazz, QObject* service, const ctkDictionary& properties)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  QStringList clazzes;
  clazzes.append(clazz);
  return d->plugin->fwCtx->services->registerService(d->plugin, clazzes, service, properties);
}

//----------------------------------------------------------------------------
QList<ctkServiceReference> ctkPluginContext::getServiceReferences(const QString& clazz, const QString& filter)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->services->get(clazz, filter, 0);
}

//----------------------------------------------------------------------------
ctkServiceReference ctkPluginContext::getServiceReference(const QString& clazz)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->services->get(d->plugin, clazz);
}

//----------------------------------------------------------------------------
QObject* ctkPluginContext::getService(const ctkServiceReference& reference)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();

  if (!reference)
  {
    throw std::invalid_argument("Default constructed ctkServiceReference is not a valid input to getService()");
  }
  ctkServiceReference internalRef(reference);
  return internalRef.d_func()->getService(d->plugin->q_func());
}

//----------------------------------------------------------------------------
bool ctkPluginContext::ungetService(const ctkServiceReference& reference)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  ctkServiceReference ref = reference;
  return ref.d_func()->ungetService(d->plugin->q_func(), true);
}

//----------------------------------------------------------------------------
bool ctkPluginContext::connectPluginListener(const QObject* receiver, const char* method,
                                             Qt::ConnectionType type)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  // TODO check permissions for a direct connection
  if (type == Qt::DirectConnection || type == Qt::BlockingQueuedConnection)
  {
    return receiver->connect(&(d->plugin->fwCtx->listeners), SIGNAL(pluginChangedDirect(ctkPluginEvent)), method, type);
  }
  else if (type == Qt::QueuedConnection)
  {
    return receiver->connect(&(d->plugin->fwCtx->listeners), SIGNAL(pluginChangedQueued(ctkPluginEvent)), method, type);
  }
  else
  {
    throw std::invalid_argument("Only Qt::DirectConnection, Qt::QueuedConnection, or Qt::BlockingQueuedConnection are allowed as type argument.");
  }
}

//----------------------------------------------------------------------------
bool ctkPluginContext::connectFrameworkListener(const QObject* receiver, const char* method, Qt::ConnectionType type)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  // TODO check permissions for a direct connection
  return receiver->connect(&(d->plugin->fwCtx->listeners), SIGNAL(frameworkEvent(ctkPluginFrameworkEvent)), method, type);
}

//----------------------------------------------------------------------------
void ctkPluginContext::connectServiceListener(QObject* receiver, const char* slot,
                                             const QString& filter)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  d->plugin->fwCtx->listeners.addServiceSlot(getPlugin(), receiver, slot, filter);
}

//----------------------------------------------------------------------------
void ctkPluginContext::disconnectServiceListener(QObject* receiver,
                                                const char* slot)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  d->plugin->fwCtx->listeners.removeServiceSlot(getPlugin(), receiver, slot);
}
<commit_msg>getDataFile() now returns the complete path (dropped last segment).<commit_after>/*=============================================================================

  Library: CTK

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

#include "ctkPluginContext.h"
#include "ctkPluginContext_p.h"

#include "ctkPluginPrivate_p.h"
#include "ctkPluginFrameworkContext_p.h"
#include "ctkServices_p.h"
#include "ctkServiceRegistration.h"
#include "ctkServiceReference.h"
#include "ctkServiceReferencePrivate.h"

#include <stdexcept>

//----------------------------------------------------------------------------
ctkPluginContextPrivate::ctkPluginContextPrivate(ctkPluginPrivate* plugin)
  : plugin(plugin)
{}

//----------------------------------------------------------------------------
void ctkPluginContextPrivate::isPluginContextValid() const
{
  if (!plugin) {
    throw std::logic_error("This plugin context is no longer valid");
  }
}

//----------------------------------------------------------------------------
void ctkPluginContextPrivate::invalidate()
{
  plugin = 0;
}

//----------------------------------------------------------------------------
ctkPluginContext::ctkPluginContext(ctkPluginPrivate* plugin)
  : d_ptr(new ctkPluginContextPrivate(plugin))
{}

//----------------------------------------------------------------------------
ctkPluginContext::~ctkPluginContext()
{
  Q_D(ctkPluginContext);
  delete d;
}

//----------------------------------------------------------------------------
QVariant ctkPluginContext::getProperty(const QString& key) const
{
  Q_D(const ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->props.value(key);
}

//----------------------------------------------------------------------------
QSharedPointer<ctkPlugin> ctkPluginContext::getPlugin() const
{
  Q_D(const ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->q_func();
}

//----------------------------------------------------------------------------
QSharedPointer<ctkPlugin> ctkPluginContext::getPlugin(long id) const
{
  Q_D(const ctkPluginContext);
  return d->plugin->fwCtx->plugins->getPlugin(id);
}

//----------------------------------------------------------------------------
QList<QSharedPointer<ctkPlugin> > ctkPluginContext::getPlugins() const
{
  Q_D(const ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->plugins->getPlugins();
}

//----------------------------------------------------------------------------
QSharedPointer<ctkPlugin> ctkPluginContext::installPlugin(const QUrl& location, QIODevice* in)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->plugins->install(location, in);
}

//----------------------------------------------------------------------------
QFileInfo ctkPluginContext::getDataFile(const QString& filename)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  QDir dataRoot(d->plugin->getDataRoot().absoluteFilePath());
  if (!dataRoot.exists())
  {
    if (!dataRoot.mkpath(dataRoot.absolutePath()))
    {
      qWarning() << "Could not create persistent storage area:" << dataRoot.absolutePath();
    }
  }

  return QFileInfo(dataRoot, filename);
}

//----------------------------------------------------------------------------
ctkServiceRegistration ctkPluginContext::registerService(const QStringList& clazzes, QObject* service, const ctkDictionary& properties)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->services->registerService(d->plugin, clazzes, service, properties);
}

//----------------------------------------------------------------------------
ctkServiceRegistration ctkPluginContext::registerService(const char* clazz, QObject* service, const ctkDictionary& properties)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  QStringList clazzes;
  clazzes.append(clazz);
  return d->plugin->fwCtx->services->registerService(d->plugin, clazzes, service, properties);
}

//----------------------------------------------------------------------------
QList<ctkServiceReference> ctkPluginContext::getServiceReferences(const QString& clazz, const QString& filter)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->services->get(clazz, filter, 0);
}

//----------------------------------------------------------------------------
ctkServiceReference ctkPluginContext::getServiceReference(const QString& clazz)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  return d->plugin->fwCtx->services->get(d->plugin, clazz);
}

//----------------------------------------------------------------------------
QObject* ctkPluginContext::getService(const ctkServiceReference& reference)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();

  if (!reference)
  {
    throw std::invalid_argument("Default constructed ctkServiceReference is not a valid input to getService()");
  }
  ctkServiceReference internalRef(reference);
  return internalRef.d_func()->getService(d->plugin->q_func());
}

//----------------------------------------------------------------------------
bool ctkPluginContext::ungetService(const ctkServiceReference& reference)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  ctkServiceReference ref = reference;
  return ref.d_func()->ungetService(d->plugin->q_func(), true);
}

//----------------------------------------------------------------------------
bool ctkPluginContext::connectPluginListener(const QObject* receiver, const char* method,
                                             Qt::ConnectionType type)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  // TODO check permissions for a direct connection
  if (type == Qt::DirectConnection || type == Qt::BlockingQueuedConnection)
  {
    return receiver->connect(&(d->plugin->fwCtx->listeners), SIGNAL(pluginChangedDirect(ctkPluginEvent)), method, type);
  }
  else if (type == Qt::QueuedConnection)
  {
    return receiver->connect(&(d->plugin->fwCtx->listeners), SIGNAL(pluginChangedQueued(ctkPluginEvent)), method, type);
  }
  else
  {
    throw std::invalid_argument("Only Qt::DirectConnection, Qt::QueuedConnection, or Qt::BlockingQueuedConnection are allowed as type argument.");
  }
}

//----------------------------------------------------------------------------
bool ctkPluginContext::connectFrameworkListener(const QObject* receiver, const char* method, Qt::ConnectionType type)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  // TODO check permissions for a direct connection
  return receiver->connect(&(d->plugin->fwCtx->listeners), SIGNAL(frameworkEvent(ctkPluginFrameworkEvent)), method, type);
}

//----------------------------------------------------------------------------
void ctkPluginContext::connectServiceListener(QObject* receiver, const char* slot,
                                             const QString& filter)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  d->plugin->fwCtx->listeners.addServiceSlot(getPlugin(), receiver, slot, filter);
}

//----------------------------------------------------------------------------
void ctkPluginContext::disconnectServiceListener(QObject* receiver,
                                                const char* slot)
{
  Q_D(ctkPluginContext);
  d->isPluginContextValid();
  d->plugin->fwCtx->listeners.removeServiceSlot(getPlugin(), receiver, slot);
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 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-CHROMIUM file.

#include "common/main_delegate.h"

#include "browser/browser_client.h"
#include "common/content_client.h"

#include "base/command_line.h"
#include "base/path_service.h"
#include "content/public/common/content_switches.h"
#include "ui/base/resource/resource_bundle.h"

namespace brightray {

MainDelegate::MainDelegate() {
}

MainDelegate::~MainDelegate() {
}

scoped_ptr<ContentClient> MainDelegate::CreateContentClient() {
  return make_scoped_ptr(new ContentClient).Pass();
}

bool MainDelegate::BasicStartupComplete(int* exit_code) {
  content_client_ = CreateContentClient().Pass();
  SetContentClient(content_client_.get());
#if defined(OS_MACOSX)
  OverrideChildProcessPath();
  OverrideFrameworkBundlePath();
#endif
  return false;
}

void MainDelegate::PreSandboxStartup() {
  InitializeResourceBundle();
}

void MainDelegate::InitializeResourceBundle() {
  base::FilePath path;
#if defined(OS_MACOSX)
  path = GetResourcesPakFilePath();
#else
  base::FilePath pak_dir;
  PathService::Get(base::DIR_MODULE, &pak_dir);
  path = pak_dir.Append(FILE_PATH_LITERAL("content_shell.pak"));
#endif

  ui::ResourceBundle::InitSharedInstanceWithLocale("", NULL,
      ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES);
  ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(path, ui::SCALE_FACTOR_100P);
  AddDataPackFromPath(&ui::ResourceBundle::GetSharedInstance(), path.DirName());
}

content::ContentBrowserClient* MainDelegate::CreateContentBrowserClient() {
  browser_client_ = CreateBrowserClient().Pass();
  return browser_client_.get();
}

scoped_ptr<BrowserClient> MainDelegate::CreateBrowserClient() {
  return make_scoped_ptr(new BrowserClient).Pass();
}

}  // namespace brightray
<commit_msg>Load content_shell.pak for current scale factor<commit_after>// Copyright (c) 2012 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-CHROMIUM file.

#include "common/main_delegate.h"

#include "browser/browser_client.h"
#include "common/content_client.h"

#include "base/command_line.h"
#include "base/path_service.h"
#include "content/public/common/content_switches.h"
#include "ui/base/resource/resource_bundle.h"

namespace brightray {

MainDelegate::MainDelegate() {
}

MainDelegate::~MainDelegate() {
}

scoped_ptr<ContentClient> MainDelegate::CreateContentClient() {
  return make_scoped_ptr(new ContentClient).Pass();
}

bool MainDelegate::BasicStartupComplete(int* exit_code) {
  content_client_ = CreateContentClient().Pass();
  SetContentClient(content_client_.get());
#if defined(OS_MACOSX)
  OverrideChildProcessPath();
  OverrideFrameworkBundlePath();
#endif
  return false;
}

void MainDelegate::PreSandboxStartup() {
  InitializeResourceBundle();
}

void MainDelegate::InitializeResourceBundle() {
  base::FilePath path;
#if defined(OS_MACOSX)
  path = GetResourcesPakFilePath();
#else
  base::FilePath pak_dir;
  PathService::Get(base::DIR_MODULE, &pak_dir);
  path = pak_dir.Append(FILE_PATH_LITERAL("content_shell.pak"));
#endif

  ui::ResourceBundle::InitSharedInstanceWithLocale("", nullptr,
      ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES);
  ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
      path, ui::GetSupportedScaleFactors()[0]);
  AddDataPackFromPath(&ui::ResourceBundle::GetSharedInstance(), path.DirName());
}

content::ContentBrowserClient* MainDelegate::CreateContentBrowserClient() {
  browser_client_ = CreateBrowserClient().Pass();
  return browser_client_.get();
}

scoped_ptr<BrowserClient> MainDelegate::CreateBrowserClient() {
  return make_scoped_ptr(new BrowserClient).Pass();
}

}  // namespace brightray
<|endoftext|>


<commit_before>#ifndef _PAR_UTIL_
#define _PAR_UTIL_

#include "common.hpp"
#include "math.h"
#include "assert.h"

// Determine whether or not we should wait for tasks in hybrid parallelism.
bool should_task_wait(int mults_per_step, int total_rec_steps, int steps_left,
                      int start_index, int position, int num_threads) {
  assert(0 < position && position <= mults_per_step);

#if defined(_PARALLEL_) && (_PARALLEL_ == _BFS_PAR_)
  return position == mults_per_step;
#endif

  int total_multiplies = pow(mults_per_step, total_rec_steps);
  int extra_multiplies = total_multiplies % num_threads;

  if (position == mults_per_step) {
    // The last position always waits.
    return true;
  }

  int end_index = total_multiplies - extra_multiplies;
  // There is exactly one wait at the bottom level of the recursive tree.
  if (steps_left == 1 && start_index + position == end_index) {
    //std::cout << "End stop: " << steps_left << " " << start_index << " " << position << std::endl;
    return true;
  }

  int num_from_end = extra_multiplies / mults_per_step;
  if (steps_left == 2 && mults_per_step - num_from_end == position) {
    //std::cout << "Early stop: " << steps_left << " " << start_index << " " << position << std::endl;
    return true;
  }

  return false;
}

// Determine whether or not we should launch a task for hybrid parallelism.
bool should_launch_task(int mults_per_step, int total_rec_steps, int steps_left,
                        int start_index, int position, int num_threads) {
  assert(0 < position && position <= mults_per_step);

#if defined(_PARALLEL_) && (_PARALLEL_ == _BFS_PAR_)
  return true;
#endif

  int total_multiplies = pow(mults_per_step, total_rec_steps);
  int extra_multiplies = total_multiplies % num_threads;

  // If the number of threads is greater than the total number of multiplies,
  // then we just run parallel MKL.
  if (num_threads > total_multiplies) {
    return false;
  }

  int end_index = total_multiplies - extra_multiplies;
  if (steps_left == 1 && start_index + position > end_index) {
    //std::cout << "Not launching: " << steps_left << " " << start_index << " " << position << std::endl;
    return false;
  }

  int num_from_end = extra_multiplies / mults_per_step;
  if (steps_left == 2 && mults_per_step - num_from_end < position) {
    //std::cout << "Not launching: " << steps_left << " " << start_index << " " << position << std::endl;
    return false;
  }

  return true;
}

class Lock {
public:
  Lock() { omp_init_lock(&lock_); }
  ~Lock() { omp_destroy_lock(&lock_); }

  void Acquire() { omp_set_lock(&lock_); }
  void Release() { omp_unset_lock(&lock_); }

private:
  omp_lock_t lock_;
};

class LockAndCounter {
public:
  LockAndCounter(int count) : count_(count) { lock_.Acquire(); }

  void decrement() {
#pragma omp atomic update
    --count_;
    if (count_ == 0) {
      lock_.Release();
    }
  }

  Lock& lock() { return lock_; }
  int count() { return count_; }

private:
  int count_;
  Lock lock_;
};

#endif  // _PAR_UTIL_
<commit_msg>Fix some of the integer arithmetic and add in additional locking stuff.<commit_after>#ifndef _PAR_UTIL_
#define _PAR_UTIL_

#include "common.hpp"
#include "math.h"
#include "assert.h"

int earliest_leaf_start(int mults_per_step, int steps_left, int start_index, int position) {
  if (steps_left == 1) {
	return start_index;
  }
  int earliest_child_start = (start_index + position - 1) * mults_per_step;
  return earliest_leaf_start(mults_per_step, steps_left - 1, earliest_child_start, 1);
}

// Determine whether or not we should wait for tasks in hybrid parallelism.
bool should_task_wait(int mults_per_step, int total_rec_steps, int steps_left,
                      int start_index, int position, int num_threads) {
  assert(0 < position && position <= mults_per_step);

#if defined(_PARALLEL_) && (_PARALLEL_ == _BFS_PAR_)
  return position == mults_per_step;
#endif

  int total_multiplies = pow(mults_per_step, total_rec_steps);
  int extra_multiplies = total_multiplies % num_threads;

  // HYBRID does all DFS, so no need to wait.
  if (num_threads > total_multiplies) {
	return false;
  }

  if (position == mults_per_step) {
    // The last position always waits.
    return true;
  }

  int end_index = total_multiplies - extra_multiplies;
  // There is exactly one wait at the bottom level of the recursion tree.
  if (steps_left == 1 && start_index + position == end_index) {
    //std::cout << "End stop: " << steps_left << " " << start_index << " " << position << std::endl;
    return true;
  }

  // There can be at most one wait at the second to last level of the recursion tree.
  int smallest_index = earliest_leaf_start(mults_per_step, steps_left, start_index, position);
  if (smallest_index >= end_index) {
    //std::cout << "Early stop: " << steps_left << " " << start_index << " " << position << std::endl;
    return true;
  }

  return false;
}

// Determine whether or not we should launch a task for hybrid parallelism.
bool should_launch_task(int mults_per_step, int total_rec_steps, int steps_left,
                        int start_index, int position, int num_threads) {
  assert(0 < position && position <= mults_per_step);

#if defined(_PARALLEL_) && (_PARALLEL_ == _BFS_PAR_)
  return true;
#endif

  int total_multiplies = pow(mults_per_step, total_rec_steps);
  int extra_multiplies = total_multiplies % num_threads;

  // If the number of threads is greater than the total number of multiplies,
  // then we just run parallel MKL.
  if (num_threads > total_multiplies) {
    return false;
  }

  int end_index = total_multiplies - extra_multiplies;
  if (steps_left == 1 && start_index + position > end_index) {
    //std::cout << "Not launching: " << steps_left << " " << start_index << " " << position << std::endl;
    return false;
  }

  int smallest_index = earliest_leaf_start(mults_per_step, steps_left, start_index, position);
  if (smallest_index >= end_index) {
    //std::cout << "Not launching: " << steps_left << " " << start_index << " " << position << std::endl;
    return false;
  }

  return true;
}

class Lock {
public:
  Lock() { omp_init_lock(&lock_); }
  ~Lock() { omp_destroy_lock(&lock_); }

  void Acquire() { omp_set_lock(&lock_); }
  bool Test() { return omp_test_lock(&lock_); }
  void Release() { omp_unset_lock(&lock_); }

private:
  omp_lock_t lock_;
};

class LockAndCounter {
public:
  LockAndCounter(int count) : count_(count) { lock_.Acquire(); }

  void Decrement() {
    #pragma omp critical
	{
	  if (count_ > 0) {
		--count_;
		if (count_ == 0) {
		  lock_.Release();
		}
	  }
	}
  }

  // Non-blocking acquire that yields to other tasks.
  void Acquire() {
	while (!lock_.Test()) {
        #pragma omp taskyield
	}
  }
  void Release() { lock_.Release(); }

private:
  int count_;
  Lock lock_;
};

# if defined(_PARALLEL_) && (_PARALLEL_ == _HYBRID_PAR_)
// Switch to DFS style sub-problems in the hybrid parallelism
void SwitchToDFS(LockAndCounter& locker, int num_threads) {
    locker.Acquire();
    mkl_set_num_threads_local(num_threads);
    locker.Release();
}
#endif

#endif  // _PAR_UTIL_
<|endoftext|>