<commit_before>// Copyright 2015 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 "sky/engine/config.h"
#include "sky/engine/core/script/dart_controller.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
#include "dart/runtime/bin/embedded_dart_io.h"
#include "dart/runtime/include/dart_mirrors_api.h"
#include "gen/sky/platform/RuntimeEnabledFeatures.h"
#include "sky/engine/bindings/builtin.h"
#include "sky/engine/bindings/builtin_natives.h"
#include "sky/engine/bindings/builtin_sky.h"
#include "sky/engine/core/app/AbstractModule.h"
#include "sky/engine/core/app/Module.h"
#include "sky/engine/core/dom/Element.h"
#include "sky/engine/core/frame/LocalFrame.h"
#include "sky/engine/core/html/HTMLScriptElement.h"
#include "sky/engine/core/html/imports/HTMLImport.h"
#include "sky/engine/core/html/imports/HTMLImportChild.h"
#include "sky/engine/core/loader/FrameLoaderClient.h"
#include "sky/engine/core/script/dart_debugger.h"
#include "sky/engine/core/script/dart_dependency_catcher.h"
#include "sky/engine/core/script/dart_loader.h"
#include "sky/engine/core/script/dart_service_isolate.h"
#include "sky/engine/core/script/dom_dart_state.h"
#include "sky/engine/public/platform/Platform.h"
#include "sky/engine/tonic/dart_api_scope.h"
#include "sky/engine/tonic/dart_class_library.h"
#include "sky/engine/tonic/dart_error.h"
#include "sky/engine/tonic/dart_gc_controller.h"
#include "sky/engine/tonic/dart_invoke.h"
#include "sky/engine/tonic/dart_isolate_scope.h"
#include "sky/engine/tonic/dart_state.h"
#include "sky/engine/tonic/dart_wrappable.h"
#include "sky/engine/wtf/text/TextPosition.h"

namespace blink {

#if ENABLE(DART_STRICT)
static const char* kCheckedModeArgs[] = {"--enable_asserts",
                                         "--enable_type_checks",
                                         "--error_on_bad_type",
                                         "--error_on_bad_override",
#if WTF_OS_IOS
                                         "--no-profile"
#endif
};
#endif

extern const uint8_t* kDartVmIsolateSnapshotBuffer;
extern const uint8_t* kDartIsolateSnapshotBuffer;

DartController::DartController() : weak_factory_(this) {
}

DartController::~DartController() {
}

bool DartController::ImportChildLibraries(AbstractModule* module,
                                          Dart_Handle library) {
  // If the document has never seen an <import> tag, it won't have an import
  // controller, and thus will return null for its root HTMLImport.  We could
  // remove this null-check by always creating an ImportController.
  HTMLImport* root = module->document()->import();
  if (!root)
    return true;

  // TODO(abarth): Why doesn't HTMLImport do these casts for us?
  for (HTMLImportChild* child =
           static_cast<HTMLImportChild*>(root->firstChild());
       child; child = static_cast<HTMLImportChild*>(child->next())) {
    if (Element* link = child->link()) {
      String name = link->getAttribute(HTMLNames::asAttr);

      Module* child_module = child->module();
      if (!child_module)
        continue;
      for (const auto& entry : child_module->libraries()) {
        if (entry.library()->is_empty())
          continue;
        if (LogIfError(Dart_LibraryImportLibrary(
                library, entry.library()->dart_value(),
                StringToDart(dart_state(), name))))
          return false;
      }
    }
  }
  return true;
}

Dart_Handle DartController::CreateLibrary(AbstractModule* module,
                                          const String& source,
                                          const TextPosition& textPosition) {
  Dart_Handle library = Dart_LoadLibrary(
      StringToDart(dart_state(), module->UrlForLibraryAt(textPosition)),
      StringToDart(dart_state(), source), textPosition.m_line.zeroBasedInt(),
      textPosition.m_column.zeroBasedInt());

  if (LogIfError(library))
    return nullptr;

  if (!ImportChildLibraries(module, library))
    return nullptr;

  return library;
}

void DartController::DidLoadMainLibrary(KURL url) {
  DCHECK(Dart_CurrentIsolate() == dart_state()->isolate());
  DartApiScope dart_api_scope;

  if (LogIfError(Dart_FinalizeLoading(true)))
    return;

  Dart_Handle library = Dart_LookupLibrary(
      StringToDart(dart_state(), url.string()));
  // TODO(eseidel): We need to load a 404 page instead!
  if (LogIfError(library))
    return;
  DartInvokeAppField(library, ToDart("main"), 0, nullptr);
}

void DartController::LoadMainLibrary(const KURL& url, mojo::URLResponsePtr response) {
  DartLoader& loader = dart_state()->loader();
  DartDependencyCatcher dependency_catcher(loader);
  loader.LoadLibrary(url, response.Pass());
  loader.WaitForDependencies(dependency_catcher.dependencies(),
                             base::Bind(&DartController::DidLoadMainLibrary, weak_factory_.GetWeakPtr(), url));
}

void DartController::LoadScriptInModule(
    AbstractModule* module,
    const String& source,
    const TextPosition& position,
    const LoadFinishedCallback& finished_callback) {
  DartIsolateScope isolate_scope(dart_state()->isolate());
  DartApiScope dart_api_scope;

  DartDependencyCatcher dependency_catcher(dart_state()->loader());
  Dart_Handle library_handle = CreateLibrary(module, source, position);
  if (!library_handle)
    return finished_callback.Run(nullptr, nullptr);
  RefPtr<DartValue> library = DartValue::Create(dart_state(), library_handle);
  module->AddLibrary(library, position);

  // TODO(eseidel): Better if the library/module retained its dependencies and
  // dependency waiting could be separate from library creation.
  dart_state()->loader().WaitForDependencies(
      dependency_catcher.dependencies(),
      base::Bind(finished_callback, module, library));
}

void DartController::ExecuteLibraryInModule(AbstractModule* module,
                                            Dart_Handle library,
                                            HTMLScriptElement* script) {
  TRACE_EVENT1("sky", "DartController::ExecuteLibraryInModule",
               "url", module->url().ascii().toStdString());
  ASSERT(library);
  DCHECK(Dart_CurrentIsolate() == dart_state()->isolate());
  DartApiScope dart_api_scope;

  // Don't continue if we failed to load the module.
  if (LogIfError(Dart_FinalizeLoading(true)))
    return;
  const char* name = module->isApplication() ? "main" : "_init";

  // main() is required, but init() is not:
  // TODO(rmacnak): Dart_LookupFunction won't find re-exports, etc.
  Dart_Handle entry = Dart_LookupFunction(library, ToDart(name));
  if (module->isApplication()) {
    DartInvokeAppField(library, ToDart(name), 0, nullptr);
    return;
  }

  if (!Dart_IsFunction(entry))
    return;

  Dart_Handle args[] = {
    ToDart(script),
  };
  DartInvokeAppField(library, ToDart(name), arraysize(args), args);
}

static void UnhandledExceptionCallback(Dart_Handle error) {
  LOG(ERROR) << Dart_GetError(error);
}

static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag,
                                     Dart_Handle library,
                                     Dart_Handle url) {
  return DartLoader::HandleLibraryTag(tag, library, url);
}

static void IsolateShutdownCallback(void* callback_data) {
  // TODO(dart)
}

static bool IsServiceIsolateURL(const char* url_name) {
  return url_name != nullptr &&
      String(url_name) == DART_VM_SERVICE_ISOLATE_NAME;
}

static void EnsureHandleWatcherStarted() {
  static bool handle_watcher_started = false;
  if (handle_watcher_started)
    return;

  // TODO(dart): Call Dart_Cleanup (ensure the handle watcher isolate is closed)
  // during shutdown.
  Dart_Handle mojo_core_lib =
      Builtin::LoadAndCheckLibrary(Builtin::kMojoInternalLibrary);
  CHECK(!LogIfError((mojo_core_lib)));
  Dart_Handle handle_watcher_type = Dart_GetType(
      mojo_core_lib,
      Dart_NewStringFromCString("MojoHandleWatcher"),
      0,
      nullptr);
  CHECK(!LogIfError(handle_watcher_type));
  CHECK(!LogIfError(Dart_Invoke(
      handle_watcher_type,
      Dart_NewStringFromCString("_start"),
      0,
      nullptr)));

  // RunLoop until the handle watcher isolate is spun-up.
  CHECK(!LogIfError(Dart_RunLoop()));
  handle_watcher_started = true;
}

// TODO(rafaelw): Right now this only supports the creation of the handle
// watcher isolate and the service isolate. Presumably, we'll want application
// isolates to spawn their own isolates.
static Dart_Isolate IsolateCreateCallback(const char* script_uri,
                                          const char* main,
                                          const char* package_root,
                                          Dart_IsolateFlags* flags,
                                          void* callback_data,
                                          char** error) {

  if (IsServiceIsolateURL(script_uri)) {
    CHECK(kDartIsolateSnapshotBuffer);
    DartState* dart_state = new DartState();
    Dart_Isolate isolate = Dart_CreateIsolate(script_uri,
                                              "main",
                                              kDartIsolateSnapshotBuffer,
                                              nullptr,
                                              nullptr,
                                              error);
    CHECK(isolate) << error;
    dart_state->SetIsolate(isolate);
    CHECK(Dart_IsServiceIsolate(isolate));
    CHECK(!LogIfError(Dart_SetLibraryTagHandler(LibraryTagHandler)));
    {
      DartApiScope apiScope;
      Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
      Builtin::SetNativeResolver(Builtin::kMojoInternalLibrary);
      Builtin::SetNativeResolver(Builtin::kIOLibrary);
      BuiltinNatives::Init(BuiltinNatives::DartIOIsolate);
      // Start the handle watcher from the service isolate so it isn't available
      // for debugging or general Observatory interaction.
      EnsureHandleWatcherStarted();
      if (RuntimeEnabledFeatures::observatoryEnabled()) {
        std::string ip = "127.0.0.1";
        const intptr_t port = 8181;
        const bool service_isolate_booted =
            DartServiceIsolate::Startup(ip, port, LibraryTagHandler, error);
        CHECK(service_isolate_booted) << error;
      }
    }
    Dart_ExitIsolate();
    return isolate;
  }

  // Create & start the handle watcher isolate
  CHECK(kDartIsolateSnapshotBuffer);
  DartState* dart_state = new DartState();
  Dart_Isolate isolate = Dart_CreateIsolate("sky:handle_watcher", "",
      kDartIsolateSnapshotBuffer, nullptr, dart_state, error);
  CHECK(isolate) << error;
  dart_state->SetIsolate(isolate);

  CHECK(!LogIfError(Dart_SetLibraryTagHandler(LibraryTagHandler)));

  {
    DartApiScope apiScope;
    Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
    Builtin::SetNativeResolver(Builtin::kMojoInternalLibrary);
    Builtin::SetNativeResolver(Builtin::kIOLibrary);

    // Ensure the isolate has a root library.
    Dart_LoadScript(Dart_NewStringFromCString("dart:empty"),
                    Dart_NewStringFromCString(""), 0, 0);
  }

  Dart_ExitIsolate();

  CHECK(Dart_IsolateMakeRunnable(isolate));
  return isolate;
}

