<commit_before>
#include "local_banker.h"
#include "soa/service/http_header.h"
#include "jml/arch/timers.h"

using namespace std;
using namespace Datacratic;

namespace RTBKIT {

LocalBanker::LocalBanker(GoAccountType type, string accountSuffix)
    : type(type), accountSuffix(accountSuffix)
{
}

void
LocalBanker::init(std::string bankerUrl,
                  double timeout,
                  int numConnections,
                  bool tcpNoDelay)
{
    httpClient = std::make_shared<HttpClient>(bankerUrl, numConnections);
    httpClient->sendExpect100Continue(false);
    addSource("LocalBanker:HttpClient", httpClient);

    auto reauthorizePeriodic = [&] (uint64_t wakeups) {
        reauthorize();
    };
    auto spendUpdatePeriodic = [&] (uint64_t wakeups) {
        spendUpdate();
    };
    auto initializeAccountsPeriodic = [&] (uint64_t wakeups) {
        std::lock_guard<std::mutex> guard(this->mutex);
        for (auto &key : uninitializedAccounts) {
            addAccount(key);
        }
    };

    if (type == ROUTER)
        addPeriodic("localBanker::reauthorize", 1.0, reauthorizePeriodic);

    if (type == POST_AUCTION)
        addPeriodic("localBanker::spendUpdate", 0.5, spendUpdatePeriodic);

    addPeriodic("uninitializedAccounts", 1.0, initializeAccountsPeriodic);
}

void
LocalBanker::start()
{
    MessageLoop::start();
}

void
LocalBanker::shutdown()
{
    MessageLoop::shutdown();
}

void
LocalBanker::addAccount(const AccountKey &key)
{
    auto onResponse = [&] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        if (status != 200) {
            cout << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl
                 << "url:    " << req.url_ << endl
                 << "cont_str: " << req.content_.str << endl;
            std::lock_guard<std::mutex> guard(this->mutex);
            uninitializedAccounts.insert(key);
        } else {
            //cout << "returned account: " << endl;
            //cout << body << endl;
            accounts.addFromJsonString(body);
            std::lock_guard<std::mutex> guard(this->mutex);
            uninitializedAccounts.erase(key);
        }
    };
    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::objectValue);
    payload["accountName"] = key.toString() + ":" + accountSuffix;
    switch (type) {
        case ROUTER:
            payload["accountType"] = "Router";
            break;
        case POST_AUCTION:
            payload["accountType"] = "PostAuction";
            break;
    };
    cout << "calling add go banker account: " << key.toString() << endl;
    httpClient->post("/accounts", cbs, payload, {}, {}, 1);
}

void
LocalBanker::spendUpdate()
{
    auto onResponse = [] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        if (status != 200) {
            cout << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl;
        } else {
            cout << "status: " << status << endl
                 << "body:   " << body << endl;
        }
    };
    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::arrayValue);
//    int i = 0;
    for (auto it : accounts.accounts) {
//         cout << "i: " << i++ << "\n"
//              << "name: " << it.first.toString() << "\n"
//              << "info: " << it.second.toJson() << endl;
        payload.append(it.second.toJson());
    }
    httpClient->post("/spendupdate", cbs, payload, {}, {}, 1);
}

void
LocalBanker::reauthorize()
{
    auto onResponse = [&] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        if (status != 200) {
            cout << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl
                 << "url:    " << req.url_ << endl
                 << "cont_str: " << req.content_.str << endl;
        } else {
            Json::Value jsonAccounts = Json::parse(body);
            for ( auto jsonAccount : jsonAccounts ) {
                auto key = AccountKey(jsonAccount["name"].asString());
                int64_t newBalance = jsonAccount["balance"].asInt();
                //cout << "account: " << key.toString() << "\n"
                //     << "new bal: " << newBalance << endl;
                accounts.updateBalance(key, newBalance);
            }
        }
    };

    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::arrayValue);
//    int i = 0;
    for (auto it : accounts.accounts) {
//         cout << "i: " << i++ << "\n"
//              << "name: " << it.first.toString() << "\n"
//              << "info: " << it.second.toJson() << endl;
        payload.append(it.first.toString());
    }
    httpClient->post("/reauthorize/1", cbs, payload, {}, {}, 2);
}

bool
LocalBanker::bid(const AccountKey &key, Amount bidPrice)
{
    return accounts.bid(AccountKey(key.toString() + ":" + accountSuffix), bidPrice);
}

bool
LocalBanker::win(const AccountKey &key, Amount winPrice)
{
    return accounts.win(AccountKey(key.toString() + ":" + accountSuffix), winPrice);
}

} // namespace RTBKIT
<commit_msg>removed print from spend update<commit_after>
#include "local_banker.h"
#include "soa/service/http_header.h"
#include "jml/arch/timers.h"

using namespace std;
using namespace Datacratic;

namespace RTBKIT {

LocalBanker::LocalBanker(GoAccountType type, string accountSuffix)
    : type(type), accountSuffix(accountSuffix)
{
}

void
LocalBanker::init(std::string bankerUrl,
                  double timeout,
                  int numConnections,
                  bool tcpNoDelay)
{
    httpClient = std::make_shared<HttpClient>(bankerUrl, numConnections);
    httpClient->sendExpect100Continue(false);
    addSource("LocalBanker:HttpClient", httpClient);

    auto reauthorizePeriodic = [&] (uint64_t wakeups) {
        reauthorize();
    };
    auto spendUpdatePeriodic = [&] (uint64_t wakeups) {
        spendUpdate();
    };
    auto initializeAccountsPeriodic = [&] (uint64_t wakeups) {
        std::lock_guard<std::mutex> guard(this->mutex);
        for (auto &key : uninitializedAccounts) {
            addAccount(key);
        }
    };

    if (type == ROUTER)
        addPeriodic("localBanker::reauthorize", 1.0, reauthorizePeriodic);

    if (type == POST_AUCTION)
        addPeriodic("localBanker::spendUpdate", 0.5, spendUpdatePeriodic);

    addPeriodic("uninitializedAccounts", 1.0, initializeAccountsPeriodic);
}

void
LocalBanker::start()
{
    MessageLoop::start();
}

void
LocalBanker::shutdown()
{
    MessageLoop::shutdown();
}

void
LocalBanker::addAccount(const AccountKey &key)
{
    auto onResponse = [&] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        if (status != 200) {
            cout << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl
                 << "url:    " << req.url_ << endl
                 << "cont_str: " << req.content_.str << endl;
            std::lock_guard<std::mutex> guard(this->mutex);
            uninitializedAccounts.insert(key);
        } else {
            //cout << "returned account: " << endl;
            //cout << body << endl;
            accounts.addFromJsonString(body);
            std::lock_guard<std::mutex> guard(this->mutex);
            uninitializedAccounts.erase(key);
        }
    };
    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::objectValue);
    payload["accountName"] = key.toString() + ":" + accountSuffix;
    switch (type) {
        case ROUTER:
            payload["accountType"] = "Router";
            break;
        case POST_AUCTION:
            payload["accountType"] = "PostAuction";
            break;
    };
    cout << "calling add go banker account: " << key.toString() << endl;
    httpClient->post("/accounts", cbs, payload, {}, {}, 1);
}

void
LocalBanker::spendUpdate()
{
    auto onResponse = [] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        if (status != 200) {
            cout << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl;
        } else {
            //cout << "status: " << status << endl
            //     << "body:   " << body << endl;
        }
    };
    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::arrayValue);
//    int i = 0;
    for (auto it : accounts.accounts) {
//         cout << "i: " << i++ << "\n"
//              << "name: " << it.first.toString() << "\n"
//              << "info: " << it.second.toJson() << endl;
        payload.append(it.second.toJson());
    }
    httpClient->post("/spendupdate", cbs, payload, {}, {}, 1);
}

void
LocalBanker::reauthorize()
{
    auto onResponse = [&] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        if (status != 200) {
            cout << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl
                 << "url:    " << req.url_ << endl
                 << "cont_str: " << req.content_.str << endl;
        } else {
            Json::Value jsonAccounts = Json::parse(body);
            for ( auto jsonAccount : jsonAccounts ) {
                auto key = AccountKey(jsonAccount["name"].asString());
                int64_t newBalance = jsonAccount["balance"].asInt();
                //cout << "account: " << key.toString() << "\n"
                //     << "new bal: " << newBalance << endl;
                accounts.updateBalance(key, newBalance);
            }
        }
    };

    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::arrayValue);
//    int i = 0;
    for (auto it : accounts.accounts) {
//         cout << "i: " << i++ << "\n"
//              << "name: " << it.first.toString() << "\n"
//              << "info: " << it.second.toJson() << endl;
        payload.append(it.first.toString());
    }
    httpClient->post("/reauthorize/1", cbs, payload, {}, {}, 2);
}

bool
LocalBanker::bid(const AccountKey &key, Amount bidPrice)
{
    return accounts.bid(AccountKey(key.toString() + ":" + accountSuffix), bidPrice);
}

bool
LocalBanker::win(const AccountKey &key, Amount winPrice)
{
    return accounts.win(AccountKey(key.toString() + ":" + accountSuffix), winPrice);
}

} // namespace RTBKIT
<|endoftext|>


<commit_before>
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "rosalloc_space-inl.h"

#include "gc/accounting/card_table.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "runtime.h"
#include "thread.h"
#include "thread_list.h"
#include "utils.h"
#include "valgrind_malloc_space-inl.h"

namespace art {
namespace gc {
namespace space {

static constexpr bool kPrefetchDuringRosAllocFreeList = false;
static constexpr size_t kPrefetchLookAhead = 8;
// Use this only for verification, it is not safe to use since the class of the object may have
// been freed.
static constexpr bool kVerifyFreedBytes = false;

// TODO: Fix
// template class ValgrindMallocSpace<RosAllocSpace, allocator::RosAlloc*>;

RosAllocSpace::RosAllocSpace(const std::string& name, MemMap* mem_map,
                             art::gc::allocator::RosAlloc* rosalloc, byte* begin, byte* end,
                             byte* limit, size_t growth_limit, bool can_move_objects,
                             size_t starting_size, size_t initial_size, bool low_memory_mode)
    : MallocSpace(name, mem_map, begin, end, limit, growth_limit, true, can_move_objects,
                  starting_size, initial_size),
      rosalloc_(rosalloc), low_memory_mode_(low_memory_mode) {
  CHECK(rosalloc != nullptr);
}

RosAllocSpace* RosAllocSpace::CreateFromMemMap(MemMap* mem_map, const std::string& name,
                                               size_t starting_size, size_t initial_size,
                                               size_t growth_limit, size_t capacity,
                                               bool low_memory_mode, bool can_move_objects) {
  DCHECK(mem_map != nullptr);
  allocator::RosAlloc* rosalloc = CreateRosAlloc(mem_map->Begin(), starting_size, initial_size,
                                                 capacity, low_memory_mode);
  if (rosalloc == NULL) {
    LOG(ERROR) << "Failed to initialize rosalloc for alloc space (" << name << ")";
    return NULL;
  }

  // Protect memory beyond the starting size. MoreCore will add r/w permissions when necessory
  byte* end = mem_map->Begin() + starting_size;
  if (capacity - starting_size > 0) {
    CHECK_MEMORY_CALL(mprotect, (end, capacity - starting_size, PROT_NONE), name);
  }

  // Everything is set so record in immutable structure and leave
  byte* begin = mem_map->Begin();
  // TODO: Fix RosAllocSpace to support valgrind. There is currently some issues with
  // AllocationSize caused by redzones. b/12944686
  if (false && Runtime::Current()->GetHeap()->RunningOnValgrind()) {
    LOG(FATAL) << "Unimplemented";
  } else {
    return new RosAllocSpace(name, mem_map, rosalloc, begin, end, begin + capacity, growth_limit,
                             can_move_objects, starting_size, initial_size, low_memory_mode);
  }
}

RosAllocSpace::~RosAllocSpace() {
  delete rosalloc_;
}

RosAllocSpace* RosAllocSpace::Create(const std::string& name, size_t initial_size,
                                     size_t growth_limit, size_t capacity, byte* requested_begin,
                                     bool low_memory_mode, bool can_move_objects) {
  uint64_t start_time = 0;
  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    start_time = NanoTime();
    VLOG(startup) << "RosAllocSpace::Create entering " << name
                  << " initial_size=" << PrettySize(initial_size)
                  << " growth_limit=" << PrettySize(growth_limit)
                  << " capacity=" << PrettySize(capacity)
                  << " requested_begin=" << reinterpret_cast<void*>(requested_begin);
  }

