<commit_before>/* The MIT License (MIT)
 *
 * Copyright (c) 2016 Ștefan-Gabriel Mirea, Adrian Dobrică
 *
 * 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 "elf_file.hpp"
#include "elf_header_container.hpp"
#include "program_header_table_container.hpp"
#include "section_header_table_container.hpp"
#include "segment_contents_container.hpp"
#include "section_contents_container.hpp"
#include <utility>

using namespace elf;

ELFFile::ELFFile(const std::string &filename) : FileUnit(filename), formatName("ELF")
{
    loadFile(filename);
}

const std::string &ELFFile::getFormatName()
{
    return formatName;
}

ELFFile::~ELFFile()
{
    delete file;
}

bool ELFFile::getOpenStatus()
{
    return open;
}

bool ELFFile::save(std::string &filename)
{
    return file->save(filename);
}

void ELFFile::modifyHex(size_t offset, std::string &newContent) {}

ELFIO::elfio *ELFFile::getELFIO()
{
    return file;
}

bool ELFFile::loadFile(const std::string &filename)
{
    file = new ELFIO::elfio();
    try
    {
        open = file->load(filename);
    }
    catch (std::exception &e)
    {
#ifdef DEBUG
        std::cerr << "Caught " << e.what() << " in LEFIO::load.\n";
#endif
        open = false;
    }

    if (open && file->get_type() != ET_EXEC)
        open = false;

    std::vector<Container *> &topLevelContainers = getTopLevelContainers();
    topLevelContainers.clear();

    if (open)
    {
        topLevelContainers.push_back(new ELFHeaderContainer(this, std::make_pair(0, file->get_header_size())));
        topLevelContainers.push_back(new ProgramHeaderTableContainer(this, std::make_pair(10, 20)));
        topLevelContainers.push_back(new SectionHeaderTableContainer(this, std::make_pair(20, 30)));
        topLevelContainers.push_back(new SegmentContentsContainer(this));
        topLevelContainers.push_back(new SectionContentsContainer(this));
    }

    return open;
}
<commit_msg>Deallocate old ELFIO::elfio in refresh<commit_after>/* The MIT License (MIT)
 *
 * Copyright (c) 2016 Ștefan-Gabriel Mirea, Adrian Dobrică
 *
 * 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 "elf_file.hpp"
#include "elf_header_container.hpp"
#include "program_header_table_container.hpp"
#include "section_header_table_container.hpp"
#include "segment_contents_container.hpp"
#include "section_contents_container.hpp"
#include <utility>

using namespace elf;

ELFFile::ELFFile(const std::string &filename) : FileUnit(filename), formatName("ELF")
{
    file = nullptr;
    loadFile(filename);
}

const std::string &ELFFile::getFormatName()
{
    return formatName;
}

ELFFile::~ELFFile()
{
    delete file;
}

bool ELFFile::getOpenStatus()
{
    return open;
}

bool ELFFile::save(std::string &filename)
{
    return file->save(filename);
}

void ELFFile::modifyHex(size_t offset, std::string &newContent) {}

ELFIO::elfio *ELFFile::getELFIO()
{
    return file;
}

bool ELFFile::loadFile(const std::string &filename)
{
    if (file)
        delete file;

    file = new ELFIO::elfio();
    try
    {
        open = file->load(filename);
    }
    catch (std::exception &e)
    {
#ifdef DEBUG
        std::cerr << "Caught " << e.what() << " in LEFIO::load.\n";
#endif
        open = false;
    }

    if (open && file->get_type() != ET_EXEC)
        open = false;

    std::vector<Container *> &topLevelContainers = getTopLevelContainers();
    topLevelContainers.clear();

    if (open)
    {
        topLevelContainers.push_back(new ELFHeaderContainer(this, std::make_pair(0, file->get_header_size())));
        topLevelContainers.push_back(new ProgramHeaderTableContainer(this, std::make_pair(10, 20)));
        topLevelContainers.push_back(new SectionHeaderTableContainer(this, std::make_pair(20, 30)));
        topLevelContainers.push_back(new SegmentContentsContainer(this));
        topLevelContainers.push_back(new SectionContentsContainer(this));
    }

    return open;
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
//      https://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 <thread>

#include "iree/hal/cts/cts_test_base.h"
#include "iree/hal/driver_registry.h"
#include "iree/testing/gtest.h"

namespace iree {
namespace hal {
namespace cts {

class SemaphoreTest : public CtsTestBase {};

// Tests that a semaphore that is unused properly cleans itself up.
TEST_P(SemaphoreTest, NoOp) {
  ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(123u));
  ASSERT_OK_AND_ASSIGN(uint64_t value, semaphore->Query());
  EXPECT_EQ(123u, value);
}

// Tests that a semaphore will accept new values as it is signaled.
TEST_P(SemaphoreTest, NormalSignaling) {
  ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(2u));
  EXPECT_EQ(2u, semaphore->Query().value());
  EXPECT_OK(semaphore->Signal(3u));
  EXPECT_EQ(3u, semaphore->Query().value());
  EXPECT_OK(semaphore->Signal(40u));
  EXPECT_EQ(40u, semaphore->Query().value());
}

// Note: Behavior is undefined when signaling with decreasing values, so we
// can't reliably test it across backends. Some backends may return errors,
// while others may accept the new, decreasing, values.

// Tests that a semaphore that has failed will remain in a failed state.
TEST_P(SemaphoreTest, Failure) {
  ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(2u));
  // Signal to 3.
  EXPECT_OK(semaphore->Signal(3u));
  EXPECT_EQ(3u, semaphore->Query().value());

  // Fail now.
  semaphore->Fail(UnknownErrorBuilder(IREE_LOC));
  EXPECT_TRUE(IsUnknown(semaphore->Query().status()));

  // Signaling again is undefined behavior. Some backends may return a
  // sticky failure status while others may silently process new signal values.
}

// Tests waiting on no semaphores.
TEST_P(SemaphoreTest, EmptyWait) {
  EXPECT_OK(device_->WaitAllSemaphores({}, InfiniteFuture()));
}

// Tests waiting on a semaphore that has already been signaled.
TEST_P(SemaphoreTest, WaitAlreadySignaled) {
  ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(2u));
  // Test both previous and current values.
  EXPECT_OK(
      device_->WaitAllSemaphores({{semaphore.get(), 1u}}, InfiniteFuture()));
  EXPECT_OK(
      device_->WaitAllSemaphores({{semaphore.get(), 2u}}, InfiniteFuture()));
}

// Tests waiting on a semaphore that has not been signaled.
TEST_P(SemaphoreTest, WaitUnsignaled) {
  ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(2u));
  // NOTE: we don't actually block here because otherwise we'd lock up.
  // Result status is undefined - some backends may return DeadlineExceededError
  // while others may return success.
  device_->WaitAllSemaphores({{semaphore.get(), 3u}}, InfinitePast())
      .IgnoreError();
}

// Waiting on a failed semaphore is undefined behavior. Some backends may
// return UnknownError while others may succeed.

// Tests threading behavior by ping-ponging between the test main thread and
// a little thread.
TEST_P(SemaphoreTest, PingPong) {
  ASSERT_OK_AND_ASSIGN(auto a2b, device_->CreateSemaphore(0u));
  ASSERT_OK_AND_ASSIGN(auto b2a, device_->CreateSemaphore(0u));
  std::thread thread([&]() {
    // Should advance right past this because the value is already set.
    ASSERT_OK(device_->WaitAllSemaphores({{a2b.get(), 0u}}, InfiniteFuture()));
    ASSERT_OK(b2a->Signal(1u));
    // Jump ahead.
    ASSERT_OK(device_->WaitAllSemaphores({{a2b.get(), 4u}}, InfiniteFuture()));
  });
  ASSERT_OK(device_->WaitAllSemaphores({{b2a.get(), 1u}}, InfiniteFuture()));
  ASSERT_OK(a2b->Signal(4u));
  thread.join();
}

INSTANTIATE_TEST_SUITE_P(AllDrivers, SemaphoreTest,
                         ::testing::ValuesIn(DriverRegistry::shared_registry()
                                                 ->EnumerateAvailableDrivers()),
                         GenerateTestName());

}  // namespace cts
}  // namespace hal
}  // namespace iree
<commit_msg>Disabled Semaphore test (#2603)<commit_after>// Copyright 2020 Google LLC
//
// 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
//
//      https://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 <thread>

#include "iree/hal/cts/cts_test_base.h"
#include "iree/hal/driver_registry.h"
#include "iree/testing/gtest.h"

namespace iree {
namespace hal {
namespace cts {

class SemaphoreTest : public CtsTestBase {};

// Tests that a semaphore that is unused properly cleans itself up.
TEST_P(SemaphoreTest, NoOp) {
  ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(123u));
  ASSERT_OK_AND_ASSIGN(uint64_t value, semaphore->Query());
  EXPECT_EQ(123u, value);
}

// Tests that a semaphore will accept new values as it is signaled.
TEST_P(SemaphoreTest, NormalSignaling) {
  ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(2u));
  EXPECT_EQ(2u, semaphore->Query().value());
  EXPECT_OK(semaphore->Signal(3u));
  EXPECT_EQ(3u, semaphore->Query().value());
  EXPECT_OK(semaphore->Signal(40u));
  EXPECT_EQ(40u, semaphore->Query().value());
}

// Note: Behavior is undefined when signaling with decreasing values, so we
// can't reliably test it across backends. Some backends may return errors,
// while others may accept the new, decreasing, values.

// Tests that a semaphore that has failed will remain in a failed state.
TEST_P(SemaphoreTest, Failure) {
  ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(2u));
  // Signal to 3.
  EXPECT_OK(semaphore->Signal(3u));
  EXPECT_EQ(3u, semaphore->Query().value());

  // Fail now.
  semaphore->Fail(UnknownErrorBuilder(IREE_LOC));
  EXPECT_TRUE(IsUnknown(semaphore->Query().status()));

  // Signaling again is undefined behavior. Some backends may return a
  // sticky failure status while others may silently process new signal values.
}

// Tests waiting on no semaphores.
TEST_P(SemaphoreTest, EmptyWait) {
  EXPECT_OK(device_->WaitAllSemaphores({}, InfiniteFuture()));
}

// Tests waiting on a semaphore that has already been signaled.
TEST_P(SemaphoreTest, WaitAlreadySignaled) {
  ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(2u));
  // Test both previous and current values.
  EXPECT_OK(
      device_->WaitAllSemaphores({{semaphore.get(), 1u}}, InfiniteFuture()));
  EXPECT_OK(
      device_->WaitAllSemaphores({{semaphore.get(), 2u}}, InfiniteFuture()));
}

// Tests waiting on a semaphore that has not been signaled.
TEST_P(SemaphoreTest, DISABLED_WaitUnsignaled) {
  ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(2u));
  // NOTE: we don't actually block here because otherwise we'd lock up.
  // Result status is undefined - some backends may return DeadlineExceededError
  // while others may return success.
  device_->WaitAllSemaphores({{semaphore.get(), 3u}}, InfinitePast())
      .IgnoreError();
}

// Waiting on a failed semaphore is undefined behavior. Some backends may
// return UnknownError while others may succeed.

// Tests threading behavior by ping-ponging between the test main thread and
// a little thread.
TEST_P(SemaphoreTest, DISABLED_PingPong) {
  ASSERT_OK_AND_ASSIGN(auto a2b, device_->CreateSemaphore(0u));
  ASSERT_OK_AND_ASSIGN(auto b2a, device_->CreateSemaphore(0u));
  std::thread thread([&]() {
    // Should advance right past this because the value is already set.
    ASSERT_OK(device_->WaitAllSemaphores({{a2b.get(), 0u}}, InfiniteFuture()));
    ASSERT_OK(b2a->Signal(1u));
    // Jump ahead.
    ASSERT_OK(device_->WaitAllSemaphores({{a2b.get(), 4u}}, InfiniteFuture()));
  });
  ASSERT_OK(device_->WaitAllSemaphores({{b2a.get(), 1u}}, InfiniteFuture()));
  ASSERT_OK(a2b->Signal(4u));
  thread.join();
}

INSTANTIATE_TEST_SUITE_P(AllDrivers, SemaphoreTest,
                         ::testing::ValuesIn(DriverRegistry::shared_registry()
                                                 ->EnumerateAvailableDrivers()),
                         GenerateTestName());

}  // namespace cts
}  // namespace hal
}  // namespace iree
<|endoftext|>


<commit_before>// Copyright (c) 2009 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.

#include "webkit/database/database_tracker.h"

#include <vector>

#include "app/sql/connection.h"
#include "app/sql/meta_table.h"
#include "app/sql/statement.h"
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/string_util.h"
#include "webkit/database/databases_table.h"

namespace webkit_database {

const FilePath::CharType kDatabaseDirectoryName[] =
    FILE_PATH_LITERAL("databases");
const FilePath::CharType kTrackerDatabaseFileName[] =
    FILE_PATH_LITERAL("Databases.db");
const int kCurrentVersion = 1;
const int kCompatibleVersion = 1;
const int64 kDefaultQuota = 5 * 1024 * 1024;

DatabaseTracker::DatabaseTracker(const FilePath& profile_path)
    : initialized_(false),
      db_dir_(profile_path.Append(FilePath(kDatabaseDirectoryName))),
      db_(new sql::Connection()),
      databases_table_(NULL),
      meta_table_(NULL) {
}

DatabaseTracker::~DatabaseTracker() {
  DCHECK(observers_.size() == 0);
}

void DatabaseTracker::DatabaseOpened(const string16& origin_identifier,
                                     const string16& database_name,
                                     const string16& database_description,
                                     int64 estimated_size,
                                     int64* database_size,
                                     int64* space_available) {
  if (!LazyInit()) {
    *database_size = 0;
    *space_available = 0;
    return;
  }

  InsertOrUpdateDatabaseDetails(origin_identifier, database_name,
                                database_description, estimated_size);

  *database_size = GetCachedDatabaseFileSize(origin_identifier, database_name);
  *space_available = GetOriginSpaceAvailable(origin_identifier);
}

void DatabaseTracker::DatabaseModified(const string16& origin_identifier,
                                       const string16& database_name) {
  if (!LazyInit())
    return;

  int64 updated_db_size =
      UpdateCachedDatabaseFileSize(origin_identifier, database_name);
  int64 space_available = GetOriginSpaceAvailable(origin_identifier);
  FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseSizeChanged(
      origin_identifier, database_name, updated_db_size, space_available));
}

void DatabaseTracker::DatabaseClosed(const string16& origin_identifier,
                                     const string16& database_name) {
  // TODO(dumi): figure out how to use this information at a later time
}

void DatabaseTracker::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void DatabaseTracker::RemoveObserver(Observer* observer) {
  // When we remove a listener, we do not know which cached information
  // is still needed and which information can be discarded. So we just
  // clear all caches and re-populate them as needed.
  observers_.RemoveObserver(observer);
  ClearAllCachedOriginInfo();
}

void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() {
  ClearAllCachedOriginInfo();
  meta_table_.reset(NULL);
  databases_table_.reset(NULL);
  db_->Close();
  initialized_ = false;
}

FilePath DatabaseTracker::GetFullDBFilePath(
    const string16& origin_identifier,
    const string16& database_name) const {
  DCHECK(!origin_identifier.empty());
  DCHECK(!database_name.empty());
  int64 id = databases_table_->GetDatabaseID(
      origin_identifier, database_name);
  if (id < 0)
    return FilePath();

  FilePath file_name = FilePath::FromWStringHack(Int64ToWString(id));
  return db_dir_.Append(FilePath::FromWStringHack(
      UTF16ToWide(origin_identifier))).Append(file_name);
}

bool DatabaseTracker::LazyInit() {
  if (!initialized_) {
    DCHECK(!db_->is_open());
    DCHECK(!databases_table_.get());
    DCHECK(!meta_table_.get());

    // If the tracker database exists, but it's corrupt or doesn't
    // have a meta table, delete the database directory
    const FilePath kTrackerDatabaseFullPath =
        db_dir_.Append(FilePath(kTrackerDatabaseFileName));
    if (file_util::DirectoryExists(db_dir_) &&
        file_util::PathExists(kTrackerDatabaseFullPath) &&
        (!db_->Open(kTrackerDatabaseFullPath) ||
         !db_->DoesTableExist("meta"))) {
      db_->Close();
      if (!file_util::Delete(db_dir_, true))
        return false;
    }

    databases_table_.reset(new DatabasesTable(db_.get()));
    meta_table_.reset(new sql::MetaTable());

    initialized_ =
        file_util::CreateDirectory(db_dir_) &&
        (db_->is_open() || db_->Open(kTrackerDatabaseFullPath)) &&
        meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion) &&
        (meta_table_->GetCompatibleVersionNumber() <= kCurrentVersion) &&
        databases_table_->Init();
    if (!initialized_) {
      databases_table_.reset(NULL);
      meta_table_.reset(NULL);
      db_->Close();
    }
  }
  return initialized_;
}

void DatabaseTracker::InsertOrUpdateDatabaseDetails(
    const string16& origin_identifier,
    const string16& database_name,
    const string16& database_description,
    int64 estimated_size) {
  DatabaseDetails details;
  if (!databases_table_->GetDatabaseDetails(
          origin_identifier, database_name, &details)) {
    details.origin_identifier = origin_identifier;
    details.database_name = database_name;
    details.description = database_description;
    details.estimated_size = estimated_size;
    databases_table_->InsertDatabaseDetails(details);
  } else if ((details.description != database_description) ||
             (details.estimated_size != estimated_size)) {
    details.description = database_description;
    details.estimated_size = estimated_size;
    databases_table_->UpdateDatabaseDetails(details);
  }
}

int64 DatabaseTracker::GetDBFileSize(const string16& origin_identifier,
                                     const string16& database_name) const {
  FilePath db_file_name = GetFullDBFilePath(origin_identifier, database_name);
  int64 db_file_size = 0;
  if (!file_util::GetFileSize(db_file_name, &db_file_size))
    db_file_size = 0;
  return db_file_size;
}

void DatabaseTracker::ClearAllCachedOriginInfo() {
  origins_info_map_.clear();
}

DatabaseTracker::CachedOriginInfo* DatabaseTracker::GetCachedOriginInfo(
    const string16& origin_identifier) {
  // Populate the cache with data for this origin if needed.
  if (origins_info_map_.find(origin_identifier) == origins_info_map_.end()) {
    std::vector<DatabaseDetails> details;
    if (!databases_table_->GetAllDatabaseDetailsForOrigin(
            origin_identifier, &details)) {
      return NULL;
    }

    CachedOriginInfo& origin_info = origins_info_map_[origin_identifier];
    for (std::vector<DatabaseDetails>::const_iterator it = details.begin();
         it != details.end(); it++) {
      int64 db_file_size =
          GetDBFileSize(it->origin_identifier, it->database_name);
      origin_info.SetCachedDatabaseSize(it->database_name, db_file_size);
    }
  }

  return &origins_info_map_[origin_identifier];
}

int64 DatabaseTracker::GetCachedDatabaseFileSize(
    const string16& origin_identifier,
    const string16& database_name) {
  CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
  if (!origin_info)
    return 0;
  return origin_info->GetCachedDatabaseSize(database_name);
}

int64 DatabaseTracker::UpdateCachedDatabaseFileSize(
    const string16& origin_identifier,
    const string16& database_name) {
  int64 new_size = GetDBFileSize(origin_identifier, database_name);
  CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
  if (origin_info)
    origin_info->SetCachedDatabaseSize(database_name, new_size);
  return new_size;
}

int64 DatabaseTracker::GetOriginUsage(const string16& origin_identifier) {
  CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
  if (!origin_info)
    return kint64max;
  return origin_info->TotalSize();
}

int64 DatabaseTracker::GetOriginQuota(
    const string16& /*origin_identifier*/) const {
  return kDefaultQuota;
}