static void CallHandleMessage(base::WeakPtr<DartState> dart_state) {
  TRACE_EVENT0("sky", "CallHandleMessage");

  if (!dart_state)
    return;

  DartIsolateScope scope(dart_state->isolate());
  DartApiScope api_scope;
  LogIfError(Dart_HandleMessage());
}

static void MessageNotifyCallback(Dart_Isolate dest_isolate) {
  DCHECK(Platform::current());
  Platform::current()->mainThreadTaskRunner()->PostTask(FROM_HERE,
      base::Bind(&CallHandleMessage, DartState::From(dest_isolate)->GetWeakPtr()));
}

void DartController::CreateIsolateFor(PassOwnPtr<DOMDartState> state) {
  CHECK(kDartIsolateSnapshotBuffer);
  char* error = nullptr;
  dom_dart_state_ = state;
  Dart_Isolate isolate = Dart_CreateIsolate(
      dom_dart_state_->url().string().utf8().data(), "main",
      kDartIsolateSnapshotBuffer, nullptr,
      static_cast<DartState*>(dom_dart_state_.get()), &error);
  Dart_SetMessageNotifyCallback(MessageNotifyCallback);
  CHECK(isolate) << error;
  dom_dart_state_->SetIsolate(isolate);
  Dart_SetGcCallbacks(DartGCPrologue, DartGCEpilogue);
  CHECK(!LogIfError(Dart_SetLibraryTagHandler(LibraryTagHandler)));

  {
    DartApiScope apiScope;

    // Ensure the isolate has a root library.
    Dart_LoadScript(Dart_NewStringFromCString("dart:empty"),
                    Dart_NewStringFromCString(""), 0, 0);

    Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
    Builtin::SetNativeResolver(Builtin::kMojoInternalLibrary);
    Builtin::SetNativeResolver(Builtin::kIOLibrary);
    BuiltinNatives::Init(BuiltinNatives::MainIsolate);

    builtin_sky_ = adoptPtr(new BuiltinSky(dart_state()));
    dart_state()->class_library().set_provider(builtin_sky_.get());

    if (dart_state()->document())
      builtin_sky_->InstallWindow(dart_state());

    EnsureHandleWatcherStarted();
  }
  Dart_ExitIsolate();
}

void DartController::InstallView(View* view) {
  DartIsolateScope isolate_scope(dart_state()->isolate());
  DartApiScope dart_api_scope;

  builtin_sky_->InstallView(view);
}

void DartController::ClearForClose() {
  // Don't use a DartIsolateScope here since we never exit the isolate.
  Dart_EnterIsolate(dom_dart_state_->isolate());
  Dart_ShutdownIsolate();
  dom_dart_state_->SetIsolate(nullptr);
  dom_dart_state_.clear();
}

void DartController::InitVM() {
  int argc = 0;
  const char** argv = nullptr;

#if ENABLE(DART_STRICT)
  argc = arraysize(kCheckedModeArgs);
  argv = kCheckedModeArgs;
#endif

  dart::bin::BootstrapDartIo();

  CHECK(Dart_SetVMFlags(argc, argv));
  // This should be called before calling Dart_Initialize.
  DartDebugger::InitDebugger();
  CHECK(Dart_Initialize(kDartVmIsolateSnapshotBuffer,
                        IsolateCreateCallback,
                        nullptr,  // Isolate interrupt callback.
                        UnhandledExceptionCallback, IsolateShutdownCallback,
                        // File IO callbacks.
                        nullptr, nullptr, nullptr, nullptr, nullptr));
  // Wait for load port- ensures handle watcher and service isolates are
  // running.
  Dart_ServiceWaitForLoadPort();
}

} // namespace blink
<commit_msg>Revert "Update Dart dependency and patch dart_controller to account for"<commit_after>// Copyright 2015 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 "sky/engine/config.h"
#include "sky/engine/core/script/dart_controller.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
#include "dart/runtime/bin/embedded_dart_io.h"
#include "dart/runtime/include/dart_mirrors_api.h"
#include "gen/sky/platform/RuntimeEnabledFeatures.h"
#include "sky/engine/bindings/builtin.h"
#include "sky/engine/bindings/builtin_natives.h"
#include "sky/engine/bindings/builtin_sky.h"
#include "sky/engine/core/app/AbstractModule.h"
#include "sky/engine/core/app/Module.h"
#include "sky/engine/core/dom/Element.h"
#include "sky/engine/core/frame/LocalFrame.h"
#include "sky/engine/core/html/HTMLScriptElement.h"
#include "sky/engine/core/html/imports/HTMLImport.h"
#include "sky/engine/core/html/imports/HTMLImportChild.h"
#include "sky/engine/core/loader/FrameLoaderClient.h"
#include "sky/engine/core/script/dart_debugger.h"
#include "sky/engine/core/script/dart_dependency_catcher.h"
#include "sky/engine/core/script/dart_loader.h"
#include "sky/engine/core/script/dart_service_isolate.h"
#include "sky/engine/core/script/dom_dart_state.h"
#include "sky/engine/public/platform/Platform.h"
#include "sky/engine/tonic/dart_api_scope.h"
#include "sky/engine/tonic/dart_class_library.h"
#include "sky/engine/tonic/dart_error.h"
#include "sky/engine/tonic/dart_gc_controller.h"
#include "sky/engine/tonic/dart_invoke.h"
#include "sky/engine/tonic/dart_isolate_scope.h"
#include "sky/engine/tonic/dart_state.h"
#include "sky/engine/tonic/dart_wrappable.h"
#include "sky/engine/wtf/text/TextPosition.h"

namespace blink {

#if ENABLE(DART_STRICT)
static const char* kCheckedModeArgs[] = {"--enable_asserts",
                                         "--enable_type_checks",
                                         "--error_on_bad_type",
                                         "--error_on_bad_override",
#if WTF_OS_IOS
                                         "--no-profile"
#endif
};
#endif

extern const uint8_t* kDartVmIsolateSnapshotBuffer;
extern const uint8_t* kDartIsolateSnapshotBuffer;

DartController::DartController() : weak_factory_(this) {
}

DartController::~DartController() {
}

bool DartController::ImportChildLibraries(AbstractModule* module,
                                          Dart_Handle library) {
  // If the document has never seen an <import> tag, it won't have an import
  // controller, and thus will return null for its root HTMLImport.  We could
  // remove this null-check by always creating an ImportController.
  HTMLImport* root = module->document()->import();
  if (!root)
    return true;

  // TODO(abarth): Why doesn't HTMLImport do these casts for us?
  for (HTMLImportChild* child =
           static_cast<HTMLImportChild*>(root->firstChild());
       child; child = static_cast<HTMLImportChild*>(child->next())) {
    if (Element* link = child->link()) {
      String name = link->getAttribute(HTMLNames::asAttr);

      Module* child_module = child->module();
      if (!child_module)
        continue;
      for (const auto& entry : child_module->libraries()) {
        if (entry.library()->is_empty())
          continue;
        if (LogIfError(Dart_LibraryImportLibrary(
                library, entry.library()->dart_value(),
                StringToDart(dart_state(), name))))
          return false;
      }
    }
  }
  return true;
}

Dart_Handle DartController::CreateLibrary(AbstractModule* module,
                                          const String& source,
                                          const TextPosition& textPosition) {
  Dart_Handle library = Dart_LoadLibrary(
      StringToDart(dart_state(), module->UrlForLibraryAt(textPosition)),
      StringToDart(dart_state(), source), textPosition.m_line.zeroBasedInt(),
      textPosition.m_column.zeroBasedInt());

  if (LogIfError(library))
    return nullptr;

  if (!ImportChildLibraries(module, library))
    return nullptr;

  return library;
}

void DartController::DidLoadMainLibrary(KURL url) {
  DCHECK(Dart_CurrentIsolate() == dart_state()->isolate());
  DartApiScope dart_api_scope;

  if (LogIfError(Dart_FinalizeLoading(true)))
    return;

  Dart_Handle library = Dart_LookupLibrary(
      StringToDart(dart_state(), url.string()));
  // TODO(eseidel): We need to load a 404 page instead!
  if (LogIfError(library))
    return;
  DartInvokeAppField(library, ToDart("main"), 0, nullptr);
}

void DartController::LoadMainLibrary(const KURL& url, mojo::URLResponsePtr response) {
  DartLoader& loader = dart_state()->loader();
  DartDependencyCatcher dependency_catcher(loader);
  loader.LoadLibrary(url, response.Pass());
  loader.WaitForDependencies(dependency_catcher.dependencies(),
                             base::Bind(&DartController::DidLoadMainLibrary, weak_factory_.GetWeakPtr(), url));
}

void DartController::LoadScriptInModule(
    AbstractModule* module,
    const String& source,
    const TextPosition& position,
    const LoadFinishedCallback& finished_callback) {
  DartIsolateScope isolate_scope(dart_state()->isolate());
  DartApiScope dart_api_scope;

  DartDependencyCatcher dependency_catcher(dart_state()->loader());
  Dart_Handle library_handle = CreateLibrary(module, source, position);
  if (!library_handle)
    return finished_callback.Run(nullptr, nullptr);
  RefPtr<DartValue> library = DartValue::Create(dart_state(), library_handle);
  module->AddLibrary(library, position);

  // TODO(eseidel): Better if the library/module retained its dependencies and
  // dependency waiting could be separate from library creation.
  dart_state()->loader().WaitForDependencies(
      dependency_catcher.dependencies(),
      base::Bind(finished_callback, module, library));
}

void DartController::ExecuteLibraryInModule(AbstractModule* module,
                                            Dart_Handle library,
                                            HTMLScriptElement* script) {
  TRACE_EVENT1("sky", "DartController::ExecuteLibraryInModule",
               "url", module->url().ascii().toStdString());
  ASSERT(library);
  DCHECK(Dart_CurrentIsolate() == dart_state()->isolate());
  DartApiScope dart_api_scope;

  // Don't continue if we failed to load the module.
  if (LogIfError(Dart_FinalizeLoading(true)))
    return;
  const char* name = module->isApplication() ? "main" : "_init";

  // main() is required, but init() is not:
  // TODO(rmacnak): Dart_LookupFunction won't find re-exports, etc.
  Dart_Handle entry = Dart_LookupFunction(library, ToDart(name));
  if (module->isApplication()) {
    DartInvokeAppField(library, ToDart(name), 0, nullptr);
    return;
  }

  if (!Dart_IsFunction(entry))
    return;

  Dart_Handle args[] = {
    ToDart(script),
  };
  DartInvokeAppField(library, ToDart(name), arraysize(args), args);
}

static void UnhandledExceptionCallback(Dart_Handle error) {
  LOG(ERROR) << Dart_GetError(error);
}

static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag,
                                     Dart_Handle library,
                                     Dart_Handle url) {
  return DartLoader::HandleLibraryTag(tag, library, url);
}

static void IsolateShutdownCallback(void* callback_data) {
  // TODO(dart)
}

static bool IsServiceIsolateURL(const char* url_name) {
  return url_name != nullptr &&
      String(url_name) == DART_VM_SERVICE_ISOLATE_NAME;
}