  // Memory we promise to rosalloc before it asks for morecore.
  // Note: making this value large means that large allocations are unlikely to succeed as rosalloc
  // will ask for this memory from sys_alloc which will fail as the footprint (this value plus the
  // size of the large allocation) will be greater than the footprint limit.
  size_t starting_size = Heap::kDefaultStartingSize;
  MemMap* mem_map = CreateMemMap(name, starting_size, &initial_size, &growth_limit, &capacity,
                                 requested_begin);
  if (mem_map == NULL) {
    LOG(ERROR) << "Failed to create mem map for alloc space (" << name << ") of size "
               << PrettySize(capacity);
    return NULL;
  }

  RosAllocSpace* space = CreateFromMemMap(mem_map, name, starting_size, initial_size,
                                          growth_limit, capacity, low_memory_mode,
                                          can_move_objects);
  // We start out with only the initial size possibly containing objects.
  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    LOG(INFO) << "RosAllocSpace::Create exiting (" << PrettyDuration(NanoTime() - start_time)
        << " ) " << *space;
  }
  return space;
}

allocator::RosAlloc* RosAllocSpace::CreateRosAlloc(void* begin, size_t morecore_start,
                                                   size_t initial_size,
                                                   size_t maximum_size, bool low_memory_mode) {
  // clear errno to allow PLOG on error
  errno = 0;
  // create rosalloc using our backing storage starting at begin and
  // with a footprint of morecore_start. When morecore_start bytes of
  // memory is exhaused morecore will be called.
  allocator::RosAlloc* rosalloc = new art::gc::allocator::RosAlloc(
      begin, morecore_start, maximum_size,
      low_memory_mode ?
          art::gc::allocator::RosAlloc::kPageReleaseModeAll :
          art::gc::allocator::RosAlloc::kPageReleaseModeSizeAndEnd);
  if (rosalloc != NULL) {
    rosalloc->SetFootprintLimit(initial_size);
  } else {
    PLOG(ERROR) << "RosAlloc::Create failed";
  }
  return rosalloc;
}

mirror::Object* RosAllocSpace::AllocWithGrowth(Thread* self, size_t num_bytes,
                                               size_t* bytes_allocated, size_t* usable_size) {
  mirror::Object* result;
  {
    MutexLock mu(self, lock_);
    // Grow as much as possible within the space.
    size_t max_allowed = Capacity();
    rosalloc_->SetFootprintLimit(max_allowed);
    // Try the allocation.
    result = AllocCommon(self, num_bytes, bytes_allocated, usable_size);
    // Shrink back down as small as possible.
    size_t footprint = rosalloc_->Footprint();
    rosalloc_->SetFootprintLimit(footprint);
  }
  // Note RosAlloc zeroes memory internally.
  // Return the new allocation or NULL.
  CHECK(!kDebugSpaces || result == nullptr || Contains(result));
  return result;
}

MallocSpace* RosAllocSpace::CreateInstance(const std::string& name, MemMap* mem_map, void* allocator,
                                           byte* begin, byte* end, byte* limit, size_t growth_limit,
                                           bool can_move_objects) {
  return new RosAllocSpace(name, mem_map, reinterpret_cast<allocator::RosAlloc*>(allocator),
                           begin, end, limit, growth_limit, can_move_objects, starting_size_,
                           initial_size_, low_memory_mode_);
}

size_t RosAllocSpace::Free(Thread* self, mirror::Object* ptr) {
  if (kDebugSpaces) {
    CHECK(ptr != NULL);
    CHECK(Contains(ptr)) << "Free (" << ptr << ") not in bounds of heap " << *this;
  }
  if (kRecentFreeCount > 0) {
    MutexLock mu(self, lock_);
    RegisterRecentFree(ptr);
  }
  return rosalloc_->Free(self, ptr);
}

size_t RosAllocSpace::FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) {
  DCHECK(ptrs != nullptr);

  size_t verify_bytes = 0;
  for (size_t i = 0; i < num_ptrs; i++) {
    if (kPrefetchDuringRosAllocFreeList && i + kPrefetchLookAhead < num_ptrs) {
      __builtin_prefetch(reinterpret_cast<char*>(ptrs[i + kPrefetchLookAhead]));
    }
    if (kVerifyFreedBytes) {
      verify_bytes += AllocationSizeNonvirtual(ptrs[i], nullptr);
    }
  }

  if (kRecentFreeCount > 0) {
    MutexLock mu(self, lock_);
    for (size_t i = 0; i < num_ptrs; i++) {
      RegisterRecentFree(ptrs[i]);
    }
  }

  if (kDebugSpaces) {
    size_t num_broken_ptrs = 0;
    for (size_t i = 0; i < num_ptrs; i++) {
      if (!Contains(ptrs[i])) {
        num_broken_ptrs++;
        LOG(ERROR) << "FreeList[" << i << "] (" << ptrs[i] << ") not in bounds of heap " << *this;
      } else {
        size_t size = rosalloc_->UsableSize(ptrs[i]);
        memset(ptrs[i], 0xEF, size);
      }
    }
    CHECK_EQ(num_broken_ptrs, 0u);
  }

  const size_t bytes_freed = rosalloc_->BulkFree(self, reinterpret_cast<void**>(ptrs), num_ptrs);
  if (kVerifyFreedBytes) {
    CHECK_EQ(verify_bytes, bytes_freed);
  }
  return bytes_freed;
}

// Callback from rosalloc when it needs to increase the footprint
extern "C" void* art_heap_rosalloc_morecore(allocator::RosAlloc* rosalloc, intptr_t increment) {
  Heap* heap = Runtime::Current()->GetHeap();
  RosAllocSpace* rosalloc_space = heap->GetRosAllocSpace(rosalloc);
  DCHECK(rosalloc_space != nullptr);
  DCHECK_EQ(rosalloc_space->GetRosAlloc(), rosalloc);
  return rosalloc_space->MoreCore(increment);
}

size_t RosAllocSpace::Trim() {
  VLOG(heap) << "RosAllocSpace::Trim() ";
  {
    MutexLock mu(Thread::Current(), lock_);
    // Trim to release memory at the end of the space.
    rosalloc_->Trim();
  }
  // Attempt to release pages if it does not release all empty pages.
  if (!rosalloc_->DoesReleaseAllPages()) {
    return rosalloc_->ReleasePages();
  }
  return 0;
}

void RosAllocSpace::Walk(void(*callback)(void *start, void *end, size_t num_bytes, void* callback_arg),
                         void* arg) {
  InspectAllRosAlloc(callback, arg, true);
}

size_t RosAllocSpace::GetFootprint() {
  MutexLock mu(Thread::Current(), lock_);
  return rosalloc_->Footprint();
}

size_t RosAllocSpace::GetFootprintLimit() {
  MutexLock mu(Thread::Current(), lock_);
  return rosalloc_->FootprintLimit();
}

void RosAllocSpace::SetFootprintLimit(size_t new_size) {
  MutexLock mu(Thread::Current(), lock_);
  VLOG(heap) << "RosAllocSpace::SetFootprintLimit " << PrettySize(new_size);
  // Compare against the actual footprint, rather than the Size(), because the heap may not have
  // grown all the way to the allowed size yet.
  size_t current_space_size = rosalloc_->Footprint();
  if (new_size < current_space_size) {
    // Don't let the space grow any more.
    new_size = current_space_size;
  }
  rosalloc_->SetFootprintLimit(new_size);
}

uint64_t RosAllocSpace::GetBytesAllocated() {
  size_t bytes_allocated = 0;
  InspectAllRosAlloc(art::gc::allocator::RosAlloc::BytesAllocatedCallback, &bytes_allocated, false);
  return bytes_allocated;
}

uint64_t RosAllocSpace::GetObjectsAllocated() {
  size_t objects_allocated = 0;
  InspectAllRosAlloc(art::gc::allocator::RosAlloc::ObjectsAllocatedCallback, &objects_allocated, false);
  return objects_allocated;
}

void RosAllocSpace::InspectAllRosAllocWithSuspendAll(
    void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg),
    void* arg, bool do_null_callback_at_end) NO_THREAD_SAFETY_ANALYSIS {
  // TODO: NO_THREAD_SAFETY_ANALYSIS.
  Thread* self = Thread::Current();
  ThreadList* tl = Runtime::Current()->GetThreadList();
  tl->SuspendAll();
  {
    MutexLock mu(self, *Locks::runtime_shutdown_lock_);
    MutexLock mu2(self, *Locks::thread_list_lock_);
    rosalloc_->InspectAll(callback, arg);
    if (do_null_callback_at_end) {
      callback(NULL, NULL, 0, arg);  // Indicate end of a space.
    }
  }
  tl->ResumeAll();
}

void RosAllocSpace::InspectAllRosAlloc(void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg),
                                       void* arg, bool do_null_callback_at_end) NO_THREAD_SAFETY_ANALYSIS {
  // TODO: NO_THREAD_SAFETY_ANALYSIS.
  Thread* self = Thread::Current();
  if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
    // The mutators are already suspended. For example, a call path
    // from SignalCatcher::HandleSigQuit().
    rosalloc_->InspectAll(callback, arg);
    if (do_null_callback_at_end) {
      callback(NULL, NULL, 0, arg);  // Indicate end of a space.
    }
  } else if (Locks::mutator_lock_->IsSharedHeld(self)) {
    // The mutators are not suspended yet and we have a shared access
    // to the mutator lock. Temporarily release the shared access by
    // transitioning to the suspend state, and suspend the mutators.
    self->TransitionFromRunnableToSuspended(kSuspended);
    InspectAllRosAllocWithSuspendAll(callback, arg, do_null_callback_at_end);
    self->TransitionFromSuspendedToRunnable();
    Locks::mutator_lock_->AssertSharedHeld(self);
  } else {
    // The mutators are not suspended yet. Suspend the mutators.
    InspectAllRosAllocWithSuspendAll(callback, arg, do_null_callback_at_end);
  }
}