int64 DatabaseTracker::GetOriginSpaceAvailable(
    const string16& origin_identifier) {
  int64 space_available = GetOriginQuota(origin_identifier) -
      GetOriginUsage(origin_identifier);
  return (space_available < 0 ? 0 : space_available);
}

}  // namespace webkit_database
<commit_msg>Increasing the default DB quota for extensions from 5MB to 50MB.<commit_after>// Copyright (c) 2009 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.

#include "webkit/database/database_tracker.h"

#include <vector>

#include "app/sql/connection.h"
#include "app/sql/meta_table.h"
#include "app/sql/statement.h"
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/string_util.h"
#include "webkit/database/databases_table.h"

namespace webkit_database {

const FilePath::CharType kDatabaseDirectoryName[] =
    FILE_PATH_LITERAL("databases");
const FilePath::CharType kTrackerDatabaseFileName[] =
    FILE_PATH_LITERAL("Databases.db");
const int kCurrentVersion = 1;
const int kCompatibleVersion = 1;
const int64 kDefaultQuota = 5 * 1024 * 1024;
const int64 kDefaultExtensionQuota = 50 * 1024 * 1024;
const char* kExtensionOriginIdentifierPrefix = "chrome-extension_";

DatabaseTracker::DatabaseTracker(const FilePath& profile_path)
    : initialized_(false),
      db_dir_(profile_path.Append(FilePath(kDatabaseDirectoryName))),
      db_(new sql::Connection()),
      databases_table_(NULL),
      meta_table_(NULL) {
}

DatabaseTracker::~DatabaseTracker() {
  DCHECK(observers_.size() == 0);
}

void DatabaseTracker::DatabaseOpened(const string16& origin_identifier,
                                     const string16& database_name,
                                     const string16& database_description,
                                     int64 estimated_size,
                                     int64* database_size,
                                     int64* space_available) {
  if (!LazyInit()) {
    *database_size = 0;
    *space_available = 0;
    return;
  }

  InsertOrUpdateDatabaseDetails(origin_identifier, database_name,
                                database_description, estimated_size);

  *database_size = GetCachedDatabaseFileSize(origin_identifier, database_name);
  *space_available = GetOriginSpaceAvailable(origin_identifier);
}

void DatabaseTracker::DatabaseModified(const string16& origin_identifier,
                                       const string16& database_name) {
  if (!LazyInit())
    return;

  int64 updated_db_size =
      UpdateCachedDatabaseFileSize(origin_identifier, database_name);
  int64 space_available = GetOriginSpaceAvailable(origin_identifier);
  FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseSizeChanged(
      origin_identifier, database_name, updated_db_size, space_available));
}

void DatabaseTracker::DatabaseClosed(const string16& origin_identifier,
                                     const string16& database_name) {
  // TODO(dumi): figure out how to use this information at a later time
}

void DatabaseTracker::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void DatabaseTracker::RemoveObserver(Observer* observer) {
  // When we remove a listener, we do not know which cached information
  // is still needed and which information can be discarded. So we just
  // clear all caches and re-populate them as needed.
  observers_.RemoveObserver(observer);
  ClearAllCachedOriginInfo();
}

void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() {
  ClearAllCachedOriginInfo();
  meta_table_.reset(NULL);
  databases_table_.reset(NULL);
  db_->Close();
  initialized_ = false;
}

FilePath DatabaseTracker::GetFullDBFilePath(
    const string16& origin_identifier,
    const string16& database_name) const {
  DCHECK(!origin_identifier.empty());
  DCHECK(!database_name.empty());
  int64 id = databases_table_->GetDatabaseID(
      origin_identifier, database_name);
  if (id < 0)
    return FilePath();

  FilePath file_name = FilePath::FromWStringHack(Int64ToWString(id));
  return db_dir_.Append(FilePath::FromWStringHack(
      UTF16ToWide(origin_identifier))).Append(file_name);
}

bool DatabaseTracker::LazyInit() {
  if (!initialized_) {
    DCHECK(!db_->is_open());
    DCHECK(!databases_table_.get());
    DCHECK(!meta_table_.get());

    // If the tracker database exists, but it's corrupt or doesn't
    // have a meta table, delete the database directory
    const FilePath kTrackerDatabaseFullPath =
        db_dir_.Append(FilePath(kTrackerDatabaseFileName));
    if (file_util::DirectoryExists(db_dir_) &&
        file_util::PathExists(kTrackerDatabaseFullPath) &&
        (!db_->Open(kTrackerDatabaseFullPath) ||
         !db_->DoesTableExist("meta"))) {
      db_->Close();
      if (!file_util::Delete(db_dir_, true))
        return false;
    }

    databases_table_.reset(new DatabasesTable(db_.get()));
    meta_table_.reset(new sql::MetaTable());

    initialized_ =
        file_util::CreateDirectory(db_dir_) &&
        (db_->is_open() || db_->Open(kTrackerDatabaseFullPath)) &&
        meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion) &&
        (meta_table_->GetCompatibleVersionNumber() <= kCurrentVersion) &&
        databases_table_->Init();
    if (!initialized_) {
      databases_table_.reset(NULL);
      meta_table_.reset(NULL);
      db_->Close();
    }
  }
  return initialized_;
}