static void EnsureHandleWatcherStarted() {
  static bool handle_watcher_started = false;
  if (handle_watcher_started)
    return;

  // TODO(dart): Call Dart_Cleanup (ensure the handle watcher isolate is closed)
  // during shutdown.
  Dart_Handle mojo_core_lib =
      Builtin::LoadAndCheckLibrary(Builtin::kMojoInternalLibrary);
  CHECK(!LogIfError((mojo_core_lib)));
  Dart_Handle handle_watcher_type = Dart_GetType(
      mojo_core_lib,
      Dart_NewStringFromCString("MojoHandleWatcher"),
      0,
      nullptr);
  CHECK(!LogIfError(handle_watcher_type));
  CHECK(!LogIfError(Dart_Invoke(
      handle_watcher_type,
      Dart_NewStringFromCString("_start"),
      0,
      nullptr)));

  // RunLoop until the handle watcher isolate is spun-up.
  CHECK(!LogIfError(Dart_RunLoop()));
  handle_watcher_started = true;
}

// TODO(rafaelw): Right now this only supports the creation of the handle
// watcher isolate and the service isolate. Presumably, we'll want application
// isolates to spawn their own isolates.
static Dart_Isolate IsolateCreateCallback(const char* script_uri,
                                          const char* main,
                                          const char* package_root,
                                          void* callback_data,
                                          char** error) {

  if (IsServiceIsolateURL(script_uri)) {
    CHECK(kDartIsolateSnapshotBuffer);
    DartState* dart_state = new DartState();
    Dart_Isolate isolate = Dart_CreateIsolate(script_uri,
                                              "main",
                                              kDartIsolateSnapshotBuffer,
                                              nullptr,
                                              error);
    CHECK(isolate) << error;
    dart_state->SetIsolate(isolate);
    CHECK(Dart_IsServiceIsolate(isolate));
    CHECK(!LogIfError(Dart_SetLibraryTagHandler(LibraryTagHandler)));
    {
      DartApiScope apiScope;
      Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
      Builtin::SetNativeResolver(Builtin::kMojoInternalLibrary);
      Builtin::SetNativeResolver(Builtin::kIOLibrary);
      BuiltinNatives::Init(BuiltinNatives::DartIOIsolate);
      // Start the handle watcher from the service isolate so it isn't available
      // for debugging or general Observatory interaction.
      EnsureHandleWatcherStarted();
      if (RuntimeEnabledFeatures::observatoryEnabled()) {
        std::string ip = "127.0.0.1";
        const intptr_t port = 8181;
        const bool service_isolate_booted =
            DartServiceIsolate::Startup(ip, port, LibraryTagHandler, error);
        CHECK(service_isolate_booted) << error;
      }
    }
    Dart_ExitIsolate();
    return isolate;
  }

  // Create & start the handle watcher isolate
  CHECK(kDartIsolateSnapshotBuffer);
  DartState* dart_state = new DartState();
  Dart_Isolate isolate = Dart_CreateIsolate("sky:handle_watcher", "",
      kDartIsolateSnapshotBuffer, dart_state, error);
  CHECK(isolate) << error;
  dart_state->SetIsolate(isolate);

  CHECK(!LogIfError(Dart_SetLibraryTagHandler(LibraryTagHandler)));

  {
    DartApiScope apiScope;
    Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
    Builtin::SetNativeResolver(Builtin::kMojoInternalLibrary);
    Builtin::SetNativeResolver(Builtin::kIOLibrary);

    // Ensure the isolate has a root library.
    Dart_LoadScript(Dart_NewStringFromCString("dart:empty"),
                    Dart_NewStringFromCString(""), 0, 0);
  }

  Dart_ExitIsolate();

  CHECK(Dart_IsolateMakeRunnable(isolate));
  return isolate;
}

static void CallHandleMessage(base::WeakPtr<DartState> dart_state) {
  TRACE_EVENT0("sky", "CallHandleMessage");

  if (!dart_state)
    return;

  DartIsolateScope scope(dart_state->isolate());
  DartApiScope api_scope;
  LogIfError(Dart_HandleMessage());
}

static void MessageNotifyCallback(Dart_Isolate dest_isolate) {
  DCHECK(Platform::current());
  Platform::current()->mainThreadTaskRunner()->PostTask(FROM_HERE,
      base::Bind(&CallHandleMessage, DartState::From(dest_isolate)->GetWeakPtr()));
}

void DartController::CreateIsolateFor(PassOwnPtr<DOMDartState> state) {
  CHECK(kDartIsolateSnapshotBuffer);
  char* error = nullptr;
  dom_dart_state_ = state;
  Dart_Isolate isolate = Dart_CreateIsolate(
      dom_dart_state_->url().string().utf8().data(), "main",
      kDartIsolateSnapshotBuffer,
      static_cast<DartState*>(dom_dart_state_.get()), &error);
  Dart_SetMessageNotifyCallback(MessageNotifyCallback);
  CHECK(isolate) << error;
  dom_dart_state_->SetIsolate(isolate);
  Dart_SetGcCallbacks(DartGCPrologue, DartGCEpilogue);
  CHECK(!LogIfError(Dart_SetLibraryTagHandler(LibraryTagHandler)));

  {
    DartApiScope apiScope;

    // Ensure the isolate has a root library.
    Dart_LoadScript(Dart_NewStringFromCString("dart:empty"),
                    Dart_NewStringFromCString(""), 0, 0);

    Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
    Builtin::SetNativeResolver(Builtin::kMojoInternalLibrary);
    Builtin::SetNativeResolver(Builtin::kIOLibrary);
    BuiltinNatives::Init(BuiltinNatives::MainIsolate);

    builtin_sky_ = adoptPtr(new BuiltinSky(dart_state()));
    dart_state()->class_library().set_provider(builtin_sky_.get());

    if (dart_state()->document())
      builtin_sky_->InstallWindow(dart_state());

    EnsureHandleWatcherStarted();
  }
  Dart_ExitIsolate();
}

void DartController::InstallView(View* view) {
  DartIsolateScope isolate_scope(dart_state()->isolate());
  DartApiScope dart_api_scope;

  builtin_sky_->InstallView(view);
}

void DartController::ClearForClose() {
  // Don't use a DartIsolateScope here since we never exit the isolate.
  Dart_EnterIsolate(dom_dart_state_->isolate());
  Dart_ShutdownIsolate();
  dom_dart_state_->SetIsolate(nullptr);
  dom_dart_state_.clear();
}

void DartController::InitVM() {
  int argc = 0;
  const char** argv = nullptr;

#if ENABLE(DART_STRICT)
  argc = arraysize(kCheckedModeArgs);
  argv = kCheckedModeArgs;
#endif

  dart::bin::BootstrapDartIo();

  CHECK(Dart_SetVMFlags(argc, argv));
  // This should be called before calling Dart_Initialize.
  DartDebugger::InitDebugger();
  CHECK(Dart_Initialize(kDartVmIsolateSnapshotBuffer,
                        IsolateCreateCallback,
                        nullptr,  // Isolate interrupt callback.
                        UnhandledExceptionCallback, IsolateShutdownCallback,
                        // File IO callbacks.
                        nullptr, nullptr, nullptr, nullptr, nullptr));
  // Wait for load port- ensures handle watcher and service isolates are
  // running.
  Dart_ServiceWaitForLoadPort();
}

} // namespace blink
<|endoftext|>


<commit_before>// Copyright 2015-2020 Elviss Strazdins. All rights reserved.

#ifndef OUZEL_GRAPHICS_RENDERER_RENDERER_HPP
#define OUZEL_GRAPHICS_RENDERER_RENDERER_HPP

#include <cstddef>
#include <mutex>
#include <queue>
#include "../RenderDevice.hpp"

namespace ouzel::graphics::renderer
{
    class Renderer final
    {
    public:
        using ResourceId = std::size_t;
        struct Command final
        {
            enum class Type
            {
                initCamera,
                initLight,
                initMaterial,
                initObject,
                destroyResource
            };

            Type type;
            ResourceId resourceId;
        };

        Renderer() = default;

        class Resource final
        {
        public:
            Resource() noexcept = default;
            Resource(Renderer& initRenderer):
                renderer{&initRenderer}, id{initRenderer.createResourceId()} {}

            ~Resource()
            {
                if (renderer && id) renderer->deleteResourceId(id);
            }

            Resource(const Resource& other) = delete;
            Resource& operator=(const Resource& other) = delete;

            Resource(Resource&& other) noexcept:
                renderer{other.renderer}, id{other.id}
            {
                other.renderer = nullptr;
                other.id = 0;
            }

            Resource& operator=(Resource&& other) noexcept
            {
                if (&other == this) return *this;

                renderer = other.renderer;
                id = other.id;
                other.renderer = nullptr;
                other.id = 0;

                return *this;
            }

            operator ResourceId() const noexcept { return id; }

        private:
            Renderer* renderer = nullptr;
            ResourceId id = 0;
        };

        void addCommand(const Command& command);

    private:
        ResourceId createResourceId()
        {
            const auto i = deletedResourceIds.begin();

            if (i == deletedResourceIds.end())
                return ++lastResourceId;
            else
            {
                std::size_t resourceId = *i;
                deletedResourceIds.erase(i);
                return resourceId;
            }
        }

        void deleteResourceId(ResourceId id)
        {
            deletedResourceIds.insert(id);
        }

        void render();

        ResourceId lastResourceId = 0;
        std::set<ResourceId> deletedResourceIds;

        std::queue<Command> commandQueue;
        std::mutex commandQueueMutex;
    };
}

#endif // OUZEL_GRAPHICS_RENDERER_RENDERER_HPP
<commit_msg>Add attribute setter commands<commit_after>// Copyright 2015-2020 Elviss Strazdins. All rights reserved.

#ifndef OUZEL_GRAPHICS_RENDERER_RENDERER_HPP
#define OUZEL_GRAPHICS_RENDERER_RENDERER_HPP

#include <cstddef>
#include <mutex>
#include <queue>
#include "../RenderDevice.hpp"

namespace ouzel::graphics::renderer
{
    class Renderer final
    {
    public:
        using ResourceId = std::size_t;
        struct Command final
        {
            enum class Type
            {
                initCamera,
                setCameraAttributes,
                initLight,
                setLightAttributes,
                initMaterial,
                setMaterialAttributes,
                initObject,
                setObjectAttributes,
                destroyResource
            };

            Type type;
            ResourceId resourceId;
        };

        Renderer() = default;

        class Resource final
        {
        public:
            Resource() noexcept = default;
            Resource(Renderer& initRenderer):
                renderer{&initRenderer}, id{initRenderer.createResourceId()} {}

            ~Resource()
            {
                if (renderer && id) renderer->deleteResourceId(id);
            }

            Resource(const Resource& other) = delete;
            Resource& operator=(const Resource& other) = delete;

            Resource(Resource&& other) noexcept:
                renderer{other.renderer}, id{other.id}
            {
                other.renderer = nullptr;
                other.id = 0;
            }

            Resource& operator=(Resource&& other) noexcept
            {
                if (&other == this) return *this;

                renderer = other.renderer;
                id = other.id;
                other.renderer = nullptr;
                other.id = 0;

                return *this;
            }