void RosAllocSpace::RevokeThreadLocalBuffers(Thread* thread) {
  rosalloc_->RevokeThreadLocalRuns(thread);
}

void RosAllocSpace::RevokeAllThreadLocalBuffers() {
  rosalloc_->RevokeAllThreadLocalRuns();
}

void RosAllocSpace::AssertAllThreadLocalBuffersAreRevoked() {
  if (kIsDebugBuild) {
    rosalloc_->AssertAllThreadLocalRunsAreRevoked();
  }
}

void RosAllocSpace::Clear() {
  size_t footprint_limit = GetFootprintLimit();
  madvise(GetMemMap()->Begin(), GetMemMap()->Size(), MADV_DONTNEED);
  live_bitmap_->Clear();
  mark_bitmap_->Clear();
  SetEnd(begin_ + starting_size_);
  delete rosalloc_;
  rosalloc_ = CreateRosAlloc(mem_map_->Begin(), starting_size_, initial_size_, Capacity(),
                             low_memory_mode_);
  SetFootprintLimit(footprint_limit);
}

}  // namespace space
}  // namespace gc
}  // namespace art
<commit_msg>Pass the real capacity to CreateRosAlloc.<commit_after>
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "rosalloc_space-inl.h"

#include "gc/accounting/card_table.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "runtime.h"
#include "thread.h"
#include "thread_list.h"
#include "utils.h"
#include "valgrind_malloc_space-inl.h"

namespace art {
namespace gc {
namespace space {

static constexpr bool kPrefetchDuringRosAllocFreeList = false;
static constexpr size_t kPrefetchLookAhead = 8;
// Use this only for verification, it is not safe to use since the class of the object may have
// been freed.
static constexpr bool kVerifyFreedBytes = false;

// TODO: Fix
// template class ValgrindMallocSpace<RosAllocSpace, allocator::RosAlloc*>;

RosAllocSpace::RosAllocSpace(const std::string& name, MemMap* mem_map,
                             art::gc::allocator::RosAlloc* rosalloc, byte* begin, byte* end,
                             byte* limit, size_t growth_limit, bool can_move_objects,
                             size_t starting_size, size_t initial_size, bool low_memory_mode)
    : MallocSpace(name, mem_map, begin, end, limit, growth_limit, true, can_move_objects,
                  starting_size, initial_size),
      rosalloc_(rosalloc), low_memory_mode_(low_memory_mode) {
  CHECK(rosalloc != nullptr);
}

RosAllocSpace* RosAllocSpace::CreateFromMemMap(MemMap* mem_map, const std::string& name,
                                               size_t starting_size, size_t initial_size,
                                               size_t growth_limit, size_t capacity,
                                               bool low_memory_mode, bool can_move_objects) {
  DCHECK(mem_map != nullptr);
  allocator::RosAlloc* rosalloc = CreateRosAlloc(mem_map->Begin(), starting_size, initial_size,
                                                 capacity, low_memory_mode);
  if (rosalloc == NULL) {
    LOG(ERROR) << "Failed to initialize rosalloc for alloc space (" << name << ")";
    return NULL;
  }

  // Protect memory beyond the starting size. MoreCore will add r/w permissions when necessory
  byte* end = mem_map->Begin() + starting_size;
  if (capacity - starting_size > 0) {
    CHECK_MEMORY_CALL(mprotect, (end, capacity - starting_size, PROT_NONE), name);
  }

  // Everything is set so record in immutable structure and leave
  byte* begin = mem_map->Begin();
  // TODO: Fix RosAllocSpace to support valgrind. There is currently some issues with
  // AllocationSize caused by redzones. b/12944686
  if (false && Runtime::Current()->GetHeap()->RunningOnValgrind()) {
    LOG(FATAL) << "Unimplemented";
  } else {
    return new RosAllocSpace(name, mem_map, rosalloc, begin, end, begin + capacity, growth_limit,
                             can_move_objects, starting_size, initial_size, low_memory_mode);
  }
}

RosAllocSpace::~RosAllocSpace() {
  delete rosalloc_;
}

RosAllocSpace* RosAllocSpace::Create(const std::string& name, size_t initial_size,
                                     size_t growth_limit, size_t capacity, byte* requested_begin,
                                     bool low_memory_mode, bool can_move_objects) {
  uint64_t start_time = 0;
  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    start_time = NanoTime();
    VLOG(startup) << "RosAllocSpace::Create entering " << name
                  << " initial_size=" << PrettySize(initial_size)
                  << " growth_limit=" << PrettySize(growth_limit)
                  << " capacity=" << PrettySize(capacity)
                  << " requested_begin=" << reinterpret_cast<void*>(requested_begin);
  }

  // Memory we promise to rosalloc before it asks for morecore.
  // Note: making this value large means that large allocations are unlikely to succeed as rosalloc
  // will ask for this memory from sys_alloc which will fail as the footprint (this value plus the
  // size of the large allocation) will be greater than the footprint limit.
  size_t starting_size = Heap::kDefaultStartingSize;
  MemMap* mem_map = CreateMemMap(name, starting_size, &initial_size, &growth_limit, &capacity,
                                 requested_begin);
  if (mem_map == NULL) {
    LOG(ERROR) << "Failed to create mem map for alloc space (" << name << ") of size "
               << PrettySize(capacity);
    return NULL;
  }

  RosAllocSpace* space = CreateFromMemMap(mem_map, name, starting_size, initial_size,
                                          growth_limit, capacity, low_memory_mode,
                                          can_move_objects);
  // We start out with only the initial size possibly containing objects.
  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    LOG(INFO) << "RosAllocSpace::Create exiting (" << PrettyDuration(NanoTime() - start_time)
        << " ) " << *space;
  }
  return space;
}

allocator::RosAlloc* RosAllocSpace::CreateRosAlloc(void* begin, size_t morecore_start,
                                                   size_t initial_size,
                                                   size_t maximum_size, bool low_memory_mode) {
  // clear errno to allow PLOG on error
  errno = 0;
  // create rosalloc using our backing storage starting at begin and
  // with a footprint of morecore_start. When morecore_start bytes of
  // memory is exhaused morecore will be called.
  allocator::RosAlloc* rosalloc = new art::gc::allocator::RosAlloc(
      begin, morecore_start, maximum_size,
      low_memory_mode ?
          art::gc::allocator::RosAlloc::kPageReleaseModeAll :
          art::gc::allocator::RosAlloc::kPageReleaseModeSizeAndEnd);
  if (rosalloc != NULL) {
    rosalloc->SetFootprintLimit(initial_size);
  } else {
    PLOG(ERROR) << "RosAlloc::Create failed";
  }
  return rosalloc;
}

mirror::Object* RosAllocSpace::AllocWithGrowth(Thread* self, size_t num_bytes,
                                               size_t* bytes_allocated, size_t* usable_size) {
  mirror::Object* result;
  {
    MutexLock mu(self, lock_);
    // Grow as much as possible within the space.
    size_t max_allowed = Capacity();
    rosalloc_->SetFootprintLimit(max_allowed);
    // Try the allocation.
    result = AllocCommon(self, num_bytes, bytes_allocated, usable_size);
    // Shrink back down as small as possible.
    size_t footprint = rosalloc_->Footprint();
    rosalloc_->SetFootprintLimit(footprint);
  }
  // Note RosAlloc zeroes memory internally.
  // Return the new allocation or NULL.
  CHECK(!kDebugSpaces || result == nullptr || Contains(result));
  return result;
}

MallocSpace* RosAllocSpace::CreateInstance(const std::string& name, MemMap* mem_map, void* allocator,
                                           byte* begin, byte* end, byte* limit, size_t growth_limit,
                                           bool can_move_objects) {
  return new RosAllocSpace(name, mem_map, reinterpret_cast<allocator::RosAlloc*>(allocator),
                           begin, end, limit, growth_limit, can_move_objects, starting_size_,
                           initial_size_, low_memory_mode_);
}

size_t RosAllocSpace::Free(Thread* self, mirror::Object* ptr) {
  if (kDebugSpaces) {
    CHECK(ptr != NULL);
    CHECK(Contains(ptr)) << "Free (" << ptr << ") not in bounds of heap " << *this;
  }
  if (kRecentFreeCount > 0) {
    MutexLock mu(self, lock_);
    RegisterRecentFree(ptr);
  }
  return rosalloc_->Free(self, ptr);
}

size_t RosAllocSpace::FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) {
  DCHECK(ptrs != nullptr);

  size_t verify_bytes = 0;
  for (size_t i = 0; i < num_ptrs; i++) {
    if (kPrefetchDuringRosAllocFreeList && i + kPrefetchLookAhead < num_ptrs) {
      __builtin_prefetch(reinterpret_cast<char*>(ptrs[i + kPrefetchLookAhead]));
    }
    if (kVerifyFreedBytes) {
      verify_bytes += AllocationSizeNonvirtual(ptrs[i], nullptr);
    }
  }

  if (kRecentFreeCount > 0) {
    MutexLock mu(self, lock_);
    for (size_t i = 0; i < num_ptrs; i++) {
      RegisterRecentFree(ptrs[i]);
    }
  }

  if (kDebugSpaces) {
    size_t num_broken_ptrs = 0;
    for (size_t i = 0; i < num_ptrs; i++) {
      if (!Contains(ptrs[i])) {
        num_broken_ptrs++;
        LOG(ERROR) << "FreeList[" << i << "] (" << ptrs[i] << ") not in bounds of heap " << *this;
      } else {
        size_t size = rosalloc_->UsableSize(ptrs[i]);
        memset(ptrs[i], 0xEF, size);
      }
    }
    CHECK_EQ(num_broken_ptrs, 0u);
  }

  const size_t bytes_freed = rosalloc_->BulkFree(self, reinterpret_cast<void**>(ptrs), num_ptrs);
  if (kVerifyFreedBytes) {
    CHECK_EQ(verify_bytes, bytes_freed);
  }
  return bytes_freed;
}

// Callback from rosalloc when it needs to increase the footprint
extern "C" void* art_heap_rosalloc_morecore(allocator::RosAlloc* rosalloc, intptr_t increment) {
  Heap* heap = Runtime::Current()->GetHeap();
  RosAllocSpace* rosalloc_space = heap->GetRosAllocSpace(rosalloc);
  DCHECK(rosalloc_space != nullptr);
  DCHECK_EQ(rosalloc_space->GetRosAlloc(), rosalloc);
  return rosalloc_space->MoreCore(increment);
}

size_t RosAllocSpace::Trim() {
  VLOG(heap) << "RosAllocSpace::Trim() ";
  {
    MutexLock mu(Thread::Current(), lock_);
    // Trim to release memory at the end of the space.
    rosalloc_->Trim();
  }
  // Attempt to release pages if it does not release all empty pages.
  if (!rosalloc_->DoesReleaseAllPages()) {
    return rosalloc_->ReleasePages();
  }
  return 0;
}

void RosAllocSpace::Walk(void(*callback)(void *start, void *end, size_t num_bytes, void* callback_arg),
                         void* arg) {
  InspectAllRosAlloc(callback, arg, true);
}

size_t RosAllocSpace::GetFootprint() {
  MutexLock mu(Thread::Current(), lock_);
  return rosalloc_->Footprint();
}