void DatabaseTracker::InsertOrUpdateDatabaseDetails(
    const string16& origin_identifier,
    const string16& database_name,
    const string16& database_description,
    int64 estimated_size) {
  DatabaseDetails details;
  if (!databases_table_->GetDatabaseDetails(
          origin_identifier, database_name, &details)) {
    details.origin_identifier = origin_identifier;
    details.database_name = database_name;
    details.description = database_description;
    details.estimated_size = estimated_size;
    databases_table_->InsertDatabaseDetails(details);
  } else if ((details.description != database_description) ||
             (details.estimated_size != estimated_size)) {
    details.description = database_description;
    details.estimated_size = estimated_size;
    databases_table_->UpdateDatabaseDetails(details);
  }
}

int64 DatabaseTracker::GetDBFileSize(const string16& origin_identifier,
                                     const string16& database_name) const {
  FilePath db_file_name = GetFullDBFilePath(origin_identifier, database_name);
  int64 db_file_size = 0;
  if (!file_util::GetFileSize(db_file_name, &db_file_size))
    db_file_size = 0;
  return db_file_size;
}

void DatabaseTracker::ClearAllCachedOriginInfo() {
  origins_info_map_.clear();
}

DatabaseTracker::CachedOriginInfo* DatabaseTracker::GetCachedOriginInfo(
    const string16& origin_identifier) {
  // Populate the cache with data for this origin if needed.
  if (origins_info_map_.find(origin_identifier) == origins_info_map_.end()) {
    std::vector<DatabaseDetails> details;
    if (!databases_table_->GetAllDatabaseDetailsForOrigin(
            origin_identifier, &details)) {
      return NULL;
    }

    CachedOriginInfo& origin_info = origins_info_map_[origin_identifier];
    for (std::vector<DatabaseDetails>::const_iterator it = details.begin();
         it != details.end(); it++) {
      int64 db_file_size =
          GetDBFileSize(it->origin_identifier, it->database_name);
      origin_info.SetCachedDatabaseSize(it->database_name, db_file_size);
    }
  }

  return &origins_info_map_[origin_identifier];
}

int64 DatabaseTracker::GetCachedDatabaseFileSize(
    const string16& origin_identifier,
    const string16& database_name) {
  CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
  if (!origin_info)
    return 0;
  return origin_info->GetCachedDatabaseSize(database_name);
}

int64 DatabaseTracker::UpdateCachedDatabaseFileSize(
    const string16& origin_identifier,
    const string16& database_name) {
  int64 new_size = GetDBFileSize(origin_identifier, database_name);
  CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
  if (origin_info)
    origin_info->SetCachedDatabaseSize(database_name, new_size);
  return new_size;
}

int64 DatabaseTracker::GetOriginUsage(const string16& origin_identifier) {
  CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
  if (!origin_info)
    return kint64max;
  return origin_info->TotalSize();
}

int64 DatabaseTracker::GetOriginQuota(
    const string16& origin_identifier) const {
  if (StartsWith(origin_identifier,
                 ASCIIToUTF16(kExtensionOriginIdentifierPrefix), true)) {
    return kDefaultExtensionQuota;
  }

  return kDefaultQuota;
}

int64 DatabaseTracker::GetOriginSpaceAvailable(
    const string16& origin_identifier) {
  int64 space_available = GetOriginQuota(origin_identifier) -
      GetOriginUsage(origin_identifier);
  return (space_available < 0 ? 0 : space_available);
}

}  // namespace webkit_database
<|endoftext|>


<commit_before>/**
 * @file
 *
 * @ingroup pwg2_forward_scripts
 */
/**
 * Run a pass on ESD data to produce the energ loss fits
 *
 *
 * @ingroup pwg2_forward_scripts
 */
void MakeELossFits(const char* esddir,
		   Int_t       nEvents=1000,
		   Int_t       proof=0,
		   Bool_t      mc=false)
{
  // --- Libraries to load -------------------------------------------
  gROOT->Macro("$ALICE_ROOT/PWG2/FORWARD/analysis2/scripts/LoadLibs.C");

  // --- Check for proof mode, and possibly upload pars --------------
  if (proof > 0) {
    gROOT->LoadMacro("$ALICE_ROOT/PWG2/FORWARD/analysis2/scripts/LoadPars.C");
    LoadPars(proof);
  }

  // --- Our data chain ----------------------------------------------
  gROOT->LoadMacro("$ALICE_ROOT/PWG2/FORWARD/analysis2/scripts/MakeESDChain.C");
  TChain* chain = MakeESDChain(esddir, true);
  // If 0 or less events is select, choose all
  if (nEvents <= 0) nEvents = chain->GetEntries();
  Info("MakeELossFits", "Will analyse %d events", nEvents);

  // --- Creating the manager and handlers ---------------------------
  AliAnalysisManager *mgr  = new AliAnalysisManager("Forward ELoss Train",
						    "Forward energy loss");
  AliAnalysisManager::SetCommonFileName("forward_eloss.root");

  AliESDInputHandler *esdHandler = new AliESDInputHandler();
  esdHandler->SetInactiveBranches("AliESDACORDE "
				  "AliRawDataErrorLogs "
				  "CaloClusters "
				  "Cascades "
				  "EMCALCells "
				  "EMCALTrigger "
				  "Kinks "
				  "Cascades "
				  "MuonTracks "
				  "TrdTracks "
				  "CaloClusters "
				  "HLTGlobalTrigger");
  mgr->SetInputEventHandler(esdHandler);

  // AOD output handler
  AliAODHandler* aodHandler   = new AliAODHandler();
  mgr->SetOutputEventHandler(aodHandler);
  aodHandler->SetOutputFileName("AliAODs.root");

  // --- Add tasks ---------------------------------------------------
  gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPhysicsSelection.C");
  AddTaskPhysicsSelection(mc, kTRUE, kTRUE);
  AliFMDEnergyFitterTask* task = new AliFMDEnergyFitterTask("fmdEnergyFitter");
  mgr->AddTask(task);

  // --- Make the output container and connect it --------------------
  TString outputfile = AliAnalysisManager::GetCommonFileName();
  AliAnalysisDataContainer* histOut =
    mgr->CreateContainer("Forward", TList::Class(),
			 AliAnalysisManager::kOutputContainer,outputfile);
  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, histOut);

  // --- Set parameters on the algorithms ----------------------------
  // Set the number of SPD tracklets for which we consider the event a
  // low flux event
  task->GetEventInspector().SetLowFluxCut(1000);
  // Set the maximum error on v_z [cm]
  task->GetEventInspector().SetMaxVzErr(0.2);
  // Set the eta axis to use - note, this overrides whatever is used
  // by the rest of the algorithms - but only for the energy fitter
  // algorithm.
  task->GetEnergyFitter().SetEtaAxis(200, -4, 6);
  // Set maximum energy loss to consider
  task->GetEnergyFitter().SetMaxE(15);
  // Set number of energy loss bins
  task->GetEnergyFitter().SetNEbins(100);
  // Set whether to use increasing bin sizes
  task->GetEnergyFitter().SetUseIncreasingBins(true);
  // Set whether to do fit the energy distributions
  task->GetEnergyFitter().SetDoFits(kTRUE);
  // Set whether to make the correction object
  task->GetEnergyFitter().SetDoMakeObject(kTRUE);
  // Set the low cut used for energy
  task->GetEnergyFitter().SetLowCut(0.4);
  // Set the number of bins to subtract from maximum of distributions
  // to get the lower bound of the fit range
  task->GetEnergyFitter().SetFitRangeBinWidth(4);
  // Set the maximum number of landaus to try to fit (max 5)
  task->GetEnergyFitter().SetNParticles(5);
  // Set the minimum number of entries in the distribution before
  // trying to fit to the data
  task->GetEnergyFitter().SetMinEntries(1000);
  // --- Set limits on fits the energy -------------------------------
  // Maximum relative error on parameters
  AliFMDCorrELossFit::ELossFit::fgMaxRelError = .12;
  // Least weight to use
  AliFMDCorrELossFit::ELossFit::fgLeastWeight = 1e-5;
  // Maximum value of reduced chi^2
  AliFMDCorrELossFit::ELossFit::fgMaxChi2nu   = 10;

  // --- Run the analysis --------------------------------------------
  TStopwatch t;
  if (!mgr->InitAnalysis()) {
    Error("RunManager", "Failed to initialize analysis train!");
    return;
  }
  // Some informative output
  mgr->PrintStatus();
  // mgr->SetDebugLevel(3);
  if (mgr->GetDebugLevel() < 1 && proof <= 0) mgr->SetUseProgressBar(kTRUE);

  // Run the train
  t.Start();
  Printf("=== RUNNING ANALYSIS ==================================");
  mgr->StartAnalysis(proof > 0 ? "proof" : "local", chain, nEvents);
  t.Stop();
  t.Print();
}
//
// EOF
//
<commit_msg>bug fix<commit_after>/**
 * @file
 *
 * @ingroup pwg2_forward_scripts
 */
/**
 * Run a pass on ESD data to produce the energ loss fits
 *
 *
 * @ingroup pwg2_forward_scripts
 */
void MakeELossFits(const char* esddir,
		   Int_t       nEvents=1000,
		   Int_t       proof=0,
		   Bool_t      mc=false)
{
  // --- Libraries to load -------------------------------------------
  gROOT->Macro("$ALICE_ROOT/PWG2/FORWARD/analysis2/scripts/LoadLibs.C");

  // --- Check for proof mode, and possibly upload pars --------------
  if (proof > 0) {
    gROOT->LoadMacro("$ALICE_ROOT/PWG2/FORWARD/analysis2/scripts/LoadPars.C");
    LoadPars(proof);
  }

  // --- Our data chain ----------------------------------------------
  gROOT->LoadMacro("$ALICE_ROOT/PWG2/FORWARD/analysis2/scripts/MakeChain.C");
  TChain* chain = MakeChain("ESD",esddir, true);
  // If 0 or less events is select, choose all
  if (nEvents <= 0) nEvents = chain->GetEntries();
  Info("MakeELossFits", "Will analyse %d events", nEvents);

  // --- Creating the manager and handlers ---------------------------
  AliAnalysisManager *mgr  = new AliAnalysisManager("Forward ELoss Train",
						    "Forward energy loss");
  AliAnalysisManager::SetCommonFileName("forward_eloss.root");

  AliESDInputHandler *esdHandler = new AliESDInputHandler();
  esdHandler->SetInactiveBranches("AliESDACORDE "
				  "AliRawDataErrorLogs "
				  "CaloClusters "
				  "Cascades "
				  "EMCALCells "
				  "EMCALTrigger "
				  "Kinks "
				  "Cascades "
				  "MuonTracks "
				  "TrdTracks "
				  "CaloClusters "
				  "HLTGlobalTrigger");
  mgr->SetInputEventHandler(esdHandler);

  // AOD output handler
  AliAODHandler* aodHandler   = new AliAODHandler();
  mgr->SetOutputEventHandler(aodHandler);
  aodHandler->SetOutputFileName("AliAODs.root");

  // --- Add tasks ---------------------------------------------------
  gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPhysicsSelection.C");
  AddTaskPhysicsSelection(mc, kTRUE, kTRUE);
  AliFMDEnergyFitterTask* task = new AliFMDEnergyFitterTask("fmdEnergyFitter");
  mgr->AddTask(task);

  // --- Make the output container and connect it --------------------
  TString outputfile = AliAnalysisManager::GetCommonFileName();
  AliAnalysisDataContainer* histOut =
    mgr->CreateContainer("Forward", TList::Class(),
			 AliAnalysisManager::kOutputContainer,outputfile);
  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, histOut);

  // --- Set parameters on the algorithms ----------------------------
  // Set the number of SPD tracklets for which we consider the event a
  // low flux event
  task->GetEventInspector().SetLowFluxCut(1000);
  // Set the maximum error on v_z [cm]
  task->GetEventInspector().SetMaxVzErr(0.2);
  // Set the eta axis to use - note, this overrides whatever is used
  // by the rest of the algorithms - but only for the energy fitter
  // algorithm.
  task->GetEnergyFitter().SetEtaAxis(200, -4, 6);
  // Set maximum energy loss to consider
  task->GetEnergyFitter().SetMaxE(15);
  // Set number of energy loss bins
  task->GetEnergyFitter().SetNEbins(100);
  // Set whether to use increasing bin sizes
  task->GetEnergyFitter().SetUseIncreasingBins(true);
  // Set whether to do fit the energy distributions
  task->GetEnergyFitter().SetDoFits(kTRUE);
  // Set whether to make the correction object
  task->GetEnergyFitter().SetDoMakeObject(kTRUE);
  // Set the low cut used for energy
  task->GetEnergyFitter().SetLowCut(0.4);
  // Set the number of bins to subtract from maximum of distributions
  // to get the lower bound of the fit range
  task->GetEnergyFitter().SetFitRangeBinWidth(4);
  // Set the maximum number of landaus to try to fit (max 5)
  task->GetEnergyFitter().SetNParticles(5);
  // Set the minimum number of entries in the distribution before
  // trying to fit to the data
  task->GetEnergyFitter().SetMinEntries(1000);
  // --- Set limits on fits the energy -------------------------------
  // Maximum relative error on parameters
  AliFMDCorrELossFit::ELossFit::fgMaxRelError = .12;
  // Least weight to use
  AliFMDCorrELossFit::ELossFit::fgLeastWeight = 1e-5;
  // Maximum value of reduced chi^2
  AliFMDCorrELossFit::ELossFit::fgMaxChi2nu   = 10;

  // --- Run the analysis --------------------------------------------
  TStopwatch t;
  if (!mgr->InitAnalysis()) {
    Error("RunManager", "Failed to initialize analysis train!");
    return;
  }
  // Some informative output
  mgr->PrintStatus();
  // mgr->SetDebugLevel(3);
  if (mgr->GetDebugLevel() < 1 && proof <= 0) mgr->SetUseProgressBar(kTRUE);

  // Run the train
  t.Start();
  Printf("=== RUNNING ANALYSIS ==================================");
  mgr->StartAnalysis(proof > 0 ? "proof" : "local", chain, nEvents);
  t.Stop();
  t.Print();
}
//
// EOF
//
<|endoftext|>