            operator ResourceId() const noexcept { return id; }

        private:
            Renderer* renderer = nullptr;
            ResourceId id = 0;
        };

        void addCommand(const Command& command);

    private:
        ResourceId createResourceId()
        {
            const auto i = deletedResourceIds.begin();

            if (i == deletedResourceIds.end())
                return ++lastResourceId;
            else
            {
                std::size_t resourceId = *i;
                deletedResourceIds.erase(i);
                return resourceId;
            }
        }

        void deleteResourceId(ResourceId id)
        {
            deletedResourceIds.insert(id);
        }

        void render();

        ResourceId lastResourceId = 0;
        std::set<ResourceId> deletedResourceIds;

        std::queue<Command> commandQueue;
        std::mutex commandQueueMutex;
    };
}

#endif // OUZEL_GRAPHICS_RENDERER_RENDERER_HPP
<|endoftext|>


<commit_before>#ifndef MESCALINE_AUDIO_ENGINE_H_INCLUDED
#define MESCALINE_AUDIO_ENGINE_H_INCLUDED

#include <Mescaline/Audio.hpp>
#include <Mescaline/Audio/AudioBus.hpp>
#include <Mescaline/Audio/CommandEngine.hpp>
#include <Mescaline/Audio/IO/Client.hpp>
#include <Mescaline/Audio/Node.hpp>
#include <Mescaline/Audio/SynthDef.hpp>
#include <Mescaline/Exception.hpp>
#include <Mescaline/Memory/Manager.hpp>

#include <boost/cstdint.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/unordered_map.hpp>
#include <boost/utility.hpp>

#include <bitset>
#include <string>
#include <vector>

#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
#include "lv2/lv2plug.in/ns/ext/atom/util.h"

namespace Mescaline { namespace Audio
{
    using namespace Memory;

    // class ControlBus : boost::noncopyable
    // {
    // public:
    //     typedef sample_t ValueType;
    //
    // private:
    //     BusId       m_id;
    //     Epoch       m_epoch;
    //     ValueType   m_data;
    // };

    struct EngineException : virtual Mescaline::Exception { };
    struct InvalidNodeId : virtual EngineException { };
    struct DuplicateNodeId : virtual EngineException { };
    struct ErrorInfoNodeIdTag { };
    typedef boost::error_info<ErrorInfoNodeIdTag, NodeId> ErrorInfoNodeId;

    class Node;

    class NodeMap
    {
        typedef std::vector<Node*> Nodes;

    public:
        typedef Nodes::const_reference const_reference;

        NodeMap(size_t maxNumNodes)
            : m_nodes(maxNumNodes, 0)
        { }

        void insert(Node* node);
        const_reference lookup(const NodeId& nodeId) const { return m_nodes.at(nodeId); }
        void release(const NodeId& nodeId);

    private:
        Nodes m_nodes;
    };

    class ResourceMap
    {
    public:
        void insert(Resource& resource)
        {
            pair<Map::iterator,bool> result = m_map.insert(Map::value_type(resource.id(), &resource));
            BOOST_ASSERT_MSG( result.second, "Duplicate resource" );
        }

        void remove(Resource& resource)
        {
            size_t n = m_map.erase(resource.id());
            BOOST_ASSERT_MSG( n > 0, "Missing resource" );
        }

        bool includes(const ResourceId& id)
        {
            return includesId(id);
        }

        Resource& lookup(const ResourceId& id)
        {
            Map::iterator it = m_map.find(id);
            BOOST_ASSERT( it != m_map.end() );
            return *it->second;
        }

        ResourceId nextId()
        {
            const uint32_t invalid = ResourceId();
            uint32_t id = m_map.size() + 1;
//            uint32_t id0 = id;
            while ((includesId(id) || id == invalid) /* && id != id0 */) {
                id++;
            }
//            BOOST_ASSERT_MSG( id != id0, "No more free resource IDs" );
            return ResourceId(id);
        }

    private:
        bool includesId(uint32_t id)
        {
            return m_map.find(id) != m_map.end();
        }

    private:
        typedef boost::unordered_map<uint32_t,Resource*> Map;
        Map m_map;
    };

    class Environment;

    class Command
    {
    public:
        Command(Environment& env, Context context)
            : m_env(env)
            , m_context(context)
        { }
        virtual ~Command() { }

        Environment& env() { return m_env; }
        Context context() const { return m_context; }

        virtual void perform(Context context) = 0;

    private:
        Environment&    m_env;
        Context         m_context;
    };

    class LV2Command : public Command
    {
    public:
        LV2Command(Environment& env, LV2_Atom* atom)
            : Command(env, kNonRealtime)
            , m_atom(atom)
        { }
        virtual ~LV2Command()
        { ::free(m_atom); }

        virtual void perform(Context context);

    private:
        LV2_Atom*    m_atom;
    };

    class Group;

    class Environment : public boost::noncopyable
    {
    public:
        struct Options
        {
            Options()
                : maxNumNodes(1024)
                , maxNumAudioBuses(128)
                , maxNumControlBuses(4096)
                , sampleRate(44100)
                , blockSize(64)
                , numHardwareInputChannels(2)
                , numHardwareOutputChannels(2)
            { }

            size_t maxNumNodes;
            size_t maxNumAudioBuses;
            size_t maxNumControlBuses;
            size_t sampleRate;
            size_t blockSize;
            size_t numHardwareInputChannels;
            size_t numHardwareOutputChannels;
        };

        Environment(Plugin::Manager& pluginManager, const Options& options);
        ~Environment();

        Plugin::Manager& pluginManager() { return m_synthDefs; }
        const Plugin::Manager::PluginHandle& lookupSynthDef(const char* name) { return m_synthDefs.lookup(name); }
        void registerSynthDef(SynthDef* synthDef) { /* m_synthDefs.insert(synthDef); */ }

        Group* rootNode() { return m_rootNode; }

        size_t sampleRate() const { return m_sampleRate; }
        size_t blockSize() const { return m_blockSize; }

        ResourceId nextResourceId() { return m_resources.nextId(); }

        AudioBus& audioBus(const ResourceId& busId)
        {
            return dynamic_cast<AudioBus&>(m_resources.lookup(busId));
        }

//        {
//            switch (busId.scope()) {
//                case AudioBusId::kInput:
//                    return m_audioInputChannels[busId.id()];
//                case AudioBusId::kOutput:
//                    return m_audioOutputChannels[busId.id()];
//                case AudioBusId::kInternal:
//                    return m_audioBuses[busId.id()];
//            }
//            BOOST_THROW_EXCEPTION(InvalidInput());
//        }

        RTMemoryManager& rtMem() { return m_rtMem; }

        const Epoch& epoch() const { return m_epoch; }

        void process(size_t numFrames, sample_t** inputs, sample_t** outputs);

        struct Uris
        {
            LV2_URID atom_String;
        };

        // URIs and messages
        const Uris& uris() const { return m_uris; }
        const LV2_Atom_Forge& atomForge() const { return m_forge; }

        void sendMessage(LV2_Atom* msg);

        // Commands
        void free(Context context, Command* cmd);

    protected:
        friend class Resource;

        void addResource(Resource& resource);
        void removeResource(Resource& resource);

    private:
//        void processMessages(MessageFIFO& fifo);
//        void dispatchMessages(const LV2_Atom_Sequencet* bundle);

    private:
        const size_t                m_sampleRate;
        const size_t                m_blockSize;
        RTMemoryManager             m_rtMem;
//        SynthDefMap                 m_synthDefs;
        Plugin::Manager&            m_synthDefs;
        ResourceMap                 m_resources;
        Group*                      m_rootNode;
//        NodeMap                     m_nodes;
        boost::ptr_vector<ExternalAudioBus> m_audioInputChannels;
        boost::ptr_vector<ExternalAudioBus> m_audioOutputChannels;
        boost::ptr_vector<InternalAudioBus> m_audioBuses;
        Epoch                       m_epoch;
        CommandChannel<Command>     m_commandChannel;
        CommandEngine<Command>      m_commandEngine;
        Uris                        m_uris;
        LV2_Atom_Forge              m_forge;
    };

    class Engine : public IO::Client
    {
    public:
        Engine(Plugin::Loader* pluginLoader);
        virtual ~Engine();

        virtual void configure(const IO::Driver& driver);
        virtual void process(size_t numFrames, sample_t** inputs, sample_t** outputs);

        Environment& env()
        {
            BOOST_ASSERT( m_env != 0 );
            return *m_env;
        }
        const Environment& env() const
        {
            BOOST_ASSERT( m_env != 0 );
            return *m_env;
        }

    private:
        Plugin::Loader*     m_pluginLoader;
        Plugin::Manager     m_pluginManager;
        Environment*        m_env;
    };
}; };

#endif // MESCALINE_AUDIO_ENGINE_H_INCLUDED
<commit_msg>Remove unused members<commit_after>#ifndef MESCALINE_AUDIO_ENGINE_H_INCLUDED
#define MESCALINE_AUDIO_ENGINE_H_INCLUDED

#include <Mescaline/Audio.hpp>
#include <Mescaline/Audio/AudioBus.hpp>
#include <Mescaline/Audio/CommandEngine.hpp>
#include <Mescaline/Audio/IO/Client.hpp>
#include <Mescaline/Audio/Node.hpp>
#include <Mescaline/Audio/SynthDef.hpp>
#include <Mescaline/Exception.hpp>
#include <Mescaline/Memory/Manager.hpp>

#include <boost/cstdint.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/unordered_map.hpp>
#include <boost/utility.hpp>

#include <bitset>
#include <string>
#include <vector>

#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
#include "lv2/lv2plug.in/ns/ext/atom/util.h"

namespace Mescaline { namespace Audio
{
    using namespace Memory;

    // class ControlBus : boost::noncopyable
    // {
    // public:
    //     typedef sample_t ValueType;
    //
    // private:
    //     BusId       m_id;
    //     Epoch       m_epoch;
    //     ValueType   m_data;
    // };

    struct EngineException : virtual Mescaline::Exception { };
    struct InvalidNodeId : virtual EngineException { };
    struct DuplicateNodeId : virtual EngineException { };
    struct ErrorInfoNodeIdTag { };
    typedef boost::error_info<ErrorInfoNodeIdTag, NodeId> ErrorInfoNodeId;

    class Node;

    class NodeMap
    {
        typedef std::vector<Node*> Nodes;

    public:
        typedef Nodes::const_reference const_reference;

        NodeMap(size_t maxNumNodes)
            : m_nodes(maxNumNodes, 0)
        { }

        void insert(Node* node);
        const_reference lookup(const NodeId& nodeId) const { return m_nodes.at(nodeId); }
        void release(const NodeId& nodeId);

    private:
        Nodes m_nodes;
    };

    class ResourceMap
    {
    public:
        void insert(Resource& resource)
        {
            pair<Map::iterator,bool> result = m_map.insert(Map::value_type(resource.id(), &resource));
            BOOST_ASSERT_MSG( result.second, "Duplicate resource" );
        }