size_t RosAllocSpace::GetFootprintLimit() {
  MutexLock mu(Thread::Current(), lock_);
  return rosalloc_->FootprintLimit();
}

void RosAllocSpace::SetFootprintLimit(size_t new_size) {
  MutexLock mu(Thread::Current(), lock_);
  VLOG(heap) << "RosAllocSpace::SetFootprintLimit " << PrettySize(new_size);
  // Compare against the actual footprint, rather than the Size(), because the heap may not have
  // grown all the way to the allowed size yet.
  size_t current_space_size = rosalloc_->Footprint();
  if (new_size < current_space_size) {
    // Don't let the space grow any more.
    new_size = current_space_size;
  }
  rosalloc_->SetFootprintLimit(new_size);
}

uint64_t RosAllocSpace::GetBytesAllocated() {
  size_t bytes_allocated = 0;
  InspectAllRosAlloc(art::gc::allocator::RosAlloc::BytesAllocatedCallback, &bytes_allocated, false);
  return bytes_allocated;
}

uint64_t RosAllocSpace::GetObjectsAllocated() {
  size_t objects_allocated = 0;
  InspectAllRosAlloc(art::gc::allocator::RosAlloc::ObjectsAllocatedCallback, &objects_allocated, false);
  return objects_allocated;
}

void RosAllocSpace::InspectAllRosAllocWithSuspendAll(
    void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg),
    void* arg, bool do_null_callback_at_end) NO_THREAD_SAFETY_ANALYSIS {
  // TODO: NO_THREAD_SAFETY_ANALYSIS.
  Thread* self = Thread::Current();
  ThreadList* tl = Runtime::Current()->GetThreadList();
  tl->SuspendAll();
  {
    MutexLock mu(self, *Locks::runtime_shutdown_lock_);
    MutexLock mu2(self, *Locks::thread_list_lock_);
    rosalloc_->InspectAll(callback, arg);
    if (do_null_callback_at_end) {
      callback(NULL, NULL, 0, arg);  // Indicate end of a space.
    }
  }
  tl->ResumeAll();
}

void RosAllocSpace::InspectAllRosAlloc(void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg),
                                       void* arg, bool do_null_callback_at_end) NO_THREAD_SAFETY_ANALYSIS {
  // TODO: NO_THREAD_SAFETY_ANALYSIS.
  Thread* self = Thread::Current();
  if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
    // The mutators are already suspended. For example, a call path
    // from SignalCatcher::HandleSigQuit().
    rosalloc_->InspectAll(callback, arg);
    if (do_null_callback_at_end) {
      callback(NULL, NULL, 0, arg);  // Indicate end of a space.
    }
  } else if (Locks::mutator_lock_->IsSharedHeld(self)) {
    // The mutators are not suspended yet and we have a shared access
    // to the mutator lock. Temporarily release the shared access by
    // transitioning to the suspend state, and suspend the mutators.
    self->TransitionFromRunnableToSuspended(kSuspended);
    InspectAllRosAllocWithSuspendAll(callback, arg, do_null_callback_at_end);
    self->TransitionFromSuspendedToRunnable();
    Locks::mutator_lock_->AssertSharedHeld(self);
  } else {
    // The mutators are not suspended yet. Suspend the mutators.
    InspectAllRosAllocWithSuspendAll(callback, arg, do_null_callback_at_end);
  }
}

void RosAllocSpace::RevokeThreadLocalBuffers(Thread* thread) {
  rosalloc_->RevokeThreadLocalRuns(thread);
}

void RosAllocSpace::RevokeAllThreadLocalBuffers() {
  rosalloc_->RevokeAllThreadLocalRuns();
}

void RosAllocSpace::AssertAllThreadLocalBuffersAreRevoked() {
  if (kIsDebugBuild) {
    rosalloc_->AssertAllThreadLocalRunsAreRevoked();
  }
}

void RosAllocSpace::Clear() {
  size_t footprint_limit = GetFootprintLimit();
  madvise(GetMemMap()->Begin(), GetMemMap()->Size(), MADV_DONTNEED);
  live_bitmap_->Clear();
  mark_bitmap_->Clear();
  SetEnd(begin_ + starting_size_);
  delete rosalloc_;
  rosalloc_ = CreateRosAlloc(mem_map_->Begin(), starting_size_, initial_size_,
                             NonGrowthLimitCapacity(), low_memory_mode_);
  SetFootprintLimit(footprint_limit);
}

}  // namespace space
}  // namespace gc
}  // namespace art
<|endoftext|>


<commit_before>#ifndef BOLA_H
#define BOLA_H

#include "auxiliares.hpp"
#include "tipoClasses.hpp"

class Bola{
  estadoBola estadoAtualBola; // Todas as informacoes sobre a bola
  estadoBola estadoPrevistoBola; // Todas as informacoes sobre as posicoes(provaveis) futuras da bola.

  public:
    // Retorna a posicao xy da bola.
    inline posXY getPosicaoAtualBola ();

    // Retorna o vetor sentido da bola
    inline vetorSentido getVetorSentidoAtualBola ();

    // Retorna a velocidade atual da bola
    inline float getVelocidadeAtualBola ();

    // Retorna a posicao xy prevista da bola.
    inline posXY getPosicaoPrevistoBola ();

    // Retorna o vetor sentido previsto da bola
    inline vetorSentido getVetorSentidoPrevistoBola ();

    // Retorna a velocidade prevista da bola
    inline float getVelocidadePrevistoBola ();

};

#endif /* BOLA_H*/<commit_msg>Adicionadas notas para implementações futuras.<commit_after>#ifndef BOLA_H
#define BOLA_H

#include "auxiliares.hpp"
#include "tipoClasses.hpp"

class Bola{
  estadoBola estadoAtualBola; // Todas as informacoes sobre a bola
  estadoBola estadoPrevistoBola; // Todas as informacoes sobre as posicoes(provaveis) futuras da bola.

  public:
    // Retorna a posicao xy da bola.
    inline posXY getPosicaoAtualBola ();

    // Retorna o vetor sentido da bola
    inline vetorSentido getVetorSentidoAtualBola ();

    // Retorna a velocidade atual da bola
    inline float getVelocidadeAtualBola ();

    // Retorna a posicao xy prevista da bola.
    inline posXY getPosicaoPrevistoBola ();

    // Retorna o vetor sentido previsto da bola
    inline vetorSentido getVetorSentidoPrevistoBola ();

    // Retorna a velocidade prevista da bola
    inline float getVelocidadePrevistoBola ();

		// TO-DO -> criar funcao para determinar a posicao XY da bola quando ela atingir o gol
		// criar funcao para checar se a bola esta indo na diracao do nosso gol, se esta parada ou se esta indo na direcao do time adversario
		// criar funcao para determinar o vetor sentido (utilizando a posicao anterior e atual)

};

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


<commit_before>///
/// @file  MpiLoadBalancer.hpp
/// @brief The MpiLoadBalancer evenly distributes the computation
///        of the hard special leaves onto cluster nodes.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef MPILOADBALANCER_HPP
#define MPILOADBALANCER_HPP

#include <mpi.h>
#include <LoadBalancer.hpp>
#include <MpiMsg.hpp>
#include <S2Status.hpp>
#include <int128_t.hpp>
#include <stdint.h>

namespace primecount {

class MpiLoadBalancer
{
public:
  MpiLoadBalancer(maxint_t x, int64_t y, int64_t z, maxint_t s2_approx);
  void get_work(MpiMsg* msg);

private:
  void init_size();
  void update_segments(Runtime& runtime);
  double remaining_secs() const;

  int64_t z_;
  int64_t low_;
  int64_t max_low_;
  int64_t max_size_;
  int64_t segments_;
  int64_t segment_size_;
  int64_t smallest_hard_leaf_;
  maxint_t s2_hard_;
  maxint_t s2_approx_;
  double time_;
  S2Status status_;
};

} // namespace

#endif
<commit_msg>Silence compiler warning<commit_after>///
/// @file  MpiLoadBalancer.hpp
/// @brief The MpiLoadBalancer evenly distributes the computation
///        of the hard special leaves onto cluster nodes.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef MPILOADBALANCER_HPP
#define MPILOADBALANCER_HPP

#include <mpi.h>
#include <LoadBalancer.hpp>
#include <MpiMsg.hpp>
#include <S2Status.hpp>
#include <int128_t.hpp>
#include <stdint.h>

namespace primecount {

class MpiLoadBalancer
{
public:
  MpiLoadBalancer(maxint_t x, int64_t y, int64_t z, maxint_t s2_approx);
  void get_work(MpiMsg* msg);

private:
  void init_size();
  void update_segments(Runtime& runtime);
  double remaining_secs() const;

  int64_t low_;
  int64_t max_low_;
  int64_t z_;
  int64_t segments_;
  int64_t segment_size_;
  int64_t max_size_;
  int64_t smallest_hard_leaf_;
  maxint_t s2_hard_;
  maxint_t s2_approx_;
  double time_;
  S2Status status_;
};

} // namespace

#endif
<|endoftext|>


<commit_before>//
// web_socket.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2013 Jack (jack at gmail dot com)
//
// Distributed under the GNU Affero General Public License, Version 3.0. (See accompanying
// file LICENSE or copy at http://www.gnu.org/licenses/agpl-3.0.txt)
//

#ifndef AVWS_WEB_SOCKET_HPP
#define AVWS_WEB_SOCKET_HPP

#include "avws.hpp"
#include <boost/noncopyable.hpp>
#include <boost/asio.hpp>
#include <boost/asio/detail/config.hpp>

namespace avws {

using boost::asio::ip::tcp;

class web_socket : public boost::noncopyable
{
	// 使用枚举类型而不是static const int, 是方便可能被用于在switch中.
	enum op_code
	{
		op_code_continuation = 0x0,
		op_code_text = 0x1,
		op_code_binary = 0x2,
		op_code_data_unused = 0x3,
		op_code_close = 0x8,
		op_code_ping = 0x9,
		op_code_pong = 0xA,
		op_code_control_unused = 0xB,
	};

public:
	/// Constructor.
	AVWS_DECL explicit web_socket(boost::asio::io_service &io)
		: m_ioservice(io)
	{
	}

	/// Destructor.
	AVWS_DECL virtual ~web_socket()
	{
	}

protected:

	boost::asio::io_service& m_ioservice;
};

} // namespace avws

#endif // AVWS_WEB_SOCKET_HPP
<commit_msg>定义一些简单的接口草案, 待商议.<commit_after>//
// web_socket.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2013 Jack (jack at gmail dot com)
//
// Distributed under the GNU Affero General Public License, Version 3.0. (See accompanying
// file LICENSE or copy at http://www.gnu.org/licenses/agpl-3.0.txt)
//

#ifndef AVWS_WEB_SOCKET_HPP
#define AVWS_WEB_SOCKET_HPP

#include "avws.hpp"
#include <boost/noncopyable.hpp>
#include <boost/asio.hpp>
#include <boost/asio/detail/config.hpp>

namespace avws {

using boost::asio::ip::tcp;

class web_socket : public boost::noncopyable
{
	// 使用枚举类型而不是static const int, 是方便可能被用于在switch中.
	enum op_code
	{
		op_code_continuation = 0x0,
		op_code_text = 0x1,
		op_code_binary = 0x2,
		op_code_data_unused = 0x3,
		op_code_close = 0x8,
		op_code_ping = 0x9,
		op_code_pong = 0xA,
		op_code_control_unused = 0xB,
	};

public:
	// Constructor.
	AVWS_DECL explicit web_socket(boost::asio::io_service &io)
		: m_ioservice(io)
	{
	}