<commit_before>#include "ThreadPool.hpp"

namespace dbr
{
	namespace cc
	{
		ThreadPool::ThreadPool(std::size_t threadCount)
		:	threadsWaiting(0),
			terminate(false),
			paused(false)
		{
			// keep from reallocating
			threads.reserve(threadCount);

			for(auto i = 0u; i < threadCount; ++i)
				threads.emplace_back(threadTask, this);
		}

		ThreadPool::~ThreadPool()
		{
			stop();
		}

		std::size_t ThreadPool::threadCount() const
		{
			return threads.size();
		}

		std::size_t ThreadPool::waitingJobs() const
		{
			std::lock_guard<std::mutex> jobLock(jobsMutex);
			return jobs.size();
		}

		void ThreadPool::clear()
		{
			std::lock_guard<std::mutex> lock(jobsMutex);

			while(!jobs.empty())
				jobs.pop();
		}

		void ThreadPool::pause()
		{
			paused = true;
		}

		void ThreadPool::resume()
		{
			paused = false;
			jobsAvailable.notify_all();

			// block until at least 1 thread has started
			while(threadsWaiting == threads.size());
		}

		void ThreadPool::wait()
		{
			// we're done waiting once all threads are waiting
			while(threadsWaiting != threads.size());
		}

		void ThreadPool::stop()
		{
			clear();

			// tell threads to stop when they can
			terminate = true;
			jobsAvailable.notify_all();

			// wait for all threads to finish
			for(auto& t : threads)
				t.join();
		}

		void ThreadPool::threadTask(ThreadPool* pool)
		{
			// loop until we break (to keep thread alive)
			while(true)
			{
				if(pool->terminate)
					break;

				std::unique_lock<std::mutex> jobsLock(pool->jobsMutex);

				// if there are no more jobs, or we're paused, go into waiting mode
				if(pool->jobs.empty() || pool->paused)
				{
					++pool->threadsWaiting;
					pool->jobsAvailable.wait(jobsLock, [&]()
					{
						return pool->terminate || !(pool->jobs.empty() || pool->paused);
					});
					--pool->threadsWaiting;

					// if we were woken in order to stop
					if(pool->terminate)
						break;
				}

				// take next job
				auto job = std::move(pool->jobs.front());
				pool->jobs.pop();

				jobsLock.unlock();

				job();
			}
		}
	}
}<commit_msg>Quick sanity fix.<commit_after>#include "ThreadPool.hpp"

namespace dbr
{
	namespace cc
	{
		ThreadPool::ThreadPool(std::size_t threadCount)
		:	threadsWaiting(0),
			terminate(false),
			paused(false)
		{
			// keep from reallocating
			threads.reserve(threadCount);

			for(auto i = 0u; i < threadCount; ++i)
				threads.emplace_back(threadTask, this);
		}

		ThreadPool::~ThreadPool()
		{
			stop();
		}

		std::size_t ThreadPool::threadCount() const
		{
			return threads.size();
		}

		std::size_t ThreadPool::waitingJobs() const
		{
			std::lock_guard<std::mutex> jobLock(jobsMutex);
			return jobs.size();
		}

		void ThreadPool::clear()
		{
			std::lock_guard<std::mutex> lock(jobsMutex);

			while(!jobs.empty())
				jobs.pop();
		}

		void ThreadPool::pause()
		{
			paused = true;
		}

		void ThreadPool::resume()
		{
			paused = false;
			jobsAvailable.notify_all();

			// block until at least 1 thread has started
			while(threadsWaiting == threads.size());
		}

		void ThreadPool::wait()
		{
			// we're done waiting once all threads are waiting
			while(threadsWaiting != threads.size());
		}

		void ThreadPool::stop()
		{
			clear();

			// tell threads to stop when they can
			terminate = true;
			jobsAvailable.notify_all();

			// wait for all threads to finish
			for(auto& t : threads)
				t.join();
		}

		void ThreadPool::threadTask(ThreadPool* pool)
		{
			// loop until we break (to keep thread alive)
			while(true)
			{
				if(pool->terminate)
					break;

				std::unique_lock<std::mutex> jobsLock(pool->jobsMutex);

				// if there are no more jobs, or we're paused, go into waiting mode
				if(pool->jobs.empty() || pool->paused)
				{
					++pool->threadsWaiting;
					pool->jobsAvailable.wait(jobsLock, [&]()
					{
						return pool->terminate || !(pool->jobs.empty() || pool->paused);
					});
					--pool->threadsWaiting;
				}

				// last check before grabbing a job
				if(pool->terminate)
					break;

				// take next job
				auto job = std::move(pool->jobs.front());
				pool->jobs.pop();

				jobsLock.unlock();

				job();
			}
		}
	}
}<|endoftext|>


<commit_before>/*
 * Copyright 2010 Jonathan R. Guthrie
 *
 * 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.
 */

#if !defined(THREADPOOL_H_INCLUDED)
#define THREADPOOL_H_INCLUDED

/*
 * The template in this file implements a worker thread pool.  The template must be
 * based on a class that implements a method called DoWork that neither accepts nor
 * returns anything.  The class that uses the thread pool sends work to them using
 * the SendMessage and SendMessages methods.
 *
 * In the case of the InternetServer, the thread pools are called to notify them that
 * the socket will not block on receive, and the worker itself is expected to do the
 * actual receiving.
 *
 * Among the assumptions that underlie this implementation is the assumption that we don't
 * need to be "fair" in the distribution of work.  That is, it doesn't matter if the first
 * thread does all the work and none of the other threads do any, it only matters that the
 * work gets done in as efficient a manner as possible.
 *
 */

#include <queue>
#include <list>

#include <boost/thread.hpp>

// class MessageType must have a method called "void DoWork(void)"
template <typename T>
class ThreadPool
{
public:
  typedef typename std::list<T> Tlist;
  typedef typename std::queue<T, Tlist> Tqueue;
  typedef std::queue<int> IntQueue;
  ThreadPool(int numThreads = 1, typename Tqueue::size_type queue_highwater = 0);
  ~ThreadPool(void);
  void sendMessage(T message);
  void sendMessages(Tqueue &messages);
  void sendMessages(Tlist &messages);

private:
  void workerThread(void);
  static void *ThreadFunction(void*);

  boost::condition_variable m_workersGo;
  bool m_stopRunning;
  int m_workerThreadCount;
  boost::mutex m_pendingQueueMutex;
  boost::unique_lock<boost::mutex> m_pendingQueueLock;
  Tqueue m_pendingQueue;
  boost::mutex m_highwaterMutex;
  boost::unique_lock<boost::mutex> m_highwaterLock;
  boost::condition_variable m_highwaterCond;
  boost::thread **m_workerThreads;
  const typename ThreadPool<T>::Tqueue::size_type m_queueHighwater;
};

template <typename T>
void *ThreadPool<T>::ThreadFunction(void *instance_pointer) {
  ThreadPool<T> *self = (ThreadPool<T> *)instance_pointer;
  self->workerThread();
  return NULL;
}

template <typename T>
void ThreadPool<T>::workerThread(void) {
  // std::cout << "In the worker thread method, I've got a listener for thread " << std::endl;
  while(1) {
    m_pendingQueueLock.lock();
    if ((0 < m_queueHighwater) && (m_queueHighwater > m_pendingQueue.size())) {
      m_highwaterCond.notify_all();
    }

    if (m_stopRunning) {
      m_pendingQueueLock.unlock();
      m_workersGo.notify_all();
      break;
    }

    T work = NULL;
    if (!m_pendingQueue.empty()) {
      work = m_pendingQueue.front();
      m_pendingQueue.pop();
      m_pendingQueueLock.unlock();
    }
    else {
      work = NULL;
      // The wait unlocks m_pendingQueueLock, and then locks it again when the condition happens
      m_workersGo.wait(m_pendingQueueLock);
      if (!m_pendingQueue.empty()) {
	work = m_pendingQueue.front();
	m_pendingQueue.pop();
      }
      m_pendingQueueLock.unlock();
    }
    if (NULL != work) {
      work->doWork();
    }
  }
}

template <typename T>
ThreadPool<T>::ThreadPool(int numThreads, typename ThreadPool<T>::Tqueue::size_type queue_highwater) : m_pendingQueueLock(m_pendingQueueMutex),m_highwaterLock(m_highwaterMutex),m_queueHighwater(queue_highwater) {
  m_workerThreadCount = numThreads;
  m_stopRunning = false;

  m_workerThreads = new boost::thread*[m_workerThreadCount];

  for (int i=0; i<m_workerThreadCount; ++i) {
    m_workerThreads[i] = new boost::thread(ThreadFunction, this);
  }
  m_pendingQueueLock.unlock();
}

template <typename T>
ThreadPool<T>::~ThreadPool(void) {
  m_pendingQueueLock.lock();

  m_stopRunning = true;
  m_pendingQueueLock.unlock();
  m_workersGo.notify_all();
  m_highwaterCond.notify_all();

  // I need to wait for each thread because otherwise I don't know when I can clean up
  for (int i=0; i<m_workerThreadCount; ++i) {
    m_workerThreads[i]->join();
    delete m_workerThreads[i];
  }
  delete[] m_workerThreads;
}

/*
 * This takes a single session and does the right thing with it.  If there is an idle session, then
 * give it to that session and signal the condition variable.  If there are no idle sessions, then
 * put this at the back of the message queue and go about our way.
 */
template <typename T>
void ThreadPool<T>::sendMessage(T message)
{
  typename ThreadPool<T>::Tqueue::size_type depth;

  m_pendingQueueLock.lock();
  m_pendingQueue.push(message);
  depth = m_pendingQueue.size();
  m_pendingQueueLock.unlock();
  m_workersGo.notify_one();
  if ((0 < m_queueHighwater) && (m_queueHighwater < depth)) {
    m_highwaterLock.lock();
    m_highwaterCond.wait(m_highwaterLock);
    m_highwaterLock.unlock();
  }
}

/*
 * This takes queue of sessions and passes them to the destination.  If there fewer idle threads than
 * messages, it will allocate work to all the threads that it can and then put the rest on the pending
 * queue, otherwise it will allocate all the messages and put nothing on to the idle queue
 */