        void remove(Resource& resource)
        {
            size_t n = m_map.erase(resource.id());
            BOOST_ASSERT_MSG( n > 0, "Missing resource" );
        }

        bool includes(const ResourceId& id)
        {
            return includesId(id);
        }

        Resource& lookup(const ResourceId& id)
        {
            Map::iterator it = m_map.find(id);
            BOOST_ASSERT( it != m_map.end() );
            return *it->second;
        }

        ResourceId nextId()
        {
            const uint32_t invalid = ResourceId();
            uint32_t id = m_map.size() + 1;
//            uint32_t id0 = id;
            while ((includesId(id) || id == invalid) /* && id != id0 */) {
                id++;
            }
//            BOOST_ASSERT_MSG( id != id0, "No more free resource IDs" );
            return ResourceId(id);
        }

    private:
        bool includesId(uint32_t id)
        {
            return m_map.find(id) != m_map.end();
        }

    private:
        typedef boost::unordered_map<uint32_t,Resource*> Map;
        Map m_map;
    };

    class Environment;

    class Command
    {
    public:
        Command(Environment& env, Context context)
            : m_env(env)
            , m_context(context)
        { }
        virtual ~Command() { }

        Environment& env() { return m_env; }
        Context context() const { return m_context; }

        virtual void perform(Context context) = 0;

    private:
        Environment&    m_env;
        Context         m_context;
    };

    class LV2Command : public Command
    {
    public:
        LV2Command(Environment& env, LV2_Atom* atom)
            : Command(env, kNonRealtime)
            , m_atom(atom)
        { }
        virtual ~LV2Command()
        { ::free(m_atom); }

        virtual void perform(Context context);

    private:
        LV2_Atom*    m_atom;
    };

    class Group;

    class Environment : public boost::noncopyable
    {
    public:
        struct Options
        {
            Options()
                : maxNumNodes(1024)
                , maxNumAudioBuses(128)
                , maxNumControlBuses(4096)
                , sampleRate(44100)
                , blockSize(64)
                , numHardwareInputChannels(2)
                , numHardwareOutputChannels(2)
            { }

            size_t maxNumNodes;
            size_t maxNumAudioBuses;
            size_t maxNumControlBuses;
            size_t sampleRate;
            size_t blockSize;
            size_t numHardwareInputChannels;
            size_t numHardwareOutputChannels;
        };

        Environment(Plugin::Manager& pluginManager, const Options& options);
        ~Environment();

        Plugin::Manager& pluginManager() { return m_synthDefs; }
        const Plugin::Manager::PluginHandle& lookupSynthDef(const char* name) { return m_synthDefs.lookup(name); }
        void registerSynthDef(SynthDef* synthDef) { /* m_synthDefs.insert(synthDef); */ }

        Group* rootNode() { return m_rootNode; }

        size_t sampleRate() const { return m_sampleRate; }
        size_t blockSize() const { return m_blockSize; }

        ResourceId nextResourceId() { return m_resources.nextId(); }

        AudioBus& audioBus(const ResourceId& busId)
        {
            return dynamic_cast<AudioBus&>(m_resources.lookup(busId));
        }

//        {
//            switch (busId.scope()) {
//                case AudioBusId::kInput:
//                    return m_audioInputChannels[busId.id()];
//                case AudioBusId::kOutput:
//                    return m_audioOutputChannels[busId.id()];
//                case AudioBusId::kInternal:
//                    return m_audioBuses[busId.id()];
//            }
//            BOOST_THROW_EXCEPTION(InvalidInput());
//        }

        RTMemoryManager& rtMem() { return m_rtMem; }

        const Epoch& epoch() const { return m_epoch; }

        void process(size_t numFrames, sample_t** inputs, sample_t** outputs);

        struct Uris
        {
            LV2_URID atom_String;
        };

        // URIs and messages
        const Uris& uris() const { return m_uris; }
        const LV2_Atom_Forge& atomForge() const { return m_forge; }

        void sendMessage(LV2_Atom* msg);

        // Commands
        void free(Context context, Command* cmd);

    protected:
        friend class Resource;

        void addResource(Resource& resource);
        void removeResource(Resource& resource);

    private:
        const size_t                m_sampleRate;
        const size_t                m_blockSize;
        RTMemoryManager             m_rtMem;
        Plugin::Manager&            m_synthDefs;
        ResourceMap                 m_resources;
        Group*                      m_rootNode;
        boost::ptr_vector<ExternalAudioBus> m_audioInputChannels;
        boost::ptr_vector<ExternalAudioBus> m_audioOutputChannels;
        boost::ptr_vector<InternalAudioBus> m_audioBuses;
        Epoch                       m_epoch;
        CommandChannel<Command>     m_commandChannel;
        CommandEngine<Command>      m_commandEngine;
        Uris                        m_uris;
        LV2_Atom_Forge              m_forge;
    };

    class Engine : public IO::Client
    {
    public:
        Engine(Plugin::Loader* pluginLoader);
        virtual ~Engine();

        virtual void configure(const IO::Driver& driver);
        virtual void process(size_t numFrames, sample_t** inputs, sample_t** outputs);

        Environment& env()
        {
            BOOST_ASSERT( m_env != 0 );
            return *m_env;
        }
        const Environment& env() const
        {
            BOOST_ASSERT( m_env != 0 );
            return *m_env;
        }

    private:
        Plugin::Loader*     m_pluginLoader;
        Plugin::Manager     m_pluginManager;
        Environment*        m_env;
    };
}; };

#endif // MESCALINE_AUDIO_ENGINE_H_INCLUDED
<|endoftext|>


<commit_before>#include "doctest.h"

DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#include <thread>
#include <mutex>
#include <exception>
#include <stdexcept>
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END

std::exception_ptr g_exception_ptr = nullptr;
std::mutex         g_mutex;

TEST_CASE("threads...") {
    auto call_from_thread = [](int value) {
        INFO("print me!");
        // one of these has to fail
        CHECK(value == 1);
        CHECK(value == 2);
    };

    int data_1 = 1;
    int data_2 = 2;
    CAPTURE(data_1); // will not be used for assertions in other threads

    // subcases have to be used only in the main thread (where the test runner is)
    SUBCASE("test runner thread") {
        call_from_thread(data_1);
    }

    // normal threads which are assumed not to throw
    SUBCASE("spawned threads") {
        std::thread t1(call_from_thread, data_1);
        std::thread t2(call_from_thread, data_2);

        t1.join();
        t2.join();
    }

    // exceptions from threads (that includes failing REQUIRE asserts) have to be handled explicitly
    SUBCASE("spawned threads with exception propagation") {
        auto might_throw = []() {
            try {
                REQUIRE(1 == 1);
                REQUIRE(1 == 2); // will fail and throw an exception
                MESSAGE("not reached!");
            } catch(...) {
                // make sure there are no races when dealing with the global exception ptr
                std::lock_guard<std::mutex> lock(g_mutex);

                // set the global exception pointer in case of an exception - might overwrite
                // another exception but here we care about propagating any exception - not all
                g_exception_ptr = std::current_exception();
            }
        };
        std::thread t1(might_throw);
        std::thread t2(might_throw);

        t1.join();
        t2.join();

        // if any thread has thrown an exception - rethrow it
        if(g_exception_ptr)
            std::rethrow_exception(g_exception_ptr);
    }
}
<commit_msg>builds should pass now...<commit_after>#include "doctest.h"

#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS

DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#include <thread>
#include <mutex>
#include <exception>
#include <stdexcept>
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END

std::exception_ptr g_exception_ptr = nullptr;
std::mutex         g_mutex;

TEST_CASE("threads...") {
    auto call_from_thread = [](int value) {
        INFO("print me!");
        // one of these has to fail
        CHECK(value == 1);
        CHECK(value == 2);
    };

    int data_1 = 1;
    int data_2 = 2;
    CAPTURE(data_1); // will not be used for assertions in other threads

    // subcases have to be used only in the main thread (where the test runner is)
    SUBCASE("test runner thread") {
        call_from_thread(data_1);
    }

    // normal threads which are assumed not to throw
    SUBCASE("spawned threads") {
        std::thread t1(call_from_thread, data_1);
        std::thread t2(call_from_thread, data_2);

        t1.join();
        t2.join();
    }

    // exceptions from threads (that includes failing REQUIRE asserts) have to be handled explicitly
    SUBCASE("spawned threads with exception propagation") {
        auto might_throw = []() {
            try {
                REQUIRE(1 == 1);
                REQUIRE(1 == 2); // will fail and throw an exception
                MESSAGE("not reached!");
            } catch(...) {
                // make sure there are no races when dealing with the global exception ptr
                std::lock_guard<std::mutex> lock(g_mutex);

                // set the global exception pointer in case of an exception - might overwrite
                // another exception but here we care about propagating any exception - not all
                g_exception_ptr = std::current_exception();
            }
        };
        std::thread t1(might_throw);
        std::thread t2(might_throw);

        t1.join();
        t2.join();

        // if any thread has thrown an exception - rethrow it
        if(g_exception_ptr)
            std::rethrow_exception(g_exception_ptr);
    }
}

#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
**     the names of its contributors may be used to endorse or promote
**     products derived from this software without specific prior written
**     permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/

#include "daypage.h"

#include "calendardemo.h"
#include <QtGui>
#include <qtorganizer.h>

QTM_USE_NAMESPACE

Q_DECLARE_METATYPE(QOrganizerItem)

DayPage::DayPage(QWidget *parent)
    :QWidget(parent),
    m_manager(0),
    m_dateLabel(0),
    m_itemList(0),
    m_menuBar(0)
{
    QVBoxLayout *mainLayout = new QVBoxLayout();

    QHBoxLayout *dateLayout = new QHBoxLayout();
    m_dateLabel = new QLabel(this);
    m_dateLabel->setAlignment(Qt::AlignCenter);
    dateLayout->addWidget(m_dateLabel);
    dateLayout->addStretch();
#ifndef Q_OS_SYMBIAN
    QPushButton* backButton = new QPushButton("View Month",this);
    connect(backButton,SIGNAL(clicked()),this,SLOT(viewMonthClicked()));
    dateLayout->addWidget(backButton);
#endif
    mainLayout->addLayout(dateLayout);

    m_itemList = new QListWidget(this);
    mainLayout->addWidget(m_itemList);
    connect(m_itemList, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(itemDoubleClicked(QListWidgetItem *)));

    QHBoxLayout* hbLayout = new QHBoxLayout();
    QPushButton* editEventButton = new QPushButton("Edit",this);
    connect(editEventButton,SIGNAL(clicked()),this,SLOT(editItem()));
    hbLayout->addWidget(editEventButton);
    QPushButton* removeEventButton = new QPushButton("Remove",this);
    connect(removeEventButton,SIGNAL(clicked()),this,SLOT(removeItem()));
    hbLayout->addWidget(removeEventButton);
    mainLayout->addLayout(hbLayout);

#ifdef Q_OS_SYMBIAN
    // Add softkey for symbian
    QAction* backSoftKey = new QAction("View Month", this);
    backSoftKey->setSoftKeyRole(QAction::NegativeSoftKey);
    addAction(backSoftKey);
    connect(backSoftKey, SIGNAL(triggered(bool)), this, SLOT(viewMonthClicked()));
#endif

    setLayout(mainLayout);
}