	// Destructor.
	AVWS_DECL virtual ~web_socket()
	{
	}

	// 设置请求选项信息, 必须在open或accept之前设置.
	AVWS_DECL void request_options(const request_opts &options);
	// 返回当前连接的请求选项.
	AVWS_DECL request_opts request_options(void) const;
	// 返回当前连接的回复选项信息.
	AVWS_DECL response_opts response_options(void) const;

	// 在open或accept的步骤里, 实行了websocket认证.

	// 打开url.
	AVWS_DECL void open(const url &u);
	AVWS_DECL void open(const url &u, boost::system::error_code &ec);

	// 异步打开url.
	template <typename Handler>
	void async_open(const url &u, BOOST_ASIO_MOVE_ARG(Handler) handler);

	// 关闭底层连接.
	AVWS_DECL void close();
	AVWS_DECL void close(boost::system::error_code &ec);

	// 在websocket中, 数据封装成frame由发送函数实现, 上层用户无需操心.
	// 至于是文本还是二进制, 由request_options确定.

	// 同步发送一些数据.
	template <typename ConstBufferSequence>
	std::size_t write_some(const ConstBufferSequence &buffers);
	// 同步发送一些数据.
	template <typename ConstBufferSequence>
	std::size_t write_some(const ConstBufferSequence &buffers,
		boost::system::error_code &ec);

	// 异步发送一些数据.
	template <typename ConstBufferSequence, typename Handler>
	void async_write_some(const ConstBufferSequence &buffers, BOOST_ASIO_MOVE_ARG(Handler) handler);

	// 同步发送ping消息.
	AVWS_DECL void ping();
	AVWS_DECL void ping(boost::system::error_code &ec);

	// 同步发送带payload的ping消息.
	template <typename ConstBufferSequence>
	void ping(const ConstBufferSequence &buffers);
	template <typename ConstBufferSequence>
	void ping(const ConstBufferSequence &buffers, boost::system::error_code &ec);

	// 异步发送ping消息.
	template <typename Handler>
	void async_ping(BOOST_ASIO_MOVE_ARG(Handler) handler);
	// 异步发送payload的ping消息.
	template <typename ConstBufferSequence, typename Handler>
	void async_ping(const ConstBufferSequence &buffers, BOOST_ASIO_MOVE_ARG(Handler) handler);

	// 同步发送pong消息.
	AVWS_DECL void pong();
	AVWS_DECL void pong(boost::system::error_code &ec);

	// 同步发送带payload的pong消息.
	template <typename ConstBufferSequence>
	void pong(const ConstBufferSequence &buffers);
	template <typename ConstBufferSequence>
	void pong(const ConstBufferSequence &buffers, boost::system::error_code &ec);

	// 异步发送pong消息.
	template <typename Handler>
	void async_pong(BOOST_ASIO_MOVE_ARG(Handler) handler);
	// 异步发送payload的ping消息.
	template <typename ConstBufferSequence, typename Handler>
	void async_pong(const ConstBufferSequence &buffers, BOOST_ASIO_MOVE_ARG(Handler) handler);

	// 欠缺的考虑, FIN消息控制.

protected:

	boost::asio::io_service& m_ioservice;
};

} // namespace avws

#endif // AVWS_WEB_SOCKET_HPP
<|endoftext|>


<commit_before>
#include "EnvironmentSettings.hpp"
#include "Project.hpp"
#include "Workspace.hpp"

Workspace::Workspace()
	: m_devTools(ln::makeRef<BuildEnvironment>())
{
	m_devTools->setupPathes();
}

Workspace::~Workspace()
{
}

Result Workspace::openProject(const ln::Path& dir)
{
	m_project = ln::makeRef<Project>(this);
	return m_project->openProject(dir);
}

Result Workspace::runProject(const ln::String& target)
{
	// Windows
	if (ln::String::compare(target, u"Windows", ln::CaseSensitivity::CaseInsensitive) == 0)
	{
		auto exe = ln::FileSystem::getFile(ln::Path(m_project->windowsProjectDir(), u"bin/Debug"), u"*.exe");
		ln::Process::execute(exe);
	}
	// Web
	else if (ln::String::compare(target, u"Web", ln::CaseSensitivity::CaseInsensitive) == 0)
	{
		auto buildDir = ln::Path::combine(m_project->buildDir(), u"Web").canonicalize();

		ln::Process proc;
		proc.setProgram(m_devTools->python2());
		proc.setArguments({u"-m", u"SimpleHTTPServer", u"8000"});
		proc.setWorkingDirectory(buildDir);
		proc.setUseShellExecute(false);
		proc.start();

		{
			auto files = ln::FileSystem::getFiles(buildDir, u"*.html");
			if (files.isEmpty()) {
				CLI::error("Not found *.html file.");
				return Result::Fail;
			}

			ln::Process proc2;
			proc2.setProgram(u"http://localhost:8000/" + (*files.begin()).fileName());
			proc2.start();
		}

		proc.wait();
	}
	else
	{
		CLI::error(ln::String::format(u"{0} is invalid target.", target));
		return Result::Fail;
	}

	return Result::Success;
}

Result Workspace::restoreProject()
{
	m_project->restore();
	return Result::Success;
}

Result Workspace::dev_installTools() const
{
	m_devTools->prepareEmscriptenSdk();

	return Result::Success;
}

void Workspace::dev_openIde(const ln::String& target) const
{
#if defined(_WIN32)
	if (ln::String::compare(target, u"Android", ln::CaseSensitivity::CaseInsensitive) == 0)
	{
		HKEY hKey = NULL;
		LONG lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
			L"SOFTWARE\\Android Studio",
			NULL,
			KEY_READ | KEY_WOW64_64KEY,	// https://stackoverflow.com/questions/252297/why-is-regopenkeyex-returning-error-code-2-on-vista-64bit
			&hKey);
		if (lRet != ERROR_SUCCESS) {
			LN_LOG_ERROR << u"Android Studio not installed.";
			return;
		}

		DWORD type, size;
		WCHAR path[MAX_PATH];
		RegQueryValueExW(hKey, L"Path", NULL, &type, (LPBYTE)path, &size);

		ln::Environment::setEnvironmentVariable(u"LUMINO", buildEnvironment()->luminoPackageRootDir());

		ln::Process proc;
		proc.setProgram(ln::Path::combine(ln::String::fromCString(path), u"bin", u"studio"));
		proc.setArguments({ m_project->androidProjectDir() });
		proc.start();
	}
	else
	{
		auto files = ln::FileSystem::getFiles(ln::Environment::currentDirectory(), u"*.sln");
		if (files.isEmpty()) {
			CLI::error("Not found *.sln file.");
			return;
		}

		ln::Environment::setEnvironmentVariable(u"LUMINO", buildEnvironment()->luminoPackageRootDir());

		ln::Process proc;
		proc.setProgram(*files.begin());
		proc.start();
	}
#elif defined(__APPLE__)
	ln::Process proc;
	proc.setProgram(u"/usr/bin/open");
	proc.setArguments({ u"/Applications/Xcode.app/", ln::Path(m_project->macOSProjectDir(), u"LuminoApp.macOS.xcodeproj") });
	proc.start();
#else
	LN_NOTIMPLEMENTED();	// TODO: putenv は書き込み可能なポインタを渡さないとならないみたい？
#endif
}
<commit_msg>fix cli run failure<commit_after>
#include "EnvironmentSettings.hpp"
#include "Project.hpp"
#include "Workspace.hpp"

Workspace::Workspace()
	: m_devTools(ln::makeRef<BuildEnvironment>())
{
	m_devTools->setupPathes();
}

Workspace::~Workspace()
{
}

Result Workspace::openProject(const ln::Path& dir)
{
	m_project = ln::makeRef<Project>(this);
	return m_project->openProject(dir);
}

Result Workspace::runProject(const ln::String& target)
{
	// Windows
	if (ln::String::compare(target, u"Windows", ln::CaseSensitivity::CaseInsensitive) == 0)
	{
		auto exe = ln::FileSystem::getFile(ln::Path(m_project->windowsProjectDir(), u"bin/Debug"), u"*.exe");
		ln::Process::execute(exe);
	}
	// Web
	else if (ln::String::compare(target, u"Web", ln::CaseSensitivity::CaseInsensitive) == 0)
	{
		auto buildDir = ln::Path::combine(m_project->buildDir(), u"Web").canonicalize();

		ln::Process proc;
		proc.setProgram(m_devTools->python2());
		proc.setArguments({u"-m", u"SimpleHTTPServer", u"8000"});
		proc.setWorkingDirectory(buildDir);
		proc.setUseShellExecute(false);
		proc.start();

		{
			auto files = ln::FileSystem::getFiles(buildDir, u"*.html");
			if (files.isEmpty()) {
				CLI::error("Not found *.html file.");
				return Result::Fail;
			}

			ln::Process proc2;
            proc2.setUseShellExecute(true);
			proc2.setProgram(u"http://localhost:8000/" + (*files.begin()).fileName());
			proc2.start();
		}

		proc.wait();
	}
	else
	{
		CLI::error(ln::String::format(u"{0} is invalid target.", target));
		return Result::Fail;
	}

	return Result::Success;
}

Result Workspace::restoreProject()
{
	m_project->restore();
	return Result::Success;
}

Result Workspace::dev_installTools() const
{
	m_devTools->prepareEmscriptenSdk();

	return Result::Success;
}

void Workspace::dev_openIde(const ln::String& target) const
{
#if defined(_WIN32)
	if (ln::String::compare(target, u"Android", ln::CaseSensitivity::CaseInsensitive) == 0)
	{
		HKEY hKey = NULL;
		LONG lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
			L"SOFTWARE\\Android Studio",
			NULL,
			KEY_READ | KEY_WOW64_64KEY,	// https://stackoverflow.com/questions/252297/why-is-regopenkeyex-returning-error-code-2-on-vista-64bit
			&hKey);
		if (lRet != ERROR_SUCCESS) {
			LN_LOG_ERROR << u"Android Studio not installed.";
			return;
		}

		DWORD type, size;
		WCHAR path[MAX_PATH];
		RegQueryValueExW(hKey, L"Path", NULL, &type, (LPBYTE)path, &size);

		ln::Environment::setEnvironmentVariable(u"LUMINO", buildEnvironment()->luminoPackageRootDir());

		ln::Process proc;
		proc.setProgram(ln::Path::combine(ln::String::fromCString(path), u"bin", u"studio"));
		proc.setArguments({ m_project->androidProjectDir() });
		proc.start();
	}
	else
	{
		auto files = ln::FileSystem::getFiles(ln::Environment::currentDirectory(), u"*.sln");
		if (files.isEmpty()) {
			CLI::error("Not found *.sln file.");
			return;
		}

		ln::Environment::setEnvironmentVariable(u"LUMINO", buildEnvironment()->luminoPackageRootDir());

		ln::Process proc;
		proc.setProgram(*files.begin());
		proc.start();
	}