template <typename T>
void ThreadPool<T>::sendMessages(Tqueue &messages) {
  typename ThreadPool<T>::Tqueue::size_type depth;

  m_pendingQueueLock.lock();
  while (!messages.empty()) {
    m_pendingQueue.push(messages.front());
    messages.pop();
  }
  depth = m_pendingQueue.size();
  m_pendingQueueLock.unlock();
  m_workersGo.notify_all();
  if ((0 < m_queueHighwater) && (m_queueHighwater < depth)) {
    m_highwaterLock.lock();
    m_highwaterCond.wait(m_highwaterLock);
    m_highwaterLock.unlock();
  }
}

/*
 * This takes list of sessions and passes them to the destination.  If there fewer idle threads than
 * messages, it will allocate work to all the threads that it can and then put the rest on the pending
 * queue, otherwise it will allocate all the messages and put nothing on to the idle queue
 */
template <typename T>
void ThreadPool<T>::sendMessages(Tlist &messages) {
  typename ThreadPool<T>::Tqueue::size_type depth;
  m_pendingQueueLock.lock();

  for (typename ThreadPool<T>::Tlist::iterator i=messages.begin(); i!=messages.end(); ++i) {
    m_pendingQueue.push(*i);
  }
  depth = m_pendingQueue.size();
  m_pendingQueueLock.unlock();
  m_workersGo.notify_all();
  if ((0 < m_queueHighwater) && (m_queueHighwater < depth)) {
    m_highwaterLock.lock();
    m_highwaterCond.wait(m_highwaterLock);
    m_highwaterLock.unlock();
  }
}

#endif // THREADPOOL_H_INCLUDED
<commit_msg>It turns out that the boost locking classes aren't threadsafe, so I have to create a lock in each of the threads in the class based on the mutex that belongs to the class.<commit_after>/*
 * Copyright 2010 Jonathan R. Guthrie
 *
 * 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.
 */

#if !defined(THREADPOOL_H_INCLUDED)
#define THREADPOOL_H_INCLUDED

/*
 * The template in this file implements a worker thread pool.  The template must be
 * based on a class that implements a method called DoWork that neither accepts nor
 * returns anything.  The class that uses the thread pool sends work to them using
 * the SendMessage and SendMessages methods.
 *
 * In the case of the InternetServer, the thread pools are called to notify them that
 * the socket will not block on receive, and the worker itself is expected to do the
 * actual receiving.
 *
 * Among the assumptions that underlie this implementation is the assumption that we don't
 * need to be "fair" in the distribution of work.  That is, it doesn't matter if the first
 * thread does all the work and none of the other threads do any, it only matters that the
 * work gets done in as efficient a manner as possible.
 *
 */

#include <queue>
#include <list>

#include <boost/thread.hpp>

// class MessageType must have a method called "void DoWork(void)"
template <typename T>
class ThreadPool
{
public:
  typedef typename std::list<T> Tlist;
  typedef typename std::queue<T, Tlist> Tqueue;
  typedef std::queue<int> IntQueue;
  ThreadPool(int numThreads = 1, typename Tqueue::size_type queue_highwater = 0);
  ~ThreadPool(void);
  void sendMessage(T message);
  void sendMessages(Tqueue &messages);
  void sendMessages(Tlist &messages);

private:
  void workerThread(void);
  static void *ThreadFunction(void*);

  boost::condition_variable m_workersGo;
  bool m_stopRunning;
  int m_workerThreadCount;
  boost::mutex m_pendingQueueMutex;
  boost::unique_lock<boost::mutex> m_pendingQueueLock;
  Tqueue m_pendingQueue;
  boost::mutex m_highwaterMutex;
  boost::unique_lock<boost::mutex> m_highwaterLock;
  boost::condition_variable m_highwaterCond;
  boost::thread **m_workerThreads;
  const typename ThreadPool<T>::Tqueue::size_type m_queueHighwater;
};

template <typename T>
void *ThreadPool<T>::ThreadFunction(void *instance_pointer) {
  ThreadPool<T> *self = (ThreadPool<T> *)instance_pointer;
  self->workerThread();
  return NULL;
}

template <typename T>
void ThreadPool<T>::workerThread(void) {
  // std::cout << "In the worker thread method, I've got a listener for thread " << std::endl;
  boost::unique_lock<boost::mutex> pendingQueueLock(m_pendingQueueMutex);
  pendingQueueLock.unlock();
  while(1) {
    pendingQueueLock.lock();
    if ((0 < m_queueHighwater) && (m_queueHighwater > m_pendingQueue.size())) {
      m_highwaterCond.notify_all();
    }

    if (m_stopRunning) {
      pendingQueueLock.unlock();
      m_workersGo.notify_all();
      break;
    }

    T work = NULL;
    if (!m_pendingQueue.empty()) {
      work = m_pendingQueue.front();
      m_pendingQueue.pop();
      pendingQueueLock.unlock();
    }
    else {
      work = NULL;
      // The wait unlocks pendingQueueLock, and then locks it again when the condition happens
      m_workersGo.wait(pendingQueueLock);
      if (!m_pendingQueue.empty()) {
	work = m_pendingQueue.front();
	m_pendingQueue.pop();
      }
      pendingQueueLock.unlock();
    }
    if (NULL != work) {
      work->doWork();
    }
  }
}

template <typename T>
ThreadPool<T>::ThreadPool(int numThreads, typename ThreadPool<T>::Tqueue::size_type queue_highwater) : m_pendingQueueLock(m_pendingQueueMutex),m_highwaterLock(m_highwaterMutex),m_queueHighwater(queue_highwater) {
  m_workerThreadCount = numThreads;
  m_stopRunning = false;

  m_workerThreads = new boost::thread*[m_workerThreadCount];

  for (int i=0; i<m_workerThreadCount; ++i) {
    m_workerThreads[i] = new boost::thread(ThreadFunction, this);
  }

  m_pendingQueueLock.unlock();
}

template <typename T>
ThreadPool<T>::~ThreadPool(void) {
  m_pendingQueueLock.lock();

  m_stopRunning = true;
  m_pendingQueueLock.unlock();
  m_workersGo.notify_all();
  m_highwaterCond.notify_all();

  // I need to wait for each thread because otherwise I don't know when I can clean up
  for (int i=0; i<m_workerThreadCount; ++i) {
    m_workerThreads[i]->join();
    delete m_workerThreads[i];
  }
  delete[] m_workerThreads;
}

/*
 * This takes a single session and does the right thing with it.  If there is an idle session, then
 * give it to that session and signal the condition variable.  If there are no idle sessions, then
 * put this at the back of the message queue and go about our way.
 */
template <typename T>
void ThreadPool<T>::sendMessage(T message)
{
  typename ThreadPool<T>::Tqueue::size_type depth;

  m_pendingQueueLock.lock();
  m_pendingQueue.push(message);
  depth = m_pendingQueue.size();
  m_pendingQueueLock.unlock();
  m_workersGo.notify_one();
  if ((0 < m_queueHighwater) && (m_queueHighwater < depth)) {
    m_highwaterLock.lock();
    m_highwaterCond.wait(m_highwaterLock);
    m_highwaterLock.unlock();
  }
}

/*
 * This takes queue of sessions and passes them to the destination.  If there fewer idle threads than
 * messages, it will allocate work to all the threads that it can and then put the rest on the pending
 * queue, otherwise it will allocate all the messages and put nothing on to the idle queue
 */
template <typename T>
void ThreadPool<T>::sendMessages(Tqueue &messages) {
  typename ThreadPool<T>::Tqueue::size_type depth;

  m_pendingQueueLock.lock();
  while (!messages.empty()) {
    m_pendingQueue.push(messages.front());
    messages.pop();
  }
  depth = m_pendingQueue.size();
  m_pendingQueueLock.unlock();
  m_workersGo.notify_all();
  if ((0 < m_queueHighwater) && (m_queueHighwater < depth)) {
    m_highwaterLock.lock();
    m_highwaterCond.wait(m_highwaterLock);
    m_highwaterLock.unlock();
  }
}

/*
 * This takes list of sessions and passes them to the destination.  If there fewer idle threads than
 * messages, it will allocate work to all the threads that it can and then put the rest on the pending
 * queue, otherwise it will allocate all the messages and put nothing on to the idle queue
 */
template <typename T>
void ThreadPool<T>::sendMessages(Tlist &messages) {
  typename ThreadPool<T>::Tqueue::size_type depth;
  m_pendingQueueLock.lock();

  for (typename ThreadPool<T>::Tlist::iterator i=messages.begin(); i!=messages.end(); ++i) {
    m_pendingQueue.push(*i);
  }
  depth = m_pendingQueue.size();
  m_pendingQueueLock.unlock();
  m_workersGo.notify_all();
  if ((0 < m_queueHighwater) && (m_queueHighwater < depth)) {
    m_highwaterLock.lock();
    m_highwaterCond.wait(m_highwaterLock);
    m_highwaterLock.unlock();
  }
}

#endif // THREADPOOL_H_INCLUDED
<|endoftext|>


<commit_before>// ThreadTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <thread>
#include <chrono>
#include <set>
#include <vector>
#include <shared_mutex>
#include <atomic>

int egis = 0;
class AsmLock {
public:
	void Lock()
	{
		__asm {
			mov eax, 1;
		retry:
			xchg eax, [egis];
			test eax, eax;
			jnz retry;
		}
	}

	void Lock2()
	{
		__asm {
			mov eax, 1;
		retry:
			xchg eax, [egis];
			test eax, eax;
			jz done;
		retry_mov:
			mov ebx, [egis];
			test ebx, ebx;
			jnz retry_mov;
			jmp retry;
		done:
		}
	}

	void Unlock()
	{
		__asm {
			mov eax, 0;
			xchg eax, [egis];
		}
	}

	void Unlock2()
	{
		__asm {
			mov[egis], 0;
		}
	}
};

class SharedMutex {
	std::shared_timed_mutex mutex;
public:
	void Lock()
	{
		mutex.lock();
	}

	void Unlock()
	{
		mutex.unlock();
	}
};

class Atomic {
	std::atomic<int> val = 0;
	static const int writeLockBit = 0x40000000;
	static const int upgradingBit = 0x00010000;
	static const int writeUpgradeingBits = 0x7fff0000;
	static const int readerBits = 0x0000ffff;

	void LockInternal(int delta, int testBits)
	{
		int expected;
		do {
			do {
				expected = val;
			} while (expected & testBits);
		} while (!std::atomic_compare_exchange_weak(&val, &expected, expected + delta));
	}

public:
	void ReadLock()
	{
		LockInternal(1, writeUpgradeingBits);
	}

	void Upgrade()
	{
		std::atomic_fetch_add(&val, upgradingBit - 1);
		LockInternal(writeLockBit - upgradingBit, readerBits | writeLockBit);
	}

	void WriteLock()
	{
		LockInternal(writeLockBit, readerBits | writeLockBit);
	}

	void WriteUnlock()
	{
		std::atomic_fetch_sub(&val, writeLockBit);
	}

	void ReadUnlock()
	{
		std::atomic_fetch_sub(&val, 1);
	}
};

//static AsmLock lock;
//static SharedMutex lock;
static Atomic lock;

void IncDecThreadMain()
{
	static int a = 0;
	for (int i = 0; i < 1000000; i++) {
		lock.WriteLock();
		a++;
		if (a != 1)
		{
			printf("%d ", a);
		}
		a--;
		lock.WriteUnlock();
		printf("");
	}
}

void StlContainerThreadMain(int id)
{
	static std::set<int> c;
	int readFound = 0;
	int readNotFound = 0;
	for (int i = 0; i < 1000000; i++) {
		int r = rand() % 10000;
		if (i % 10 == 0) {
			lock.ReadLock();
			auto it = c.find(r);
			if (it != c.end()) {
				lock.ReadUnlock();
			} else {
				lock.Upgrade();
				auto it = c.find(r);
				if (it == c.end()) {
					c.insert(r);
				}
				lock.WriteUnlock();
			}
		} else {
			lock.ReadLock();
			auto it = c.find(r);
			if (it == c.end()) {
				readNotFound++;
			} else {
				readFound++;
			}
			lock.ReadUnlock();
		}
		printf("");
	}
	printf("threadId=%d readFound=%d readNotFound=%d\n", id, readFound, readNotFound);
}