DayPage::~DayPage()
{

}

#ifdef Q_OS_SYMBIAN
void DayPage::setMenu(QMenu *menu)
{
    // Add softkey for symbian
    QAction* optionsSoftKey = new QAction("Options", this);
    optionsSoftKey->setSoftKeyRole(QAction::PositiveSoftKey);
    optionsSoftKey->setMenu(menu);
    addAction(optionsSoftKey);
}
#endif

void DayPage::refresh()
{

    m_dateLabel->setText(m_day.toString());
    m_itemList->clear();

    // Items
    QList<QOrganizerItem> items = m_manager->items();

    // Today's item instances
    QOrganizerItemDateTimePeriodFilter filter;
    filter.setStartPeriod(QDateTime(m_day, QTime(0, 0, 0)));
    filter.setEndPeriod(QDateTime(m_day, QTime(23, 59, 59)));
    QList<QOrganizerItem> instances = m_manager->itemInstances(filter);

    foreach (const QOrganizerItem &item, items)
    {
        QOrganizerEventTimeRange eventTimeRange = item.detail<QOrganizerEventTimeRange>();
        if (!eventTimeRange.isEmpty()) {
            QOrganizerItemGuid itemGuid = item.detail<QOrganizerItemGuid>();
            QOrganizerEventTimeRange itemTimeRange = item.detail<QOrganizerEventTimeRange>();
            bool instancesContainGuid = false;
            foreach (QOrganizerItem instance, instances) {
                if (instance.detail<QOrganizerItemGuid>() == itemGuid
                    && instance.detail<QOrganizerEventTimeRange>().startDateTime() != itemTimeRange.startDateTime()) {
                    instancesContainGuid = true;
                    break;
                }
            }

            if (eventTimeRange.startDateTime().date() == m_day && !instancesContainGuid) {
                QString time = eventTimeRange.startDateTime().time().toString("hh:mm");
                QListWidgetItem* listItem = new QListWidgetItem();
                listItem->setText(QString("Event:%1-%2").arg(time).arg(item.displayLabel()));
                QVariant data = QVariant::fromValue<QOrganizerItem>(item);
                listItem->setData(ORGANIZER_ITEM_ROLE, data);
                m_itemList->addItem(listItem);
            }
        }

        QOrganizerTodoTimeRange todoTimeRange = item.detail<QOrganizerTodoTimeRange>();
        if (!todoTimeRange.isEmpty()) {
            if (todoTimeRange.startDateTime().date() == m_day) {
                QString time = todoTimeRange.startDateTime().time().toString("hh:mm");
                QListWidgetItem* listItem = new QListWidgetItem();
                listItem->setText(QString("Todo:%1-%2").arg(time).arg(item.displayLabel()));
                QVariant data = QVariant::fromValue<QOrganizerItem>(item);
                listItem->setData(ORGANIZER_ITEM_ROLE, data);
                m_itemList->addItem(listItem);
            }
        }

        QOrganizerJournalTimeRange journalTimeRange = item.detail<QOrganizerJournalTimeRange>();
        if (!journalTimeRange.isEmpty()) {
            if (journalTimeRange.entryDateTime().date() == m_day) {
                QString time = journalTimeRange.entryDateTime().time().toString("hh:mm");
                QListWidgetItem* listItem = new QListWidgetItem();
                listItem->setText(QString("Journal:%1-%2").arg(time).arg(item.displayLabel()));
                QVariant data = QVariant::fromValue<QOrganizerItem>(item);
                listItem->setData(ORGANIZER_ITEM_ROLE, data);
                m_itemList->addItem(listItem);
            }
        }

        // TODO: other item types
    }

    foreach (const QOrganizerItem &instance, instances)
    {
        QString type = instance.type();
        if (type == QOrganizerItemType::TypeEventOccurrence) {
            QOrganizerEventOccurrence occurrence = static_cast<QOrganizerEventOccurrence>(instance);
            QString time = occurrence.startDateTime().time().toString("hh:mm");
            QListWidgetItem* listItem = new QListWidgetItem();
            listItem->setText(QString("Event occurrence:%1-%2").arg(time).arg(occurrence.displayLabel()));
            QVariant data = QVariant::fromValue<QOrganizerItem>(instance);
            listItem->setData(ORGANIZER_ITEM_ROLE, data);
            m_itemList->addItem(listItem);
        }
    }

    if (m_itemList->count() == 0)
        m_itemList->addItem("(no entries)");
}

void DayPage::changeManager(QOrganizerItemManager *manager)
{
    m_manager = manager;
}

void DayPage::dayChanged(QDate date)
{
    m_day = date;
}

void DayPage::itemDoubleClicked(QListWidgetItem *listItem)
{
    if (!listItem)
        return;

    QOrganizerItem organizerItem = listItem->data(ORGANIZER_ITEM_ROLE).value<QOrganizerItem>();
    if (!organizerItem.isEmpty())
        emit showEditPage(organizerItem);
}

void DayPage::viewMonthClicked()
{
    emit showMonthPage();
}

void DayPage::editItem()
{
    QListWidgetItem *listItem = m_itemList->currentItem();
    if (!listItem)
        return;

    QOrganizerItem organizerItem = listItem->data(ORGANIZER_ITEM_ROLE).value<QOrganizerItem>();
    if (!organizerItem.isEmpty())
        emit showEditPage(organizerItem);
}

void DayPage::removeItem()
{
    QListWidgetItem *listItem = m_itemList->currentItem();
    if (!listItem)
        return;

    QOrganizerItem organizerItem = listItem->data(ORGANIZER_ITEM_ROLE).value<QOrganizerItem>();
    if (organizerItem.isEmpty())
        return;

    m_manager->removeItem(organizerItem.localId());
    if (m_manager->error())
        QMessageBox::information(this, "Failed!", QString("Failed to remove item!\n(error code %1)").arg(m_manager->error()));
    else
        delete m_itemList->takeItem(m_itemList->currentRow());

    if (m_itemList->count() == 0)
        m_itemList->addItem("(no entries)");
}

void DayPage::showEvent(QShowEvent *event)
{
    window()->setWindowTitle(m_day.toString("dddd"));
    QWidget::showEvent(event);
}

<commit_msg>Compile fix with new items APIs.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
**     the names of its contributors may be used to endorse or promote
**     products derived from this software without specific prior written
**     permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/

#include "daypage.h"

#include "calendardemo.h"
#include <QtGui>
#include <qtorganizer.h>

QTM_USE_NAMESPACE

Q_DECLARE_METATYPE(QOrganizerItem)

DayPage::DayPage(QWidget *parent)
    :QWidget(parent),
    m_manager(0),
    m_dateLabel(0),
    m_itemList(0),
    m_menuBar(0)
{
    QVBoxLayout *mainLayout = new QVBoxLayout();

    QHBoxLayout *dateLayout = new QHBoxLayout();
    m_dateLabel = new QLabel(this);
    m_dateLabel->setAlignment(Qt::AlignCenter);
    dateLayout->addWidget(m_dateLabel);
    dateLayout->addStretch();
#ifndef Q_OS_SYMBIAN
    QPushButton* backButton = new QPushButton("View Month",this);
    connect(backButton,SIGNAL(clicked()),this,SLOT(viewMonthClicked()));
    dateLayout->addWidget(backButton);
#endif
    mainLayout->addLayout(dateLayout);

    m_itemList = new QListWidget(this);
    mainLayout->addWidget(m_itemList);
    connect(m_itemList, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(itemDoubleClicked(QListWidgetItem *)));

    QHBoxLayout* hbLayout = new QHBoxLayout();
    QPushButton* editEventButton = new QPushButton("Edit",this);
    connect(editEventButton,SIGNAL(clicked()),this,SLOT(editItem()));
    hbLayout->addWidget(editEventButton);
    QPushButton* removeEventButton = new QPushButton("Remove",this);
    connect(removeEventButton,SIGNAL(clicked()),this,SLOT(removeItem()));
    hbLayout->addWidget(removeEventButton);
    mainLayout->addLayout(hbLayout);

#ifdef Q_OS_SYMBIAN
    // Add softkey for symbian
    QAction* backSoftKey = new QAction("View Month", this);
    backSoftKey->setSoftKeyRole(QAction::NegativeSoftKey);
    addAction(backSoftKey);
    connect(backSoftKey, SIGNAL(triggered(bool)), this, SLOT(viewMonthClicked()));
#endif

    setLayout(mainLayout);
}

DayPage::~DayPage()
{

}

#ifdef Q_OS_SYMBIAN
void DayPage::setMenu(QMenu *menu)
{
    // Add softkey for symbian
    QAction* optionsSoftKey = new QAction("Options", this);
    optionsSoftKey->setSoftKeyRole(QAction::PositiveSoftKey);
    optionsSoftKey->setMenu(menu);
    addAction(optionsSoftKey);
}
#endif

void DayPage::refresh()
{

    m_dateLabel->setText(m_day.toString());
    m_itemList->clear();

    // Items
    QList<QOrganizerItem> items = m_manager->items();

    // Today's item instances
    QList<QOrganizerItem> instances = m_manager->items(QDateTime(m_day, QTime(0, 0, 0)), QDateTime(m_day, QTime(23, 59, 59)));

    foreach (const QOrganizerItem &item, items)
    {
        QOrganizerEventTimeRange eventTimeRange = item.detail<QOrganizerEventTimeRange>();
        if (!eventTimeRange.isEmpty()) {
            QOrganizerItemGuid itemGuid = item.detail<QOrganizerItemGuid>();
            QOrganizerEventTimeRange itemTimeRange = item.detail<QOrganizerEventTimeRange>();
            bool instancesContainGuid = false;
            foreach (QOrganizerItem instance, instances) {
                if (instance.detail<QOrganizerItemGuid>() == itemGuid
                    && instance.detail<QOrganizerEventTimeRange>().startDateTime() != itemTimeRange.startDateTime()) {
                    instancesContainGuid = true;
                    break;
                }
            }

            if (eventTimeRange.startDateTime().date() == m_day && !instancesContainGuid) {
                QString time = eventTimeRange.startDateTime().time().toString("hh:mm");
                QListWidgetItem* listItem = new QListWidgetItem();
                listItem->setText(QString("Event:%1-%2").arg(time).arg(item.displayLabel()));
                QVariant data = QVariant::fromValue<QOrganizerItem>(item);
                listItem->setData(ORGANIZER_ITEM_ROLE, data);
                m_itemList->addItem(listItem);
            }
        }

        QOrganizerTodoTimeRange todoTimeRange = item.detail<QOrganizerTodoTimeRange>();
        if (!todoTimeRange.isEmpty()) {
            if (todoTimeRange.startDateTime().date() == m_day) {
                QString time = todoTimeRange.startDateTime().time().toString("hh:mm");
                QListWidgetItem* listItem = new QListWidgetItem();
                listItem->setText(QString("Todo:%1-%2").arg(time).arg(item.displayLabel()));
                QVariant data = QVariant::fromValue<QOrganizerItem>(item);
                listItem->setData(ORGANIZER_ITEM_ROLE, data);
                m_itemList->addItem(listItem);
            }
        }

        QOrganizerJournalTimeRange journalTimeRange = item.detail<QOrganizerJournalTimeRange>();
        if (!journalTimeRange.isEmpty()) {
            if (journalTimeRange.entryDateTime().date() == m_day) {
                QString time = journalTimeRange.entryDateTime().time().toString("hh:mm");
                QListWidgetItem* listItem = new QListWidgetItem();
                listItem->setText(QString("Journal:%1-%2").arg(time).arg(item.displayLabel()));
                QVariant data = QVariant::fromValue<QOrganizerItem>(item);
                listItem->setData(ORGANIZER_ITEM_ROLE, data);
                m_itemList->addItem(listItem);
            }
        }

        // TODO: other item types
    }

    foreach (const QOrganizerItem &instance, instances)
    {
        QString type = instance.type();
        if (type == QOrganizerItemType::TypeEventOccurrence) {
            QOrganizerEventOccurrence occurrence = static_cast<QOrganizerEventOccurrence>(instance);
            QString time = occurrence.startDateTime().time().toString("hh:mm");
            QListWidgetItem* listItem = new QListWidgetItem();
            listItem->setText(QString("Event occurrence:%1-%2").arg(time).arg(occurrence.displayLabel()));
            QVariant data = QVariant::fromValue<QOrganizerItem>(instance);
            listItem->setData(ORGANIZER_ITEM_ROLE, data);
            m_itemList->addItem(listItem);
        }
    }

    if (m_itemList->count() == 0)
        m_itemList->addItem("(no entries)");
}