#elif defined(__APPLE__)
	ln::Process proc;
	proc.setProgram(u"/usr/bin/open");
	proc.setArguments({ u"/Applications/Xcode.app/", ln::Path(m_project->macOSProjectDir(), u"LuminoApp.macOS.xcodeproj") });
	proc.start();
#else
	LN_NOTIMPLEMENTED();	// TODO: putenv は書き込み可能なポインタを渡さないとならないみたい？
#endif
}
<|endoftext|>


<commit_before>#ifndef __CALCULATE_LEXER_HPP__
#define __CALCULATE_LEXER_HPP__

#include <complex>
#include <iomanip>
#include <locale>
#include <sstream>
#include <unordered_set>

#include "util.hpp"

namespace calculate {

namespace detail {

struct RegexesInitializer {
    std::string number;
    std::string name;
    std::string symbol;
};

struct StringsInitializer {
    std::string left;
    std::string right;
    std::string separator;
    std::string decimal;
};

inline std::unordered_set<char> regex_scaped() {
    static std::unordered_set<char> chars =
        {'\\', '.', '^', '$', '*', '+', '?', '(', ')', '[', '{'};
    return chars;
}

}

inline std::string default_number() {
    return R"_(^(?:\d+\.?\d*|\.\d+)+(?:[eE][+\-]?\d+)?$)_";
}

inline std::string default_complex() {
    return R"_(^(?:\d+\.?\d*|\.\d+)+(?:[eE][+\-]?\d+)?i?$)_";
}

inline std::string default_name() { return R"_(^[A-Za-z_]+[A-Za-z_\d]*$)_"; }

inline std::string default_symbol() { return R"_(^[^A-Za-z\d.(),_\s]+$)_"; }

inline std::string default_left() { return "("; }

inline std::string default_right() { return ")"; }

inline std::string default_separator() { return ","; }

inline std::string default_decimal() { return "."; }

template<typename Type>
class BaseLexer {
public:
    const std::string left;
    const std::string right;
    const std::string separator;
    const std::string decimal;

    const std::string number;
    const std::string name;
    const std::string symbol;
    const std::string tokenizer;

    const std::regex number_regex;
    const std::regex name_regex;
    const std::regex symbol_regex;
    const std::regex tokenizer_regex;

private:
    std::string _adapt_regex(std::string regex) const {
        if (regex.front() != '^')
            regex.insert(0, 1, '^');
        if (regex.back() != '$')
            regex.append(1, '$');

        try{
            std::regex{regex};
        }
        catch(const std::regex_error&) {
            throw LexerError{"bad regex '" + regex + "'"};
        }
        return regex;
    }

    std::string _generate_tokenizer() const {
        std::string tokenizer{};

        auto escape = [](std::string token) {
            for (const auto& character : detail::regex_scaped()) {
                size_t index = 0;
                while (true) {
                    index = token.find(character, index);
                    if (index == std::string::npos)
                        break;
                    token.insert(index, 1, '\\');
                    index += 2;
                }
            }
            return token;
        };

        tokenizer += "(" + number.substr(1, number.size() - 2) + ")|";
        tokenizer += "(" + name.substr(1, name.size() - 2) + ")|";
        tokenizer += "(" + symbol.substr(1, symbol.size() - 2) + ")|";
        tokenizer += "(" + escape(left) + ")|";
        tokenizer += "(" + escape(right) + ")|";
        tokenizer += "(" + escape(separator) + ")|";
        tokenizer += "(" + escape(decimal) + ")";
        return tokenizer;
    }

public:
    BaseLexer(
        const detail::RegexesInitializer& regexes,
        const detail::StringsInitializer& strings
    ) :
            left{strings.left},
            right{strings.right},
            separator{strings.separator},
            decimal{strings.decimal},
            number{_adapt_regex(regexes.number)},
            name{_adapt_regex(regexes.name)},
            symbol{_adapt_regex(regexes.symbol)},
            tokenizer{_generate_tokenizer()},
            number_regex{number},
            name_regex{name},
            symbol_regex{symbol},
            tokenizer_regex{tokenizer}
    {
        if ((left == right || left == separator || left == decimal) ||
            (right == separator || right == decimal) ||
            (separator == decimal)
        )
            throw LexerError{"tokens must be different"};

    }
    BaseLexer(const BaseLexer&) = default;
    virtual ~BaseLexer() = default;

    BaseLexer& operator=(const BaseLexer&) = delete;
    BaseLexer& operator=(BaseLexer&&) = delete;

    virtual std::shared_ptr<BaseLexer> clone() const noexcept = 0;
    virtual Type to_value(const std::string&) const = 0;
    virtual std::string to_string(Type) const noexcept = 0;
};

template<typename Type>
class Lexer final : public BaseLexer<Type> {
    using BaseLexer = calculate::BaseLexer<Type>;

public:
    Lexer(
        const detail::RegexesInitializer& regexes={
            default_number(),
            default_name(),
            default_symbol()
        },
        const detail::StringsInitializer& strings={
            default_left(),
            default_right(),
            default_separator(),
            default_decimal()
        }
    ) : BaseLexer{regexes, strings} {}

    std::shared_ptr<BaseLexer> clone() const noexcept override {
        return std::make_shared<Lexer>(*this);
    }

    Type to_value(const std::string& token) const override {
        std::istringstream converter{token};
        Type value;

        if (!std::regex_search(token, this->number_regex))
            throw BadCast{token};
        converter.imbue(std::locale("C"));
        converter >> value;
        return value;
    }

    std::string to_string(Type value) const noexcept override {
        std::ostringstream string{};

        string << std::setprecision(std::numeric_limits<Type>::max_digits10);
        string << value;
        return string.str();
    }
};

template<typename Type>
class Lexer<std::complex<Type>> final : public BaseLexer<std::complex<Type>> {
    using BaseLexer = calculate::BaseLexer<std::complex<Type>>;

    static constexpr Type _zero = static_cast<Type>(0);

public:
    Lexer(
        const detail::RegexesInitializer& regexes={
            default_complex(),
            default_name(),
            default_symbol()
        },
        const detail::StringsInitializer& strings={
            default_left(),
            default_right(),
            default_separator(),
            default_decimal()
        }
    ) : BaseLexer{regexes, strings} {}

    std::shared_ptr<BaseLexer> clone() const noexcept override {
        return std::make_shared<Lexer>(*this);
    }

    std::complex<Type> to_value(const std::string& token) const override {
        using namespace std::complex_literals;

        std::istringstream converter{token};
        Type value;

        if (!std::regex_search(token, this->number_regex))
            throw BadCast{token};
        converter.imbue(std::locale("C"));
        converter >> value;

        if (token.back() != 'i')
            return value;
        return 1i * value;
    }

    std::string to_string(std::complex<Type> value) const noexcept override {
        std::ostringstream string{};
        Type real{std::real(value)}, imag{std::imag(value)};

        string << std::setprecision(std::numeric_limits<Type>::max_digits10);
        if (real != _zero)
            string << real << (imag > _zero ? "+" : "");
        if (real == _zero || imag != _zero)
            string << imag << (real != _zero || imag != _zero ? "i" : "");
        return string.str();
    }
};

}

namespace std {

template<typename Type>
struct hash<std::complex<Type>> {
    size_t operator()(const std::complex<Type>& z) const {
        size_t combined{hash<Type>{}(real(z))};
        calculate::util::hash_combine(combined, imag(z));
        return combined;
    }
};

}

#endif
<commit_msg>Added sanity checks for tokenizer<commit_after>#ifndef __CALCULATE_LEXER_HPP__
#define __CALCULATE_LEXER_HPP__

#include <complex>
#include <iomanip>
#include <locale>
#include <sstream>
#include <unordered_set>

#include "util.hpp"

namespace calculate {

namespace detail {

struct RegexesInitializer {
    std::string number;
    std::string name;
    std::string symbol;
};

struct StringsInitializer {
    std::string left;
    std::string right;
    std::string separator;
    std::string decimal;
};

inline std::unordered_set<char> regex_scaped() {
    static std::unordered_set<char> chars =
        {'\\', '.', '^', '$', '*', '+', '?', '(', ')', '[', '{'};
    return chars;
}

}

inline std::string default_number() {
    return R"_(^(?:\d+\.?\d*|\.\d+)+(?:[eE][+\-]?\d+)?$)_";
}

inline std::string default_complex() {
    return R"_(^(?:\d+\.?\d*|\.\d+)+(?:[eE][+\-]?\d+)?i?$)_";
}

inline std::string default_name() { return R"_(^[A-Za-z_]+[A-Za-z_\d]*$)_"; }

inline std::string default_symbol() { return R"_(^[^A-Za-z\d.(),_\s]+$)_"; }

inline std::string default_left() { return "("; }

inline std::string default_right() { return ")"; }

inline std::string default_separator() { return ","; }

inline std::string default_decimal() { return "."; }

template<typename Type>
class BaseLexer {
public:
    const std::string left;
    const std::string right;
    const std::string separator;
    const std::string decimal;

    const std::string number;
    const std::string name;
    const std::string symbol;
    const std::string tokenizer;

    const std::regex number_regex;
    const std::regex name_regex;
    const std::regex symbol_regex;
    const std::regex tokenizer_regex;

private:
    std::string _adapt_regex(std::string regex) const {
        if (regex.front() != '^')
            regex.insert(0, 1, '^');
        if (regex.back() != '$')
            regex.append(1, '$');

        try{
            std::regex{regex};
        }
        catch(const std::regex_error&) {
            throw LexerError{"bad regex '" + regex + "'"};
        }
        return regex;
    }

    std::string _generate_tokenizer() const {
        std::string tokenizer{};

        auto escape = [](std::string token) {
            for (const auto& character : detail::regex_scaped()) {
                size_t index = 0;
                while (true) {
                    index = token.find(character, index);
                    if (index == std::string::npos)
                        break;
                    token.insert(index, 1, '\\');
                    index += 2;
                }
            }
            return token;
        };

        tokenizer += "(" + number.substr(1, number.size() - 2) + ")|";
        tokenizer += "(" + name.substr(1, name.size() - 2) + ")|";
        tokenizer += "(" + symbol.substr(1, symbol.size() - 2) + ")|";
        tokenizer += "(" + escape(left) + ")|";
        tokenizer += "(" + escape(right) + ")|";
        tokenizer += "(" + escape(separator) + ")|";
        tokenizer += "(" + escape(decimal) + ")";
        return tokenizer;
    }

public:
    BaseLexer(
        const detail::RegexesInitializer& regexes,
        const detail::StringsInitializer& strings
    ) :
            left{strings.left},
            right{strings.right},
            separator{strings.separator},
            decimal{strings.decimal},
            number{_adapt_regex(regexes.number)},
            name{_adapt_regex(regexes.name)},
            symbol{_adapt_regex(regexes.symbol)},
            tokenizer{_generate_tokenizer()},
            number_regex{number},
            name_regex{name},
            symbol_regex{symbol},
            tokenizer_regex{tokenizer}
    {
        enum Group {NUMBER=1, NAME, SYMBOL, LEFT, RIGHT, SEPARATOR, DECIMAL};
        std::smatch match{};

        if (left == right ||
            left == separator ||
            left == decimal ||
            right == separator ||
            right == decimal ||
            separator == decimal
        )
            throw LexerError{"tokens must be different"};

        std::regex_search(left, match, tokenizer_regex);
        if (match[Group::LEFT].str().empty())
            throw LexerError{"tokenizer doesn't match left symbol"};
        std::regex_search(right, match, tokenizer_regex);
        if (match[Group::RIGHT].str().empty())
            throw LexerError{"tokenizer doesn't match right symbol"};
        std::regex_search(separator, match, tokenizer_regex);
        if (match[Group::SEPARATOR].str().empty())
            throw LexerError{"tokenizer doesn't match separator symbol"};
        std::regex_search(decimal, match, tokenizer_regex);
        if (match[Group::DECIMAL].str().empty())
            throw LexerError{"tokenizer doesn't match decimal symbol"};
    }
    BaseLexer(const BaseLexer&) = default;
    virtual ~BaseLexer() = default;