double GetTime()
{
	static auto start = std::chrono::high_resolution_clock::now();
	auto now = std::chrono::high_resolution_clock::now();
	return std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1, 1>>>(now - start).count();
}

void IncDecTest()
{
	printf("IncDecTest\n");
	double begin = GetTime();
	std::thread t1(IncDecThreadMain);
	std::thread t2(IncDecThreadMain);
	std::thread t3(IncDecThreadMain);
	t1.join();
	t2.join();
	t3.join();
	double end = GetTime();
	printf("elapsed: %f\n", end - begin);
}

void StlContainerTest()
{
	printf("StlContainerTest\n");
	double begin = GetTime();
	std::vector<std::thread> t;
	for (int i = 0; i < 10; i++) {
		t.emplace_back(std::thread(StlContainerThreadMain, i));
	}
	for (int i = 0; i < 10; i++) {
		t[i].join();
	}
	double end = GetTime();
	printf("elapsed: %f\n", end - begin);
}

int main()
{
	IncDecTest();
	StlContainerTest();
	return 0;
}
<commit_msg>shorten the code<commit_after>// ThreadTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <thread>
#include <chrono>
#include <set>
#include <vector>
#include <shared_mutex>
#include <atomic>

int egis = 0;
class AsmLock {
public:
	void Lock()
	{
		__asm {
			mov eax, 1;
		retry:
			xchg eax, [egis];
			test eax, eax;
			jnz retry;
		}
	}

	void Lock2()
	{
		__asm {
			mov eax, 1;
		retry:
			xchg eax, [egis];
			test eax, eax;
			jz done;
		retry_mov:
			mov ebx, [egis];
			test ebx, ebx;
			jnz retry_mov;
			jmp retry;
		done:
		}
	}

	void Unlock()
	{
		__asm {
			mov eax, 0;
			xchg eax, [egis];
		}
	}

	void Unlock2()
	{
		__asm {
			mov[egis], 0;
		}
	}
};

class SharedMutex {
	std::shared_timed_mutex mutex;
public:
	void Lock()
	{
		mutex.lock();
	}

	void Unlock()
	{
		mutex.unlock();
	}
};

class Atomic {
	std::atomic<int> val = 0;
	static const int writeLockBit = 0x40000000;
	static const int upgradingBit = 0x00010000;
	static const int writeUpgradeingBits = 0x7fff0000;
	static const int readerBits = 0x0000ffff;

	void LockInternal(int delta, int testBits)
	{
		int expected;
		do {
			do {
				expected = val;
			} while (expected & testBits);
		} while (!val.compare_exchange_weak(expected, expected + delta));
	}

public:
	void ReadLock()
	{
		LockInternal(1, writeUpgradeingBits);
	}

	void Upgrade()
	{
		val.fetch_add(upgradingBit - 1);
		LockInternal(writeLockBit - upgradingBit, readerBits | writeLockBit);
	}

	void WriteLock()
	{
		LockInternal(writeLockBit, readerBits | writeLockBit);
	}

	void WriteUnlock()
	{
		val.fetch_sub(writeLockBit);
	}

	void ReadUnlock()
	{
		val.fetch_sub(1);
	}
};

//static AsmLock lock;
//static SharedMutex lock;
static Atomic lock;

void IncDecThreadMain()
{
	static int a = 0;
	for (int i = 0; i < 1000000; i++) {
		lock.WriteLock();
		a++;
		if (a != 1)
		{
			printf("%d ", a);
		}
		a--;
		lock.WriteUnlock();
		printf("");
	}
}

void StlContainerThreadMain(int id)
{
	static std::set<int> c;
	int readFound = 0;
	int readNotFound = 0;
	for (int i = 0; i < 1000000; i++) {
		int r = rand() % 10000;
		if (i % 10 == 0) {
			lock.ReadLock();
			auto it = c.find(r);
			if (it != c.end()) {
				lock.ReadUnlock();
			} else {
				lock.Upgrade();
				auto it = c.find(r);
				if (it == c.end()) {
					c.insert(r);
				}
				lock.WriteUnlock();
			}
		} else {
			lock.ReadLock();
			auto it = c.find(r);
			if (it == c.end()) {
				readNotFound++;
			} else {
				readFound++;
			}
			lock.ReadUnlock();
		}
		printf("");
	}
	printf("threadId=%d readFound=%d readNotFound=%d\n", id, readFound, readNotFound);
}

double GetTime()
{
	static auto start = std::chrono::high_resolution_clock::now();
	auto now = std::chrono::high_resolution_clock::now();
	return std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1, 1>>>(now - start).count();
}

void IncDecTest()
{
	printf("IncDecTest\n");
	double begin = GetTime();
	std::thread t1(IncDecThreadMain);
	std::thread t2(IncDecThreadMain);
	std::thread t3(IncDecThreadMain);
	t1.join();
	t2.join();
	t3.join();
	double end = GetTime();
	printf("elapsed: %f\n", end - begin);
}

void StlContainerTest()
{
	printf("StlContainerTest\n");
	double begin = GetTime();
	std::vector<std::thread> t;
	for (int i = 0; i < 10; i++) {
		t.emplace_back(std::thread(StlContainerThreadMain, i));
	}
	for (int i = 0; i < 10; i++) {
		t[i].join();
	}
	double end = GetTime();
	printf("elapsed: %f\n", end - begin);
}

int main()
{
	IncDecTest();
	StlContainerTest();
	return 0;
}
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGuiD3D81BaseApplication.cpp
    created:    24/9/2004
    author:     Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/
// this controls conditional compile of file for MSVC
#include "CEGUISamplesConfig.h"
#ifdef CEGUI_SAMPLES_USE_DIRECTX_8

#include "CEGuiD3D81BaseApplication.h"

#include <d3d8.h>
#include <dinput.h>
// undefine Microsoft macro evilness
#undef min
#undef max

#include "renderers/directx81GUIRenderer/renderer.h"
#include "CEGuiSample.h"
#include "Win32AppHelper.h"
#include "CEGUI.h"
#include "CEGUIDefaultResourceProvider.h"

#include <stdexcept>

#ifdef _MSC_VER
# if defined(DEBUG) || defined (_DEBUG)
#   pragma comment (lib, "DirectX81GUIRenderer_d.lib")
# else
#   pragma comment (lib, "DirectX81GUIRenderer.lib")
# endif
#endif

/*************************************************************************
    Impl struct
*************************************************************************/
struct CEGuiD3D81BaseApplicationImpl
{
    HWND d_window;
    LPDIRECT3D8 d_D3D;
    LPDIRECT3DDEVICE8 d_3DDevice;
    D3DPRESENT_PARAMETERS d_ppars;
    CEGUI::DirectX81Renderer* d_renderer;
    Win32AppHelper::DirectInputState d_directInput;
};

/*************************************************************************
    Constructor
*************************************************************************/
CEGuiD3D81BaseApplication::CEGuiD3D81BaseApplication() :
        pimpl(new CEGuiD3D81BaseApplicationImpl),
        d_lastTime(GetTickCount()),
        d_frames(0),
        d_FPS(0)
{
    if (pimpl->d_window = Win32AppHelper::createApplicationWindow(800, 600))
    {
        if (initialiseDirect3D(800, 600, D3DADAPTER_DEFAULT, true))
        {
            if (Win32AppHelper::initialiseDirectInput(pimpl->d_window, pimpl->d_directInput))
            {
                pimpl->d_renderer = new CEGUI::DirectX81Renderer(pimpl->d_3DDevice, 3000);

                // initialise the gui system
                new CEGUI::System(pimpl->d_renderer);

                // initialise the required dirs for the DefaultResourceProvider
                CEGUI::DefaultResourceProvider* rp = static_cast<CEGUI::DefaultResourceProvider*>
                    (CEGUI::System::getSingleton().getResourceProvider());

                rp->setResourceGroupDirectory("schemes", "../datafiles/schemes/");
                rp->setResourceGroupDirectory("imagesets", "../datafiles/imagesets/");
                rp->setResourceGroupDirectory("fonts", "../datafiles/fonts/");
                rp->setResourceGroupDirectory("layouts", "../datafiles/layouts/");
                rp->setResourceGroupDirectory("looknfeels", "../datafiles/looknfeel/");
                rp->setResourceGroupDirectory("lua_scripts", "../datafiles/lua_scripts/");
#if defined(CEGUI_WITH_XERCES) && (CEGUI_DEFAULT_XMLPARSER == XercesParser)
                rp->setResourceGroupDirectory("schemas", "../../XMLRefSchema/");
#endif

                CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);

                return;
            }

            // cleanup direct 3d systems
            pimpl->d_3DDevice->Release();
            pimpl->d_D3D->Release();
        }

        DestroyWindow(pimpl->d_window);
    }
    else
    {
        MessageBox(0, Win32AppHelper::CREATE_WINDOW_ERROR, Win32AppHelper::APPLICATION_NAME, MB_ICONERROR|MB_OK);
    }

    throw std::runtime_error("Win32 DirectX 8.1 application failed to initialise.");
}

/*************************************************************************
    Destructor.
*************************************************************************/
CEGuiD3D81BaseApplication::~CEGuiD3D81BaseApplication()
{
    Win32AppHelper::mouseLeaves();

    // cleanup gui system
	delete CEGUI::System::getSingletonPtr();
    delete pimpl->d_renderer;

    Win32AppHelper::cleanupDirectInput(pimpl->d_directInput);

    // cleanup direct 3d systems
    pimpl->d_3DDevice->Release();
    pimpl->d_D3D->Release();

    DestroyWindow(pimpl->d_window);
}

/*************************************************************************
    Start the base application
*************************************************************************/
bool CEGuiD3D81BaseApplication::execute(CEGuiSample* sampleApp)
{
    sampleApp->initialiseSample();

    //
    //  This is basically a modified Win32 message pump
    //
    bool idle;
    HRESULT coop;

    while (Win32AppHelper::doWin32Events(idle))
    {
        if (idle)
        {
            // handle D3D lost device stuff
            coop = pimpl->d_3DDevice->TestCooperativeLevel();

            if (coop == D3DERR_DEVICELOST)
            {
                Sleep(500);
                continue;
            }
            else if (coop == D3DERR_DEVICENOTRESET)
            {
                if (!resetDirect3D())
                {
                    continue;
                }
            }

            if (FAILED(pimpl->d_3DDevice->BeginScene()))
            {
                continue;
            }

            // main part of idle loop
            updateFPS();
            char fpsbuff[16];
            sprintf(fpsbuff, "FPS: %d", d_FPS);

            Win32AppHelper::doDirectInputEvents(pimpl->d_directInput);

            // draw display
			CEGUI::System& guiSystem = CEGUI::System::getSingleton();
            pimpl->d_3DDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
			guiSystem.renderGUI();

            // render FPS:
            CEGUI::Font* fnt = guiSystem.getDefaultFont();
            if (fnt)
            {
                guiSystem.getRenderer()->setQueueingEnabled(false);
                fnt->drawText(fpsbuff, CEGUI::Vector3(0, 0, 0), guiSystem.getRenderer()->getRect());
            }

            pimpl->d_3DDevice->EndScene();

            pimpl->d_3DDevice->Present(0, 0, 0, 0);
        }

        // check if the application is quitting, and break the loop next time
        // around if so.
        if (isQuitting())
            PostQuitMessage(0);
    }

    return true;
}

/*************************************************************************
    Performs any required cleanup of the base application system.
*************************************************************************/
void CEGuiD3D81BaseApplication::cleanup()
{
    // nothing to do here.
}