void DayPage::changeManager(QOrganizerItemManager *manager)
{
    m_manager = manager;
}

void DayPage::dayChanged(QDate date)
{
    m_day = date;
}

void DayPage::itemDoubleClicked(QListWidgetItem *listItem)
{
    if (!listItem)
        return;

    QOrganizerItem organizerItem = listItem->data(ORGANIZER_ITEM_ROLE).value<QOrganizerItem>();
    if (!organizerItem.isEmpty())
        emit showEditPage(organizerItem);
}

void DayPage::viewMonthClicked()
{
    emit showMonthPage();
}

void DayPage::editItem()
{
    QListWidgetItem *listItem = m_itemList->currentItem();
    if (!listItem)
        return;

    QOrganizerItem organizerItem = listItem->data(ORGANIZER_ITEM_ROLE).value<QOrganizerItem>();
    if (!organizerItem.isEmpty())
        emit showEditPage(organizerItem);
}

void DayPage::removeItem()
{
    QListWidgetItem *listItem = m_itemList->currentItem();
    if (!listItem)
        return;

    QOrganizerItem organizerItem = listItem->data(ORGANIZER_ITEM_ROLE).value<QOrganizerItem>();
    if (organizerItem.isEmpty())
        return;

    m_manager->removeItem(organizerItem.localId());
    if (m_manager->error())
        QMessageBox::information(this, "Failed!", QString("Failed to remove item!\n(error code %1)").arg(m_manager->error()));
    else
        delete m_itemList->takeItem(m_itemList->currentRow());

    if (m_itemList->count() == 0)
        m_itemList->addItem("(no entries)");
}

void DayPage::showEvent(QShowEvent *event)
{
    window()->setWindowTitle(m_day.toString("dddd"));
    QWidget::showEvent(event);
}

<|endoftext|>


<commit_before>// Copyright 2010-2014 Google
// 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.
//
// ACP 2014 challenge

#include <cstdio>

#include "base/commandlineflags.h"
#include "base/file.h"
#include "base/filelinereader.h"
#include "base/hash.h"
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/split.h"
#include "base/map_util.h"
#include "base/stringprintf.h"
#include "base/strtoint.h"
#include "constraint_solver/constraint_solver.h"
#include "constraint_solver/routing.h"
#include "util/tuple_set.h"

DEFINE_string(input, "", "");
DEFINE_string(solution, "", "");
DEFINE_int32(ls_seed, 0, "ls seed");
DEFINE_int32(ls_size, 8, "ls size");
DEFINE_int32(ls_perm, 11, "ls perm");

DECLARE_string(routing_first_solution);
DECLARE_bool(routing_no_lns);
DECLARE_bool(routing_trace);
DECLARE_bool(routing_guided_local_search);

namespace operations_research {

class AcpData {
 public:
  AcpData()
      : num_periods_(-1), num_products_(-1), inventory_cost_(0), state_(0) {}

  void Load(const std::string& filename) {
    FileLineReader reader(filename.c_str());
    reader.set_line_callback(
        NewPermanentCallback(this, &AcpData::ProcessNewLine));
    reader.Reload();
    if (!reader.loaded_successfully()) {
      LOG(ERROR) << "Could not open acp challenge file";
    }
  }

  void ProcessNewLine(char* const line) {
    const std::vector<std::string> words =
        strings::Split(line, " ", strings::SkipEmpty());
    if (words.empty()) return;
    switch (state_) {
      case 0: {
        num_periods_ = atoi32(words[0]);
        state_ = 1;
        break;
      }
      case 1: {
        num_products_ = atoi32(words[0]);
        state_ = 2;
        break;
      }
      case 2: {
        due_dates_per_product_.resize(due_dates_per_product_.size() + 1);
        CHECK_EQ(words.size(), num_periods_) << "Error with line " << line;
        for (int i = 0; i < num_periods_; ++i) {
          if (atoi32(words[i]) == 1) {
            due_dates_per_product_.back().push_back(i);
          }
        }
        if (due_dates_per_product_.size() == num_products_) {
          state_ = 3;
        }
        break;
      }
      case 3: {
        inventory_cost_ = atoi32(words[0]);
        state_ = 4;
        break;
      }
      case 4: {
        transitions_.resize(transitions_.size() + 1);
        CHECK_EQ(words.size(), num_products_);
        for (int i = 0; i < num_products_; ++i) {
          transitions_.back().push_back(atoi32(words[i]));
        }
        break;
      }
      default: {
        LOG(ERROR) << "Should not be here";
      }
    }
  }

  std::string DebugString() const {
    return StringPrintf("AcpData(%d periods, %d products, %d cost)",
                        num_periods_, num_products_, inventory_cost_);
  }

  const std::vector<std::vector<int>>& due_dates_per_product() const {
    return due_dates_per_product_;
  }

  const std::vector<std::vector<int>>& transitions() const {
    return transitions_;
  }

  int num_periods() const { return num_periods_; }
  int num_products() const { return num_products_; }
  int inventory_cost() const { return inventory_cost_; }

 private:
  int num_periods_;
  int num_products_;
  int inventory_cost_;
  std::vector<std::vector<int>> due_dates_per_product_;
  std::vector<std::vector<int>> transitions_;
  int state_;
};

void LoadSolution(const std::string& filename, std::vector<int>* vec) {
  File* const file = File::OpenOrDie(filename, "r");
  std::string line;
  file->ReadToString(&line, 10000);
  const std::vector<std::string> words =
      strings::Split(line, " ", strings::SkipEmpty());
  LOG(INFO) << "Solution file has " << words.size() << " entries";
  vec->clear();
  for (const std::string& word : words) {
    vec->push_back(atoi32(word));
  }
  LOG(INFO) << "  - loaded " << strings::Join(*vec, " ");
}

int Evaluate(const AcpData& data, const std::vector<int>& schedule) {
  std::vector<int> indices(data.num_products(), 0);
  int early_days = 0;
  for (int i = 0; i < schedule.size(); ++i) {
    const int product = schedule[i];
    if (product >= data.num_products() || product < -1) {
      return kint32max;
    }
    if (product != -1) {
      const int index = indices[product];
      if (index >= data.due_dates_per_product()[product].size()) {
        LOG(INFO) << "Strange";
        return kint32max;
      }
      indices[product]++;
      const int due_date = data.due_dates_per_product()[product][index];
      if (i > due_date) {
        return kint32max;
      }
      early_days += due_date - i;
    }
  }

  int previous = -1;
  int transition_cost = 0;
  for (const int product : schedule) {
    if (previous != -1  && product != -1 && previous != product) {
      transition_cost += data.transitions()[previous][product];
    }
    if (product != -1) {
      previous = product;
    }
  }
  return transition_cost + early_days * data.inventory_cost();
}

int64 OneDistance(RoutingModel::NodeIndex from, RoutingModel::NodeIndex to) {
  return 1;
}

class ProductMatrix {
 public:
  ProductMatrix(const AcpData& data, const std::vector<int>& item_to_product)
      : data_(data), item_to_product_(item_to_product) {}

  int64 Distance(RoutingModel::NodeIndex from,
                 RoutingModel::NodeIndex to) const {
    if (from.value() == 0 || to.value() == 0) {
      return 0;
    }
    const int index1 = item_to_product_[from.value() - 1];
    const int index2 = item_to_product_[to.value() - 1];
    return data_.transitions()[index1][index2];
  }

 private:
  const AcpData& data_;
  const std::vector<int>& item_to_product_;
};

void Solve(const std::string& filename, const std::string& solution_file) {

  const char* kTime = "Time";

  LOG(INFO) << "Load " << filename;
  AcpData data;
  data.Load(filename);

  std::vector<int> best;
  int best_cost = kint32max;
  if (!solution_file.empty()) {
    LoadSolution(solution_file, &best);
    best.resize(data.num_periods());
    best_cost = Evaluate(data, best);
    LOG(INFO) << "Initial solution cost = " << best_cost;
  }

  int num_active_periods = 0;
  std::vector<int> due_dates_per_period(data.num_periods(), 0);
  for (const std::vector<int>& d : data.due_dates_per_product()) {
    for (const int v : d) {
      due_dates_per_period[v]++;
      num_active_periods++;
    }
  }
  LOG(INFO) << "num active periods = " << num_active_periods;
  std::vector<bool> active_periods(num_active_periods);
  std::vector<int> modified_dates_to_dates;
  std::vector<int> dates_to_modified_dates;
  int count = 0;
  for (int period = data.num_periods() - 1; period >= 0; --period) {
    count += due_dates_per_period[period];
    if (count > 0) {
      count--;
      active_periods[period] = true;
    } else {
      active_periods[period] = false;
    }
  }
  for (int i = 0; i < data.num_periods(); ++i) {
    if (active_periods[i]) {
      dates_to_modified_dates.push_back(modified_dates_to_dates.size());
      modified_dates_to_dates.push_back(i);
    } else {
      dates_to_modified_dates.push_back(-1);
    }
  }
  LOG(INFO) << "original: " << strings::Join(dates_to_modified_dates, " ");
  LOG(INFO) << "modified: " << strings::Join(modified_dates_to_dates, " ");

  std::vector<int> item_to_product;
  std::vector<int> modified_due_dates;
  for (int i = 0; i < data.num_products(); ++i) {
    for (const int j : data.due_dates_per_product()[i]) {
      item_to_product.push_back(i);
      modified_due_dates.push_back(dates_to_modified_dates[j]);
    }
  }

  RoutingModel routing(num_active_periods + 1, 1);
  const RoutingModel::NodeIndex kDepot(0);
  routing.SetDepot(kDepot);

  // Setting first solution heuristic (cheapest addition).
  FLAGS_routing_first_solution = "Savings";
  // Disabling Large Neighborhood Search, comment out to activate it.
  FLAGS_routing_no_lns = true;
  FLAGS_routing_trace = true;
  FLAGS_routing_guided_local_search = true;

  ProductMatrix matrix(data, item_to_product);

  routing.SetArcCostEvaluatorOfAllVehicles(
      NewPermanentCallback(&matrix, &ProductMatrix::Distance));

  routing.AddDimension(NewPermanentCallback(OneDistance), 0,
                       num_active_periods + 2, true, kTime);
  const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime);
  for (int i = 0; i < num_active_periods; ++i) {
    const int due_date = modified_due_dates[i];
    LOG(INFO) << i << ": " << due_date;
    time_dimension.CumulVar(1 + i)->SetMax(due_date + 1);
  }
  // Solve, returns a solution if any (owned by RoutingModel).
  const Assignment* solution = routing.Solve();
  if (solution != NULL) {
    LOG(INFO) << solution->DebugString();
  } else {
    LOG(INFO) << "No solution";
  }
}
}  // namespace operations_research