    BaseLexer& operator=(const BaseLexer&) = delete;
    BaseLexer& operator=(BaseLexer&&) = delete;

    virtual std::shared_ptr<BaseLexer> clone() const noexcept = 0;
    virtual Type to_value(const std::string&) const = 0;
    virtual std::string to_string(Type) const noexcept = 0;
};

template<typename Type>
class Lexer final : public BaseLexer<Type> {
    using BaseLexer = calculate::BaseLexer<Type>;

public:
    Lexer(
        const detail::RegexesInitializer& regexes={
            default_number(),
            default_name(),
            default_symbol()
        },
        const detail::StringsInitializer& strings={
            default_left(),
            default_right(),
            default_separator(),
            default_decimal()
        }
    ) : BaseLexer{regexes, strings} {}

    std::shared_ptr<BaseLexer> clone() const noexcept override {
        return std::make_shared<Lexer>(*this);
    }

    Type to_value(const std::string& token) const override {
        std::istringstream converter{token};
        Type value;

        if (!std::regex_search(token, this->number_regex))
            throw BadCast{token};
        converter.imbue(std::locale("C"));
        converter >> value;
        return value;
    }

    std::string to_string(Type value) const noexcept override {
        std::ostringstream string{};

        string << std::setprecision(std::numeric_limits<Type>::max_digits10);
        string << value;
        return string.str();
    }
};

template<typename Type>
class Lexer<std::complex<Type>> final : public BaseLexer<std::complex<Type>> {
    using BaseLexer = calculate::BaseLexer<std::complex<Type>>;

    static constexpr Type _zero = static_cast<Type>(0);

public:
    Lexer(
        const detail::RegexesInitializer& regexes={
            default_complex(),
            default_name(),
            default_symbol()
        },
        const detail::StringsInitializer& strings={
            default_left(),
            default_right(),
            default_separator(),
            default_decimal()
        }
    ) : BaseLexer{regexes, strings} {}

    std::shared_ptr<BaseLexer> clone() const noexcept override {
        return std::make_shared<Lexer>(*this);
    }

    std::complex<Type> to_value(const std::string& token) const override {
        using namespace std::complex_literals;

        std::istringstream converter{token};
        Type value;

        if (!std::regex_search(token, this->number_regex))
            throw BadCast{token};
        converter.imbue(std::locale("C"));
        converter >> value;

        if (token.back() != 'i')
            return value;
        return 1i * value;
    }

    std::string to_string(std::complex<Type> value) const noexcept override {
        std::ostringstream string{};
        Type real{std::real(value)}, imag{std::imag(value)};

        string << std::setprecision(std::numeric_limits<Type>::max_digits10);
        if (real != _zero)
            string << real << (imag > _zero ? "+" : "");
        if (real == _zero || imag != _zero)
            string << imag << (real != _zero || imag != _zero ? "i" : "");
        return string.str();
    }
};

}

namespace std {

template<typename Type>
struct hash<std::complex<Type>> {
    size_t operator()(const std::complex<Type>& z) const {
        size_t combined{hash<Type>{}(real(z))};
        calculate::util::hash_combine(combined, imag(z));
        return combined;
    }
};

}

#endif
<|endoftext|>


<commit_before>#pragma once

/// \defgroup order-book Order book management
///
/// Order book management provides support for reconstructing and
/// querying per-asset order book state such as top and depth of book bid
/// and ask price and size.

#include <unordered_map>
#include <cstdint>
#include <utility>
#include <memory>
#include <string>
#include <list>
#include <map>

namespace helix {

namespace core {

/// \addtogroup order-book
/// @{

/// \brief Order side.
enum class side_type {
    /// Buy order
    buy,
    /// Sell order
    sell,
};

/// \brief Trading state.
enum class trading_state {
    /// Trading state is unknown.
    unknown,
    /// Trading is halted.
    halted,
    /// Trading is paused.
    paused,
    /// Quotation only period.
    quotation_only,
    /// Trading is ongoing.
    trading,
    /// Auction period.
    auction,
};

struct price_level;

/// \brief Order is a request to buy or sell quantity of asset at a
/// specified price.
struct order {
    order(uint64_t id_, uint64_t price_, uint64_t quantity_, side_type side_)
        : level(nullptr)
        , id(id_)
        , price(price_)
        , quantity(quantity_)
        , side(side_)
    {}

    order(const order&) = default;
    order(order&&) = default;
    order& operator=(const order&) = default;

    price_level* level;
    uint64_t     id;
    uint64_t     price;
    uint64_t     quantity;
    side_type    side;
};

/// \brief Price level is a time-prioritized list of orders with the same price.
struct price_level {
    price_level(uint64_t price_)
        : price(price_)
        , size(0)
    { }

    price_level(const price_level&) = default;
    price_level& operator=(const price_level&) = default;

    uint64_t price;
    uint64_t size;

    // Order IDs sorted by timestamp (ascending order):
    std::list<uint64_t> orders;
};

/// \brief Order book is a price-time prioritized list of buy and sell
/// orders.

class order_book {
private:
    std::string _symbol;
    uint64_t _timestamp;
    trading_state _state;
    std::unordered_map<uint64_t, order> _orders;
    std::map<uint64_t, price_level, std::greater<uint64_t>> _bids;
    std::map<uint64_t, price_level, std::less   <uint64_t>> _asks;
public:
    using iterator = std::unordered_map<uint64_t, order>::iterator;

    order_book(const std::string& symbol, uint64_t timestamp);
    ~order_book();

    order_book(const order_book&) = default;
    order_book(order_book&&) = default;
    order_book& operator=(const order_book&) = default;

    const std::string& symbol() const {
        return _symbol;
    }

    void set_timestamp(uint64_t timestamp) {
        _timestamp = timestamp;
    }

    uint64_t timestamp() const {
        return _timestamp;
    }

    void set_state(trading_state state) {
        _state = state;
    }

    trading_state state() const {
        return _state;
    }

    void add(order&& order);
    void cancel(uint64_t order_id, uint64_t quantity);
    std::pair<uint64_t, side_type> execute(uint64_t order_id, uint64_t quantity);
    void remove(uint64_t order_id);
    side_type side(uint64_t order_id) const;

    size_t bid_levels() const;
    size_t ask_levels() const;

    uint64_t bid_price(size_t level) const;
    uint64_t bid_size (size_t level) const;
    uint64_t ask_price(size_t level) const;
    uint64_t ask_size (size_t level) const;
    uint64_t midprice (size_t level) const;

private:
    void remove(iterator& iter);

    template<typename T>
    void remove(order& o, T& levels);

    template<typename T>
    price_level& lookup_or_create(T& levels, uint64_t price);
};

/// @}

}

}
<commit_msg>order_book: Clean up order struct<commit_after>#pragma once

/// \defgroup order-book Order book management
///
/// Order book management provides support for reconstructing and
/// querying per-asset order book state such as top and depth of book bid
/// and ask price and size.

#include <unordered_map>
#include <cstdint>
#include <utility>
#include <memory>
#include <string>
#include <list>
#include <map>

namespace helix {

namespace core {

/// \addtogroup order-book
/// @{

/// \brief Order side.
enum class side_type {
    /// Buy order
    buy,
    /// Sell order
    sell,
};

/// \brief Trading state.
enum class trading_state {
    /// Trading state is unknown.
    unknown,
    /// Trading is halted.
    halted,
    /// Trading is paused.
    paused,
    /// Quotation only period.
    quotation_only,
    /// Trading is ongoing.
    trading,
    /// Auction period.
    auction,
};

struct price_level;

/// \brief Order is a request to buy or sell quantity of asset at a
/// specified price.
struct order final {
    price_level* level;
    uint64_t     id;
    uint64_t     price;
    uint64_t     quantity;
    side_type    side;

    order(uint64_t id, uint64_t price, uint64_t quantity, side_type side)
        : level{nullptr}
        , id{id}
        , price{price}
        , quantity{quantity}
        , side{side}
    {}

    order(const order&) = default;
    order(order&&) = default;
    order& operator=(const order&) = default;
};

/// \brief Price level is a time-prioritized list of orders with the same price.
struct price_level {
    price_level(uint64_t price_)
        : price(price_)
        , size(0)
    { }

    price_level(const price_level&) = default;
    price_level& operator=(const price_level&) = default;

    uint64_t price;
    uint64_t size;

    // Order IDs sorted by timestamp (ascending order):
    std::list<uint64_t> orders;
};

/// \brief Order book is a price-time prioritized list of buy and sell
/// orders.

class order_book {
private:
    std::string _symbol;
    uint64_t _timestamp;
    trading_state _state;
    std::unordered_map<uint64_t, order> _orders;
    std::map<uint64_t, price_level, std::greater<uint64_t>> _bids;
    std::map<uint64_t, price_level, std::less   <uint64_t>> _asks;
public:
    using iterator = std::unordered_map<uint64_t, order>::iterator;

    order_book(const std::string& symbol, uint64_t timestamp);
    ~order_book();

    order_book(const order_book&) = default;
    order_book(order_book&&) = default;
    order_book& operator=(const order_book&) = default;

    const std::string& symbol() const {
        return _symbol;
    }

    void set_timestamp(uint64_t timestamp) {
        _timestamp = timestamp;
    }

    uint64_t timestamp() const {
        return _timestamp;
    }

    void set_state(trading_state state) {
        _state = state;
    }

    trading_state state() const {
        return _state;
    }

    void add(order&& order);
    void cancel(uint64_t order_id, uint64_t quantity);
    std::pair<uint64_t, side_type> execute(uint64_t order_id, uint64_t quantity);
    void remove(uint64_t order_id);
    side_type side(uint64_t order_id) const;

    size_t bid_levels() const;
    size_t ask_levels() const;

    uint64_t bid_price(size_t level) const;
    uint64_t bid_size (size_t level) const;
    uint64_t ask_price(size_t level) const;
    uint64_t ask_size (size_t level) const;
    uint64_t midprice (size_t level) const;

private:
    void remove(iterator& iter);

    template<typename T>
    void remove(order& o, T& levels);

    template<typename T>
    price_level& lookup_or_create(T& levels, uint64_t price);
};

/// @}

}

}
<|endoftext|>