/*************************************************************************
    Initialise Direct3D system.
*************************************************************************/
bool CEGuiD3D81BaseApplication::initialiseDirect3D(unsigned int width, unsigned int height, unsigned int adapter, bool windowed)
{
    pimpl->d_D3D = Direct3DCreate8(D3D_SDK_VERSION);

    // display error and exit if D3D creation failed
    if (pimpl->d_D3D)
    {
        D3DDISPLAYMODE d3ddm;
        pimpl->d_D3D->GetAdapterDisplayMode(adapter, &d3ddm);

        D3DFORMAT format = d3ddm.Format;

        // complete window initialisation
        ShowWindow(pimpl->d_window, SW_NORMAL);
        UpdateWindow(pimpl->d_window);

        ZeroMemory(&pimpl->d_ppars, sizeof(pimpl->d_ppars));
        pimpl->d_ppars.BackBufferFormat = format;
        pimpl->d_ppars.hDeviceWindow    = pimpl->d_window;
        pimpl->d_ppars.SwapEffect       = D3DSWAPEFFECT_DISCARD;
        pimpl->d_ppars.Windowed         = windowed;

        if (!windowed)
        {
            pimpl->d_ppars.BackBufferWidth          = width;
            pimpl->d_ppars.BackBufferHeight         = height;
            pimpl->d_ppars.BackBufferCount          = 1;
            pimpl->d_ppars.MultiSampleType          = D3DMULTISAMPLE_NONE;
            pimpl->d_ppars.FullScreen_PresentationInterval  = D3DPRESENT_INTERVAL_IMMEDIATE;
            pimpl->d_ppars.FullScreen_RefreshRateInHz       = D3DPRESENT_RATE_DEFAULT;
        }

        if (SUCCEEDED(pimpl->d_D3D->CreateDevice(adapter, D3DDEVTYPE_HAL, pimpl->d_window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pimpl->d_ppars, &pimpl->d_3DDevice)))
        {
            return true;
        }
        else
        {
            MessageBox(0, Win32AppHelper::CREATE_DEVICE_ERROR, Win32AppHelper::APPLICATION_NAME, MB_ICONERROR|MB_OK);
        }

        pimpl->d_D3D->Release();
        pimpl->d_D3D = 0;
    }
    else
    {
        MessageBox(0, Win32AppHelper::CREATE_D3D_ERROR, Win32AppHelper::APPLICATION_NAME, MB_ICONERROR|MB_OK);
    }

    return false;
}

/*************************************************************************
    Do reset of Direct3D device
*************************************************************************/
bool CEGuiD3D81BaseApplication::resetDirect3D(void)
{
    // perform ops needed prior to reset
    pimpl->d_renderer->preD3DReset();

    if (SUCCEEDED(pimpl->d_3DDevice->Reset(&pimpl->d_ppars)))
    {
        // re-build stuff now reset has been done.
        pimpl->d_renderer->postD3DReset();

        return true;
    }

    return false;
}

#endif
<commit_msg>fixed dx8 sample driver<commit_after>/***********************************************************************
    filename:   CEGuiD3D81BaseApplication.cpp
    created:    24/9/2004
    author:     Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/
// this controls conditional compile of file for MSVC
#include "CEGUISamplesConfig.h"
#ifdef CEGUI_SAMPLES_USE_DIRECTX_8

#include "CEGuiD3D81BaseApplication.h"

#include <d3d8.h>
#include <dinput.h>
// undefine Microsoft macro evilness
#undef min
#undef max

#include "RendererModules/directx81GUIRenderer/renderer.h"
#include "CEGuiSample.h"
#include "Win32AppHelper.h"
#include "CEGUI.h"
#include "CEGUIDefaultResourceProvider.h"

#include <stdexcept>

#ifdef _MSC_VER
# if defined(DEBUG) || defined (_DEBUG)
#   pragma comment (lib, "DirectX81GUIRenderer_d.lib")
# else
#   pragma comment (lib, "DirectX81GUIRenderer.lib")
# endif
#endif

/*************************************************************************
    Impl struct
*************************************************************************/
struct CEGuiD3D81BaseApplicationImpl
{
    HWND d_window;
    LPDIRECT3D8 d_D3D;
    LPDIRECT3DDEVICE8 d_3DDevice;
    D3DPRESENT_PARAMETERS d_ppars;
    CEGUI::DirectX81Renderer* d_renderer;
    Win32AppHelper::DirectInputState d_directInput;
};

/*************************************************************************
    Constructor
*************************************************************************/
CEGuiD3D81BaseApplication::CEGuiD3D81BaseApplication() :
        pimpl(new CEGuiD3D81BaseApplicationImpl),
        d_lastTime(GetTickCount()),
        d_frames(0),
        d_FPS(0)
{
    if (pimpl->d_window = Win32AppHelper::createApplicationWindow(800, 600))
    {
        if (initialiseDirect3D(800, 600, D3DADAPTER_DEFAULT, true))
        {
            if (Win32AppHelper::initialiseDirectInput(pimpl->d_window, pimpl->d_directInput))
            {
                pimpl->d_renderer = new CEGUI::DirectX81Renderer(pimpl->d_3DDevice, 3000);

                // initialise the gui system
                new CEGUI::System(pimpl->d_renderer);

                // initialise the required dirs for the DefaultResourceProvider
                CEGUI::DefaultResourceProvider* rp = static_cast<CEGUI::DefaultResourceProvider*>
                    (CEGUI::System::getSingleton().getResourceProvider());

                rp->setResourceGroupDirectory("schemes", "../datafiles/schemes/");
                rp->setResourceGroupDirectory("imagesets", "../datafiles/imagesets/");
                rp->setResourceGroupDirectory("fonts", "../datafiles/fonts/");
                rp->setResourceGroupDirectory("layouts", "../datafiles/layouts/");
                rp->setResourceGroupDirectory("looknfeels", "../datafiles/looknfeel/");
                rp->setResourceGroupDirectory("lua_scripts", "../datafiles/lua_scripts/");
#if defined(CEGUI_WITH_XERCES) && (CEGUI_DEFAULT_XMLPARSER == XercesParser)
                rp->setResourceGroupDirectory("schemas", "../../XMLRefSchema/");
#endif

                CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);

                return;
            }

            // cleanup direct 3d systems
            pimpl->d_3DDevice->Release();
            pimpl->d_D3D->Release();
        }

        DestroyWindow(pimpl->d_window);
    }
    else
    {
        MessageBox(0, Win32AppHelper::CREATE_WINDOW_ERROR, Win32AppHelper::APPLICATION_NAME, MB_ICONERROR|MB_OK);
    }

    throw std::runtime_error("Win32 DirectX 8.1 application failed to initialise.");
}

/*************************************************************************
    Destructor.
*************************************************************************/
CEGuiD3D81BaseApplication::~CEGuiD3D81BaseApplication()
{
    Win32AppHelper::mouseLeaves();

    // cleanup gui system
	delete CEGUI::System::getSingletonPtr();
    delete pimpl->d_renderer;

    Win32AppHelper::cleanupDirectInput(pimpl->d_directInput);

    // cleanup direct 3d systems
    pimpl->d_3DDevice->Release();
    pimpl->d_D3D->Release();

    DestroyWindow(pimpl->d_window);
}

/*************************************************************************
    Start the base application
*************************************************************************/
bool CEGuiD3D81BaseApplication::execute(CEGuiSample* sampleApp)
{
    sampleApp->initialiseSample();

    //
    //  This is basically a modified Win32 message pump
    //
    bool idle;
    HRESULT coop;

    while (Win32AppHelper::doWin32Events(idle))
    {
        if (idle)
        {
            // handle D3D lost device stuff
            coop = pimpl->d_3DDevice->TestCooperativeLevel();

            if (coop == D3DERR_DEVICELOST)
            {
                Sleep(500);
                continue;
            }
            else if (coop == D3DERR_DEVICENOTRESET)
            {
                if (!resetDirect3D())
                {
                    continue;
                }
            }

            if (FAILED(pimpl->d_3DDevice->BeginScene()))
            {
                continue;
            }

            // main part of idle loop
            updateFPS();
            char fpsbuff[16];
            sprintf(fpsbuff, "FPS: %d", d_FPS);

            Win32AppHelper::doDirectInputEvents(pimpl->d_directInput);

            // draw display
			CEGUI::System& guiSystem = CEGUI::System::getSingleton();
            pimpl->d_3DDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
			guiSystem.renderGUI();

            // render FPS:
            CEGUI::Font* fnt = guiSystem.getDefaultFont();
            if (fnt)
            {
                guiSystem.getRenderer()->setQueueingEnabled(false);
                fnt->drawText(fpsbuff, CEGUI::Vector3(0, 0, 0), guiSystem.getRenderer()->getRect());
            }

            pimpl->d_3DDevice->EndScene();

            pimpl->d_3DDevice->Present(0, 0, 0, 0);
        }

        // check if the application is quitting, and break the loop next time
        // around if so.
        if (isQuitting())
            PostQuitMessage(0);
    }

    return true;
}

/*************************************************************************
    Performs any required cleanup of the base application system.
*************************************************************************/
void CEGuiD3D81BaseApplication::cleanup()
{
    // nothing to do here.
}

/*************************************************************************
    Initialise Direct3D system.
*************************************************************************/
bool CEGuiD3D81BaseApplication::initialiseDirect3D(unsigned int width, unsigned int height, unsigned int adapter, bool windowed)
{
    pimpl->d_D3D = Direct3DCreate8(D3D_SDK_VERSION);

    // display error and exit if D3D creation failed
    if (pimpl->d_D3D)
    {
        D3DDISPLAYMODE d3ddm;
        pimpl->d_D3D->GetAdapterDisplayMode(adapter, &d3ddm);

        D3DFORMAT format = d3ddm.Format;

        // complete window initialisation
        ShowWindow(pimpl->d_window, SW_NORMAL);
        UpdateWindow(pimpl->d_window);

        ZeroMemory(&pimpl->d_ppars, sizeof(pimpl->d_ppars));
        pimpl->d_ppars.BackBufferFormat = format;
        pimpl->d_ppars.hDeviceWindow    = pimpl->d_window;
        pimpl->d_ppars.SwapEffect       = D3DSWAPEFFECT_DISCARD;
        pimpl->d_ppars.Windowed         = windowed;

        if (!windowed)
        {
            pimpl->d_ppars.BackBufferWidth          = width;
            pimpl->d_ppars.BackBufferHeight         = height;
            pimpl->d_ppars.BackBufferCount          = 1;
            pimpl->d_ppars.MultiSampleType          = D3DMULTISAMPLE_NONE;
            pimpl->d_ppars.FullScreen_PresentationInterval  = D3DPRESENT_INTERVAL_IMMEDIATE;
            pimpl->d_ppars.FullScreen_RefreshRateInHz       = D3DPRESENT_RATE_DEFAULT;
        }

        if (SUCCEEDED(pimpl->d_D3D->CreateDevice(adapter, D3DDEVTYPE_HAL, pimpl->d_window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pimpl->d_ppars, &pimpl->d_3DDevice)))
        {
            return true;
        }
        else
        {
            MessageBox(0, Win32AppHelper::CREATE_DEVICE_ERROR, Win32AppHelper::APPLICATION_NAME, MB_ICONERROR|MB_OK);
        }

        pimpl->d_D3D->Release();
        pimpl->d_D3D = 0;
    }
    else
    {
        MessageBox(0, Win32AppHelper::CREATE_D3D_ERROR, Win32AppHelper::APPLICATION_NAME, MB_ICONERROR|MB_OK);
    }

    return false;
}

/*************************************************************************
    Do reset of Direct3D device
*************************************************************************/
bool CEGuiD3D81BaseApplication::resetDirect3D(void)
{
    // perform ops needed prior to reset
    pimpl->d_renderer->preD3DReset();

    if (SUCCEEDED(pimpl->d_3DDevice->Reset(&pimpl->d_ppars)))
    {
        // re-build stuff now reset has been done.
        pimpl->d_renderer->postD3DReset();

        return true;
    }

    return false;
}

#endif
<|endoftext|>


<commit_before>#include <locale.h>
#include "CWinService.cpp"

static void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
	CWinService *lpCWinService = CWinService::getInstance();
	if (lpCWinService->RegisterService() != TRUE)
		return;

	BOOL bWinsockInit = FALSE;
	do
	{
		WSADATA wsa;
		if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
			break;
		bWinsockInit = TRUE;

		if (Init(NULL) != 0)
			break;

		HostInfo *phi = new HostInfo;
		phi->host = g_Host;
		phi->port = g_Port;
		g_hListenThread = CreateThread(NULL, 0, Listen, phi, 0, NULL);
		if (g_hListenThread)
		{
			lpCWinService->ServiceRunning();
			ShutdownInstances();	// g_hListenThread͂̒CloseHandle()
		}
		else
			delete phi;
		CleanUp();	// ShutdownInstances()DriversMapɃANZXXbh͖ȂĂ͂
	} while (0);

	if (bWinsockInit)
		WSACleanup();

	lpCWinService->ServiceStopped();

	return;
}