static const char kUsage[] =
    "Usage: see flags.\nThis program runs the ACP 2014 summer school "
    "competition";

int main(int argc, char** argv) {
  FLAGS_log_prefix = false;
  gflags::SetUsageMessage(kUsage);
  gflags::ParseCommandLineFlags(&argc, &argv, true);
  if (FLAGS_input.empty()) {
    LOG(FATAL) << "Please supply a data file with --input=";
  }
  operations_research::Solve(FLAGS_input, FLAGS_solution);
  return 0;
}
<commit_msg>update the routing constructor in acp_challenge_routing.cc<commit_after>// Copyright 2010-2014 Google
// 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.
//
// ACP 2014 challenge

#include <cstdio>

#include "base/commandlineflags.h"
#include "base/file.h"
#include "base/filelinereader.h"
#include "base/hash.h"
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/split.h"
#include "base/map_util.h"
#include "base/stringprintf.h"
#include "base/strtoint.h"
#include "constraint_solver/constraint_solver.h"
#include "constraint_solver/routing.h"
#include "util/tuple_set.h"

DEFINE_string(input, "", "");
DEFINE_string(solution, "", "");
DEFINE_int32(ls_seed, 0, "ls seed");
DEFINE_int32(ls_size, 8, "ls size");
DEFINE_int32(ls_perm, 11, "ls perm");

DECLARE_string(routing_first_solution);
DECLARE_bool(routing_no_lns);
DECLARE_bool(routing_trace);
DECLARE_bool(routing_guided_local_search);

namespace operations_research {

class AcpData {
 public:
  AcpData()
      : num_periods_(-1), num_products_(-1), inventory_cost_(0), state_(0) {}

  void Load(const std::string& filename) {
    FileLineReader reader(filename.c_str());
    reader.set_line_callback(
        NewPermanentCallback(this, &AcpData::ProcessNewLine));
    reader.Reload();
    if (!reader.loaded_successfully()) {
      LOG(ERROR) << "Could not open acp challenge file";
    }
  }

  void ProcessNewLine(char* const line) {
    const std::vector<std::string> words =
        strings::Split(line, " ", strings::SkipEmpty());
    if (words.empty()) return;
    switch (state_) {
      case 0: {
        num_periods_ = atoi32(words[0]);
        state_ = 1;
        break;
      }
      case 1: {
        num_products_ = atoi32(words[0]);
        state_ = 2;
        break;
      }
      case 2: {
        due_dates_per_product_.resize(due_dates_per_product_.size() + 1);
        CHECK_EQ(words.size(), num_periods_) << "Error with line " << line;
        for (int i = 0; i < num_periods_; ++i) {
          if (atoi32(words[i]) == 1) {
            due_dates_per_product_.back().push_back(i);
          }
        }
        if (due_dates_per_product_.size() == num_products_) {
          state_ = 3;
        }
        break;
      }
      case 3: {
        inventory_cost_ = atoi32(words[0]);
        state_ = 4;
        break;
      }
      case 4: {
        transitions_.resize(transitions_.size() + 1);
        CHECK_EQ(words.size(), num_products_);
        for (int i = 0; i < num_products_; ++i) {
          transitions_.back().push_back(atoi32(words[i]));
        }
        break;
      }
      default: {
        LOG(ERROR) << "Should not be here";
      }
    }
  }

  std::string DebugString() const {
    return StringPrintf("AcpData(%d periods, %d products, %d cost)",
                        num_periods_, num_products_, inventory_cost_);
  }

  const std::vector<std::vector<int>>& due_dates_per_product() const {
    return due_dates_per_product_;
  }

  const std::vector<std::vector<int>>& transitions() const {
    return transitions_;
  }

  int num_periods() const { return num_periods_; }
  int num_products() const { return num_products_; }
  int inventory_cost() const { return inventory_cost_; }

 private:
  int num_periods_;
  int num_products_;
  int inventory_cost_;
  std::vector<std::vector<int>> due_dates_per_product_;
  std::vector<std::vector<int>> transitions_;
  int state_;
};

void LoadSolution(const std::string& filename, std::vector<int>* vec) {
  File* const file = File::OpenOrDie(filename, "r");
  std::string line;
  file->ReadToString(&line, 10000);
  const std::vector<std::string> words =
      strings::Split(line, " ", strings::SkipEmpty());
  LOG(INFO) << "Solution file has " << words.size() << " entries";
  vec->clear();
  for (const std::string& word : words) {
    vec->push_back(atoi32(word));
  }
  LOG(INFO) << "  - loaded " << strings::Join(*vec, " ");
}

int Evaluate(const AcpData& data, const std::vector<int>& schedule) {
  std::vector<int> indices(data.num_products(), 0);
  int early_days = 0;
  for (int i = 0; i < schedule.size(); ++i) {
    const int product = schedule[i];
    if (product >= data.num_products() || product < -1) {
      return kint32max;
    }
    if (product != -1) {
      const int index = indices[product];
      if (index >= data.due_dates_per_product()[product].size()) {
        LOG(INFO) << "Strange";
        return kint32max;
      }
      indices[product]++;
      const int due_date = data.due_dates_per_product()[product][index];
      if (i > due_date) {
        return kint32max;
      }
      early_days += due_date - i;
    }
  }

  int previous = -1;
  int transition_cost = 0;
  for (const int product : schedule) {
    if (previous != -1  && product != -1 && previous != product) {
      transition_cost += data.transitions()[previous][product];
    }
    if (product != -1) {
      previous = product;
    }
  }
  return transition_cost + early_days * data.inventory_cost();
}

int64 OneDistance(RoutingModel::NodeIndex from, RoutingModel::NodeIndex to) {
  return 1;
}

class ProductMatrix {
 public:
  ProductMatrix(const AcpData& data, const std::vector<int>& item_to_product)
      : data_(data), item_to_product_(item_to_product) {}

  int64 Distance(RoutingModel::NodeIndex from,
                 RoutingModel::NodeIndex to) const {
    if (from.value() == 0 || to.value() == 0) {
      return 0;
    }
    const int index1 = item_to_product_[from.value() - 1];
    const int index2 = item_to_product_[to.value() - 1];
    return data_.transitions()[index1][index2];
  }

 private:
  const AcpData& data_;
  const std::vector<int>& item_to_product_;
};

void Solve(const std::string& filename, const std::string& solution_file) {

  const char* kTime = "Time";

  LOG(INFO) << "Load " << filename;
  AcpData data;
  data.Load(filename);

  std::vector<int> best;
  int best_cost = kint32max;
  if (!solution_file.empty()) {
    LoadSolution(solution_file, &best);
    best.resize(data.num_periods());
    best_cost = Evaluate(data, best);
    LOG(INFO) << "Initial solution cost = " << best_cost;
  }

  int num_active_periods = 0;
  std::vector<int> due_dates_per_period(data.num_periods(), 0);
  for (const std::vector<int>& d : data.due_dates_per_product()) {
    for (const int v : d) {
      due_dates_per_period[v]++;
      num_active_periods++;
    }
  }
  LOG(INFO) << "num active periods = " << num_active_periods;
  std::vector<bool> active_periods(num_active_periods);
  std::vector<int> modified_dates_to_dates;
  std::vector<int> dates_to_modified_dates;
  int count = 0;
  for (int period = data.num_periods() - 1; period >= 0; --period) {
    count += due_dates_per_period[period];
    if (count > 0) {
      count--;
      active_periods[period] = true;
    } else {
      active_periods[period] = false;
    }
  }
  for (int i = 0; i < data.num_periods(); ++i) {
    if (active_periods[i]) {
      dates_to_modified_dates.push_back(modified_dates_to_dates.size());
      modified_dates_to_dates.push_back(i);
    } else {
      dates_to_modified_dates.push_back(-1);
    }
  }
  LOG(INFO) << "original: " << strings::Join(dates_to_modified_dates, " ");
  LOG(INFO) << "modified: " << strings::Join(modified_dates_to_dates, " ");

  std::vector<int> item_to_product;
  std::vector<int> modified_due_dates;
  for (int i = 0; i < data.num_products(); ++i) {
    for (const int j : data.due_dates_per_product()[i]) {
      item_to_product.push_back(i);
      modified_due_dates.push_back(dates_to_modified_dates[j]);
    }
  }

  const RoutingModel::NodeIndex kDepot(0);
  RoutingModel routing(num_active_periods + 1, 1, kDepot);

  // Setting first solution heuristic (cheapest addition).
  FLAGS_routing_first_solution = "Savings";
  // Disabling Large Neighborhood Search, comment out to activate it.
  FLAGS_routing_no_lns = true;
  FLAGS_routing_trace = true;
  FLAGS_routing_guided_local_search = true;

  ProductMatrix matrix(data, item_to_product);

  routing.SetArcCostEvaluatorOfAllVehicles(
      NewPermanentCallback(&matrix, &ProductMatrix::Distance));

  routing.AddDimension(NewPermanentCallback(OneDistance), 0,
                       num_active_periods + 2, true, kTime);
  const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime);
  for (int i = 0; i < num_active_periods; ++i) {
    const int due_date = modified_due_dates[i];
    LOG(INFO) << i << ": " << due_date;
    time_dimension.CumulVar(1 + i)->SetMax(due_date + 1);
  }
  // Solve, returns a solution if any (owned by RoutingModel).
  const Assignment* solution = routing.Solve();
  if (solution != NULL) {
    LOG(INFO) << solution->DebugString();
  } else {
    LOG(INFO) << "No solution";
  }
}
}  // namespace operations_research

static const char kUsage[] =
    "Usage: see flags.\nThis program runs the ACP 2014 summer school "
    "competition";

int main(int argc, char** argv) {
  FLAGS_log_prefix = false;
  gflags::SetUsageMessage(kUsage);
  gflags::ParseCommandLineFlags(&argc, &argv, true);
  if (FLAGS_input.empty()) {
    LOG(FATAL) << "Please supply a data file with --input=";
  }
  operations_research::Solve(FLAGS_input, FLAGS_solution);
  return 0;
}
<|endoftext|>