<commit_before>/*
	Copyright (C) 2004-2005 Cory Nelson

	This software is provided 'as-is', without any express or implied
	warranty.  In no event will the authors be held liable for any damages
	arising from the use of this software.

	Permission is granted to anyone to use this software for any purpose,
	including commercial applications, and to alter it and redistribute it
	freely, subject to the following restrictions:

	1. The origin of this software must not be misrepresented; you must not
		claim that you wrote the original software. If you use this software
		in a product, an acknowledgment in the product documentation would be
		appreciated but is not required.
	2. Altered source versions must be plainly marked as such, and must not be
		misrepresented as being the original software.
	3. This notice may not be removed or altered from any source distribution.
*/

// namespaces added by Arvid Norberg

#ifndef __UTF8_H__
#define __UTF8_H__

#include <string>
#include <iterator>
#include <stdexcept>

namespace libtorrent {
namespace detail {

template<typename InputIterator>
static wchar_t decode_utf8_mb(InputIterator &iter, InputIterator last) {
	if(iter==last) throw std::runtime_error("incomplete UTF-8 sequence");
	if(((*iter)&0xC0)!=0x80) throw std::runtime_error("invalid UTF-8 sequence");

	return (wchar_t)((*iter++)&0x3F);
}

template<typename InputIterator>
static wchar_t decode_utf8(InputIterator &iter, InputIterator last) {
	wchar_t ret;

	if(((*iter)&0x80) == 0) {
		ret=*iter++;
	}
	else if(((*iter)&0x20) == 0) {
		ret=(
			(((wchar_t)((*iter++)&0x1F)) << 6) |
			decode_utf8_mb(iter, last)
		);
	}
	else if(((*iter)&0x10) == 0) {
		ret=(
			(((wchar_t)((*iter++)&0x0F)) << 12) |
			(decode_utf8_mb(iter, last) << 6) |
			decode_utf8_mb(iter, last)
		);
	}
	else throw std::runtime_error("UTF-8 not convertable to UTF-16");

	return ret;
}

template<typename InputIterator, typename OutputIterator>
static OutputIterator utf8_wchar(InputIterator first, InputIterator last, OutputIterator dest) {
	for(; first!=last; ++dest)
		*dest=decode_utf8(first, last);
	return dest;
}

template<typename InputIterator, typename OutputIterator>
static void encode_wchar(InputIterator iter, OutputIterator &dest) {
	if(*iter <= 0x007F) {
		*dest=(char)*iter;
		++dest;
	}
	else if(*iter <= 0x07FF) {
		*dest = (char)(
			0xC0 |
			((*iter & 0x07C0) >> 6)
		);
		++dest;

		*dest = (char)(
			0x80 |
			(*iter & 0x003F)
		);
		++dest;
	}
	else if(*iter <= 0xFFFF) {
		*dest = (char)(
			0xE0 |
			((*iter & 0xF000) >> 12)
		);
		++dest;

		*dest = (char)(
			0x80 |
			((*iter & 0x0FC0) >> 6)
		);
		++dest;

		*dest = (char)(
			0x80 |
			(*iter & 0x003F)
		);
		++dest;
	}
}

template<typename InputIterator, typename OutputIterator>
static OutputIterator wchar_utf8(InputIterator first, InputIterator last, OutputIterator dest) {
	for(; first!=last; ++first)
		encode_wchar(first, dest);
	return dest;
}

}

static void utf8_wchar(const std::string &utf8, std::wstring &wide) {
	wide.clear();
	detail::utf8_wchar(utf8.begin(), utf8.end(), std::insert_iterator<std::wstring>(wide, wide.end()));
}

static std::wstring utf8_wchar(const std::string &str) {
	std::wstring ret;
	utf8_wchar(str, ret);
	return ret;
}

static std::string wchar_utf8(const std::wstring &wide, std::string &utf8) {
	utf8.clear();
	detail::wchar_utf8(wide.begin(), wide.end(), std::insert_iterator<std::string>(utf8, utf8.end()));
}

static std::string wchar_utf8(const std::wstring &str) {
	std::string ret;
	wchar_utf8(str, ret);
	return ret;
}

}

#endif
<commit_msg>*** empty log message ***<commit_after>/*
	Copyright (C) 2004-2005 Cory Nelson

	This software is provided 'as-is', without any express or implied
	warranty.  In no event will the authors be held liable for any damages
	arising from the use of this software.

	Permission is granted to anyone to use this software for any purpose,
	including commercial applications, and to alter it and redistribute it
	freely, subject to the following restrictions:

	1. The origin of this software must not be misrepresented; you must not
		claim that you wrote the original software. If you use this software
		in a product, an acknowledgment in the product documentation would be
		appreciated but is not required.
	2. Altered source versions must be plainly marked as such, and must not be
		misrepresented as being the original software.
	3. This notice may not be removed or altered from any source distribution.
*/

// namespaces added by Arvid Norberg

#ifndef __UTF8_H__
#define __UTF8_H__

#include <string>
#include <iterator>
#include <stdexcept>

namespace libtorrent {
namespace detail {

template<typename InputIterator>
static wchar_t decode_utf8_mb(InputIterator &iter, InputIterator last) {
	if(iter==last) throw std::runtime_error("incomplete UTF-8 sequence");
	if(((*iter)&0xC0)!=0x80) throw std::runtime_error("invalid UTF-8 sequence");

	return (wchar_t)((*iter++)&0x3F);
}

template<typename InputIterator>
static wchar_t decode_utf8(InputIterator &iter, InputIterator last) {
	wchar_t ret;

	if(((*iter)&0x80) == 0) {
		ret=*iter++;
	}
	else if(((*iter)&0x20) == 0) {
		ret=(
			(((wchar_t)((*iter++)&0x1F)) << 6) |
			decode_utf8_mb(iter, last)
		);
	}
	else if(((*iter)&0x10) == 0) {
		ret=(
			(((wchar_t)((*iter++)&0x0F)) << 12) |
			(decode_utf8_mb(iter, last) << 6) |
			decode_utf8_mb(iter, last)
		);
	}
	else throw std::runtime_error("UTF-8 not convertable to UTF-16");

	return ret;
}

template<typename InputIterator, typename OutputIterator>
static OutputIterator utf8_wchar(InputIterator first, InputIterator last, OutputIterator dest) {
	for(; first!=last; ++dest)
		*dest=decode_utf8(first, last);
	return dest;
}

template<typename InputIterator, typename OutputIterator>
static void encode_wchar(InputIterator iter, OutputIterator &dest) {
	if(*iter <= 0x007F) {
		*dest=(char)*iter;
		++dest;
	}
	else if(*iter <= 0x07FF) {
		*dest = (char)(
			0xC0 |
			((*iter & 0x07C0) >> 6)
		);
		++dest;

		*dest = (char)(
			0x80 |
			(*iter & 0x003F)
		);
		++dest;
	}
	else if(*iter <= 0xFFFF) {
		*dest = (char)(
			0xE0 |
			((*iter & 0xF000) >> 12)
		);
		++dest;

		*dest = (char)(
			0x80 |
			((*iter & 0x0FC0) >> 6)
		);
		++dest;

		*dest = (char)(
			0x80 |
			(*iter & 0x003F)
		);
		++dest;
	}
}

template<typename InputIterator, typename OutputIterator>
static OutputIterator wchar_utf8(InputIterator first, InputIterator last, OutputIterator dest) {
	for(; first!=last; ++first)
		encode_wchar(first, dest);
	return dest;
}

}

static void utf8_wchar(const std::string &utf8, std::wstring &wide) {
	wide.clear();
	detail::utf8_wchar(utf8.begin(), utf8.end(), std::insert_iterator<std::wstring>(wide, wide.end()));
}

static std::wstring utf8_wchar(const std::string &str) {
	std::wstring ret;
	utf8_wchar(str, ret);
	return ret;
}

static void wchar_utf8(const std::wstring &wide, std::string &utf8) {
	utf8.clear();
	detail::wchar_utf8(wide.begin(), wide.end(), std::insert_iterator<std::string>(utf8, utf8.end()));
}

static std::string wchar_utf8(const std::wstring &str) {
	std::string ret;
	wchar_utf8(str, ret);
	return ret;
}

}

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: inimgr.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2007-04-11 20:06:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _INIMGR_HXX
#define _INIMGR_HXX

#include <tools/fsys.hxx>
#include <tools/string.hxx>

/*****************************************************************************
Purpose: Allows to work on a local set of initialisation files
If Update is used, the user must ensure that only one set of
Source and Destination Dir is used. Otherwise ForceUpdate has to be used
*****************************************************************************/

class IniManager
{
private:
    BOOL bUpdate;

    ByteString sGlobalDir;      /// holds the org. ini dir
    ByteString sLocalPath;      /// holds path of local ini dir

public:
    IniManager( ByteString &rDir, ByteString &rLocalDir );
    IniManager( ByteString &rDir );
    IniManager();

    ByteString ToLocal( ByteString &rPath );
    void Update();          /// Call ForceUpdate the First Time called
    void ForceUpdate();

    static ByteString GetLocalIni();
    static ByteString GetGlobalIni();
};

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.3.120); FILE MERGED 2008/03/28 15:41:04 rt 1.3.120.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: inimgr.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _INIMGR_HXX
#define _INIMGR_HXX

#include <tools/fsys.hxx>
#include <tools/string.hxx>

/*****************************************************************************
Purpose: Allows to work on a local set of initialisation files
If Update is used, the user must ensure that only one set of
Source and Destination Dir is used. Otherwise ForceUpdate has to be used
*****************************************************************************/

class IniManager
{
private:
    BOOL bUpdate;

    ByteString sGlobalDir;      /// holds the org. ini dir
    ByteString sLocalPath;      /// holds path of local ini dir

public:
    IniManager( ByteString &rDir, ByteString &rLocalDir );
    IniManager( ByteString &rDir );
    IniManager();

    ByteString ToLocal( ByteString &rPath );
    void Update();          /// Call ForceUpdate the First Time called
    void ForceUpdate();

    static ByteString GetLocalIni();
    static ByteString GetGlobalIni();
};

#endif

<|endoftext|>


<commit_before>#ifndef RAINBACK_PASCAL_HEADER
#define RAINBACK_PASCAL_HEADER

#include <QObject>
#include <QIODevice>

namespace rainback {
namespace protocol {

class Pascal : public QObject
{
    Q_OBJECT

    typedef quint32 packetsize;
    QIODevice* _io;

    packetsize lineSize;

public:
    Pascal();
    void listen(QIODevice* const io);
    void close();

public slots:
    void write(const QString& line);
    void flush();

signals:
    void lineRead(const QString& cmd);
};

} // namespace protocol
} // namespace rainback

#endif // RAINBACK_PASCAL_HEADER

// vim: set ts=4 sw=4 :
<commit_msg>Make Pascal's close() a slot<commit_after>#ifndef RAINBACK_PASCAL_HEADER
#define RAINBACK_PASCAL_HEADER

#include <QObject>
#include <QIODevice>

namespace rainback {
namespace protocol {

class Pascal : public QObject
{
    Q_OBJECT

    typedef quint32 packetsize;
    QIODevice* _io;

    packetsize lineSize;

public:
    Pascal();
    void listen(QIODevice* const io);

public slots:
    void write(const QString& line);
    void close();
    void flush();

signals:
    void lineRead(const QString& cmd);
};

} // namespace protocol
} // namespace rainback

#endif // RAINBACK_PASCAL_HEADER

// vim: set ts=4 sw=4 :
<|endoftext|>