static int RunOnCmd(HINSTANCE hInstance)
{
	if (Init(hInstance) != 0)
		return -1;

	WSADATA wsa;
	if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
		return -2;

	HostInfo *phi = new HostInfo;
	phi->host = g_Host;
	phi->port = g_Port;
	int ret = (int)Listen(phi);

	ShutdownInstances();
	CleanUp();

	WSACleanup();
	return ret;
}

static BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
{
	switch (dwCtrlType)
	{
	case CTRL_C_EVENT:
		g_ShutdownEvent.Set();
		return TRUE;
	default:
		return FALSE;
	}
}

int _tmain(int argc, _TCHAR *argv[], _TCHAR *envp[])
{
#if _DEBUG
	_CrtMemState ostate, nstate, dstate;
	_CrtMemCheckpoint(&ostate);
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	HANDLE hLogFile = NULL;
#endif

	int ret = 0;
	CWinService *lpCWinService = CWinService::getInstance();
	if (lpCWinService)
	{
		_tsetlocale(LC_ALL, _T(""));
		do
		{
			if (argc == 1)
			{
				// ȂŋNꂽ
#if _DEBUG
				TCHAR szDrive[4];
				TCHAR szPath[MAX_PATH];
				TCHAR szLogFile[MAX_PATH + 16];
				GetModuleFileName(NULL, szPath, MAX_PATH);
				_tsplitpath_s(szPath, szDrive, 4, szPath, MAX_PATH, NULL, 0, NULL, 0);
				_tmakepath_s(szLogFile, MAX_PATH + 16, szDrive, szPath, _T("dbglog"), _T(".txt"));
				hLogFile = CreateFile(szLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
				SetFilePointer(hLogFile, 0, NULL, FILE_END);
				_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
				_CrtSetReportFile(_CRT_WARN, hLogFile);
				_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
				_CrtSetReportFile(_CRT_ERROR, hLogFile);
				_RPT0(_CRT_WARN, "--- PROCESS_START ---\n");
#endif
				if (lpCWinService->Run(ServiceMain))
				{
					// T[rX
					break;
				}
				else
				{
					// T[rXł͂Ȃ
					_tprintf(_T("R\[[hŊJn܂...Ctrl+CŏI\n"));
					SetConsoleCtrlHandler(HandlerRoutine, TRUE);
					ret = RunOnCmd(GetModuleHandle(NULL));
					switch (ret)
					{
					case -1:
						_tprintf(_T("init@C̓ǍɎs܂\n"));
						break;
					case -2:
						_tprintf(_T("winsock̏Ɏs܂\n"));
						break;
					case 1:
						_tprintf(_T("HostAhX̉Ɏs܂\n"));
						break;
					case 2:
						_tprintf(_T("bind()Ɏs܂\n"));
						break;
					case 3:
						_tprintf(_T("listen()Ɏs܂\n"));
						break;
					case 4:
						_tprintf(_T("accept()ɃG[܂\n"));
						break;
					case 0:
						_tprintf(_T("I܂\n"));
						break;
					}
					break;
				}
			}
			else
			{
				//
				BOOL done = FALSE;
				for (int i = 1; i < argc; i++)
				{
					if (_tcscmp(argv[i], _T("install")) == 0)
					{
						if (lpCWinService->Install())
							_tprintf(_T("WindowsT[rXƂēo^܂\n"));
						else
							_tprintf(_T("WindowsT[rXƂĂ̓o^Ɏs܂\n"));
						done = TRUE;
						break;
					}
					else if (_tcscmp(argv[i], _T("remove")) == 0)
					{
						if (lpCWinService->Remove())
							_tprintf(_T("WindowsT[rX폜܂\n"));
						else
							_tprintf(_T("WindowsT[rX̍폜Ɏs܂\n"));
						done = TRUE;
						break;
					}
					else if (_tcscmp(argv[i], _T("start")) == 0)
					{
						if (lpCWinService->Start())
							_tprintf(_T("WindowsT[rXN܂\n"));
						else
							_tprintf(_T("WindowsT[rX̋NɎs܂\n"));
						done = TRUE;
						break;
					}
					else if (_tcscmp(argv[i], _T("stop")) == 0)
					{
						if (lpCWinService->Stop())
							_tprintf(_T("WindowsT[rX~܂\n"));
						else
							_tprintf(_T("WindowsT[rX̒~Ɏs܂\n"));
						done = TRUE;
						break;
					}
					else if (_tcscmp(argv[i], _T("restart")) == 0)
					{
						if (lpCWinService->Restart())
							_tprintf(_T("WindowsT[rXċN܂\n"));
						else
							_tprintf(_T("WindowsT[rX̍ċNɎs܂\n"));
						done = TRUE;
						break;
					}
				}
				if (done)
					break;
			}
			// Usage\
			_tprintf(_T("Usage: %s <command>\n")
				_T("R}h\n")
				_T("  install    WindowsT[rXƂēo^܂\n")
				_T("  remove     WindowsT[rX폜܂\n")
				_T("  start      WindowsT[rXN܂\n")
				_T("  stop       WindowsT[rX~܂\n")
				_T("  restart    WindowsT[rXċN܂\n")
				_T("\n")
				_T("ȂŋNꂽꍇAR\[[hœ삵܂\n"),
				argv[0]);
		} while (0);
	}
	else
	{
		_tprintf(_T("WindowsT[rXNX̏Ɏs܂\n"));
		ret = -1;
	}

#if _DEBUG
	_CrtMemCheckpoint(&nstate);
	if (_CrtMemDifference(&dstate, &ostate, &nstate))
	{
		_CrtMemDumpStatistics(&dstate);
		_CrtMemDumpAllObjectsSince(&ostate);
	}
	if (hLogFile)
	{
		_RPT0(_CRT_WARN, "--- PROCESS_END ---\n");
		CloseHandle(hLogFile);
	}
#endif

	return ret;
}
<commit_msg>起こる事は無いエラーのチェックを削除<commit_after>#include <locale.h>
#include "CWinService.cpp"

static void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
	CWinService *lpCWinService = CWinService::getInstance();
	if (lpCWinService->RegisterService() != TRUE)
		return;

	BOOL bWinsockInit = FALSE;
	do
	{
		WSADATA wsa;
		if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
			break;
		bWinsockInit = TRUE;

		if (Init(NULL) != 0)
			break;

		HostInfo *phi = new HostInfo;
		phi->host = g_Host;
		phi->port = g_Port;
		g_hListenThread = CreateThread(NULL, 0, Listen, phi, 0, NULL);
		if (g_hListenThread)
		{
			lpCWinService->ServiceRunning();
			ShutdownInstances();	// g_hListenThread͂̒CloseHandle()
		}
		else
			delete phi;
		CleanUp();	// ShutdownInstances()DriversMapɃANZXXbh͖ȂĂ͂
	} while (0);

	if (bWinsockInit)
		WSACleanup();

	lpCWinService->ServiceStopped();

	return;
}

static int RunOnCmd(HINSTANCE hInstance)
{
	if (Init(hInstance) != 0)
		return -1;

	WSADATA wsa;
	if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
		return -2;

	HostInfo *phi = new HostInfo;
	phi->host = g_Host;
	phi->port = g_Port;
	int ret = (int)Listen(phi);

	ShutdownInstances();
	CleanUp();

	WSACleanup();
	return ret;
}

static BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
{
	switch (dwCtrlType)
	{
	case CTRL_C_EVENT:
		g_ShutdownEvent.Set();
		return TRUE;
	default:
		return FALSE;
	}
}

int _tmain(int argc, _TCHAR *argv[], _TCHAR *envp[])
{
#if _DEBUG
	_CrtMemState ostate, nstate, dstate;
	_CrtMemCheckpoint(&ostate);
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	HANDLE hLogFile = NULL;
#endif

	int ret = 0;
	CWinService *lpCWinService = CWinService::getInstance();

	_tsetlocale(LC_ALL, _T(""));
	do
	{
		if (argc == 1)
		{
			// ȂŋNꂽ
#if _DEBUG
			TCHAR szDrive[4];
			TCHAR szPath[MAX_PATH];
			TCHAR szLogFile[MAX_PATH + 16];
			GetModuleFileName(NULL, szPath, MAX_PATH);
			_tsplitpath_s(szPath, szDrive, 4, szPath, MAX_PATH, NULL, 0, NULL, 0);
			_tmakepath_s(szLogFile, MAX_PATH + 16, szDrive, szPath, _T("dbglog"), _T(".txt"));
			hLogFile = CreateFile(szLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
			SetFilePointer(hLogFile, 0, NULL, FILE_END);
			_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
			_CrtSetReportFile(_CRT_WARN, hLogFile);
			_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
			_CrtSetReportFile(_CRT_ERROR, hLogFile);
			_RPT0(_CRT_WARN, "--- PROCESS_START ---\n");
#endif
			if (lpCWinService->Run(ServiceMain))
			{
				// T[rX
				break;
			}
			else
			{
				// T[rXł͂Ȃ
				_tprintf(_T("R\[[hŊJn܂...Ctrl+CŏI\n"));
				SetConsoleCtrlHandler(HandlerRoutine, TRUE);
				ret = RunOnCmd(GetModuleHandle(NULL));
				switch (ret)
				{
				case -1:
					_tprintf(_T("init@C̓ǍɎs܂\n"));
					break;
				case -2:
					_tprintf(_T("winsock̏Ɏs܂\n"));
					break;
				case 1:
					_tprintf(_T("HostAhX̉Ɏs܂\n"));
					break;
				case 2:
					_tprintf(_T("bind()Ɏs܂\n"));
					break;
				case 3:
					_tprintf(_T("listen()Ɏs܂\n"));
					break;
				case 4:
					_tprintf(_T("accept()ɃG[܂\n"));
					break;
				case 0:
					_tprintf(_T("I܂\n"));
					break;
				}
				break;
			}
		}
		else
		{
			//
			BOOL done = FALSE;
			for (int i = 1; i < argc; i++)
			{
				if (_tcscmp(argv[i], _T("install")) == 0)
				{
					if (lpCWinService->Install())
						_tprintf(_T("WindowsT[rXƂēo^܂\n"));
					else
						_tprintf(_T("WindowsT[rXƂĂ̓o^Ɏs܂\n"));
					done = TRUE;
					break;
				}
				else if (_tcscmp(argv[i], _T("remove")) == 0)
				{
					if (lpCWinService->Remove())
						_tprintf(_T("WindowsT[rX폜܂\n"));
					else
						_tprintf(_T("WindowsT[rX̍폜Ɏs܂\n"));
					done = TRUE;
					break;
				}
				else if (_tcscmp(argv[i], _T("start")) == 0)
				{
					if (lpCWinService->Start())
						_tprintf(_T("WindowsT[rXN܂\n"));
					else
						_tprintf(_T("WindowsT[rX̋NɎs܂\n"));
					done = TRUE;
					break;
				}
				else if (_tcscmp(argv[i], _T("stop")) == 0)
				{
					if (lpCWinService->Stop())
						_tprintf(_T("WindowsT[rX~܂\n"));
					else
						_tprintf(_T("WindowsT[rX̒~Ɏs܂\n"));
					done = TRUE;
					break;
				}
				else if (_tcscmp(argv[i], _T("restart")) == 0)
				{
					if (lpCWinService->Restart())
						_tprintf(_T("WindowsT[rXċN܂\n"));
					else
						_tprintf(_T("WindowsT[rX̍ċNɎs܂\n"));
					done = TRUE;
					break;
				}
			}
			if (done)
				break;
		}
		// Usage\
		_tprintf(_T("Usage: %s <command>\n")
			_T("R}h\n")
			_T("  install    WindowsT[rXƂēo^܂\n")
			_T("  remove     WindowsT[rX폜܂\n")
			_T("  start      WindowsT[rXN܂\n")
			_T("  stop       WindowsT[rX~܂\n")
			_T("  restart    WindowsT[rXċN܂\n")
			_T("\n")
			_T("ȂŋNꂽꍇAR\[[hœ삵܂\n"),
			argv[0]);
	} while (0);

#if _DEBUG
	_CrtMemCheckpoint(&nstate);
	if (_CrtMemDifference(&dstate, &ostate, &nstate))
	{
		_CrtMemDumpStatistics(&dstate);
		_CrtMemDumpAllObjectsSince(&ostate);
	}
	if (hLogFile)
	{
		_RPT0(_CRT_WARN, "--- PROCESS_END ---\n");
		CloseHandle(hLogFile);
	}
#endif

	return ret;
}
<|endoftext|>