<commit_before>/*
Copyright (c) 2015, Trail of Bits
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

  Redistributions of source code must retain the above copyright notice, this
  list 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 Trail of Bits 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "InstructionDispatch.h"
#include "toLLVM.h"
#include "X86.h"
#include "raiseX86.h"
#include "x86Helpers.h"
#include "x86Instrs_CMOV.h"
#include "RegisterUsage.h"

#define NASSERT(cond) TASSERT(cond, "")

using namespace llvm;

static Value *EQ(BasicBlock *b, MCSemaRegs f1, MCSemaRegs f2) {

    Value *l = F_READ(b, f1);
    Value *r = F_READ(b, f2);
    Value *is_eq = new ICmpInst(*b, CmpInst::ICMP_EQ, l, r);
    return is_eq;
}

static Value *NE(BasicBlock *b, MCSemaRegs f1, MCSemaRegs f2) {

    Value *l = F_READ(b, f1);
    Value *r = F_READ(b, f2);
    Value *is_ne = new ICmpInst(*b, CmpInst::ICMP_NE, l, r);
    return is_ne;
}

static Value *NOT(BasicBlock *b, MCSemaRegs flag) {

    Value *f = F_READ(b, flag);
    Value *not_f = BinaryOperator::CreateNot(f, "", b);
    return not_f;
}

static Value *AND(BasicBlock *b, Value *v1, Value *v2) {
   Value *andv = BinaryOperator::CreateAnd(v1, v2, "", b);
   return andv;
}

static Value *OR(BasicBlock *b, Value *v1, Value *v2) {
   Value *andv = BinaryOperator::CreateOr(v1, v2, "", b);
   return andv;
}

static Value *CHOOSE_IF(BasicBlock *b, Value *cmp, Value *trueval, Value *falseval) {
    Value *se = SelectInst::Create(cmp, trueval, falseval, "", b);
    return se;
}

template <int width>
static InstTransResult  doCMOV(
        BasicBlock *b,
        MCOperand &dst,
        Value *condition,
        Value *newval)
{
    Value *orig = R_READ<width>(b, dst.getReg());

    Value *to_write = CHOOSE_IF(b,
            condition,
            newval,
            orig);

    R_WRITE<width>(b, dst.getReg(), to_write);
    return ContinueBlock;
}

#define EMIT_CMOV_RM(width, condition) [] (NativeModulePtr natM, BasicBlock *&block, InstPtr ip, MCInst &inst)->InstTransResult {\
    BasicBlock *b = block;\
    if( ip->is_data_offset() ) {\
        return doCMOV<width>(block, OP(0), condition, M_READ<width>(ip, b, STD_GLOBAL_OP(2)));\
    }else {\
        return doCMOV<width>(block, OP(0), condition, M_READ<width>(ip, b, ADDR(2)));\
    }\
}

#define EMIT_CMOV_RR(width, condition) [] (NativeModulePtr natM, BasicBlock *&b, InstPtr ip, MCInst &inst)->InstTransResult {\
    return doCMOV<width>(b, OP(0), condition, R_READ<width>(b, OP(2).getReg())); \
}

#define EMIT_CMOV(which, condition) \
        m[which ## 16rm] = EMIT_CMOV_RM(16, condition);\
        m[which ## 16rr] = EMIT_CMOV_RR(16, condition);\
        m[which ## 32rm] = EMIT_CMOV_RM(32, condition);\
        m[which ## 32rr] = EMIT_CMOV_RR(32, condition);

void CMOV_populateDispatchMap(DispatchMap &m) {
        EMIT_CMOV(X86::CMOVA,   AND(b, NOT(b, CF), NOT(b, ZF)));
        EMIT_CMOV(X86::CMOVAE,  NOT(b, CF));
        EMIT_CMOV(X86::CMOVB,   F_READ(b, CF));
        EMIT_CMOV(X86::CMOVBE,  OR(b, F_READ(b, CF), F_READ(b, ZF)));
        EMIT_CMOV(X86::CMOVE,   F_READ(b, ZF));
        EMIT_CMOV(X86::CMOVG,   AND(b, NOT(b, ZF), EQ(b, SF, OF)));
        EMIT_CMOV(X86::CMOVGE,  EQ(b, SF, OF));
        EMIT_CMOV(X86::CMOVL,   NE(b, SF, OF));
        EMIT_CMOV(X86::CMOVLE,  OR(b, F_READ(b, ZF), NE(b, SF, OF)));
        EMIT_CMOV(X86::CMOVNE,  NOT(b, ZF));
        EMIT_CMOV(X86::CMOVNO,  NOT(b, OF));
        EMIT_CMOV(X86::CMOVNP,  NOT(b, PF));
        EMIT_CMOV(X86::CMOVNS,  NOT(b, SF));
        EMIT_CMOV(X86::CMOVO,   F_READ(b, OF));
        EMIT_CMOV(X86::CMOVP,   F_READ(b, PF));
        EMIT_CMOV(X86::CMOVS,   F_READ(b, SF));
}
<commit_msg>Support 64-bit cmov<commit_after>/*
Copyright (c) 2015, Trail of Bits
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

  Redistributions of source code must retain the above copyright notice, this
  list 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 Trail of Bits 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "InstructionDispatch.h"
#include "toLLVM.h"
#include "X86.h"
#include "raiseX86.h"
#include "x86Helpers.h"
#include "x86Instrs_CMOV.h"
#include "RegisterUsage.h"

#define NASSERT(cond) TASSERT(cond, "")

using namespace llvm;

static Value *EQ(BasicBlock *b, MCSemaRegs f1, MCSemaRegs f2) {

    Value *l = F_READ(b, f1);
    Value *r = F_READ(b, f2);
    Value *is_eq = new ICmpInst(*b, CmpInst::ICMP_EQ, l, r);
    return is_eq;
}

static Value *NE(BasicBlock *b, MCSemaRegs f1, MCSemaRegs f2) {

    Value *l = F_READ(b, f1);
    Value *r = F_READ(b, f2);
    Value *is_ne = new ICmpInst(*b, CmpInst::ICMP_NE, l, r);
    return is_ne;
}

static Value *NOT(BasicBlock *b, MCSemaRegs flag) {

    Value *f = F_READ(b, flag);
    Value *not_f = BinaryOperator::CreateNot(f, "", b);
    return not_f;
}

static Value *AND(BasicBlock *b, Value *v1, Value *v2) {
   Value *andv = BinaryOperator::CreateAnd(v1, v2, "", b);
   return andv;
}

static Value *OR(BasicBlock *b, Value *v1, Value *v2) {
   Value *andv = BinaryOperator::CreateOr(v1, v2, "", b);
   return andv;
}

static Value *CHOOSE_IF(BasicBlock *b, Value *cmp, Value *trueval, Value *falseval) {
    Value *se = SelectInst::Create(cmp, trueval, falseval, "", b);
    return se;
}

template <int width>
static InstTransResult  doCMOV(
        BasicBlock *b,
        MCOperand &dst,
        Value *condition,
        Value *newval)
{
    Value *orig = R_READ<width>(b, dst.getReg());

    Value *to_write = CHOOSE_IF(b,
            condition,
            newval,
            orig);

    R_WRITE<width>(b, dst.getReg(), to_write);
    return ContinueBlock;
}

#define EMIT_CMOV_RM(width, condition) [] (NativeModulePtr natM, BasicBlock *&block, InstPtr ip, MCInst &inst)->InstTransResult {\
    BasicBlock *b = block;\
    if( ip->is_data_offset() ) {\
        return doCMOV<width>(block, OP(0), condition, M_READ<width>(ip, b, STD_GLOBAL_OP(2)));\
    }else {\
        return doCMOV<width>(block, OP(0), condition, M_READ<width>(ip, b, ADDR(2)));\
    }\
}

#define EMIT_CMOV_RR(width, condition) [] (NativeModulePtr natM, BasicBlock *&b, InstPtr ip, MCInst &inst)->InstTransResult {\
    return doCMOV<width>(b, OP(0), condition, R_READ<width>(b, OP(2).getReg())); \
}

#define EMIT_CMOV(which, condition) \
        m[which ## 16rm] = EMIT_CMOV_RM(16, condition);\
        m[which ## 16rr] = EMIT_CMOV_RR(16, condition);\
        m[which ## 32rm] = EMIT_CMOV_RM(32, condition);\
        m[which ## 32rr] = EMIT_CMOV_RR(32, condition);\
        m[which ## 64rm] = EMIT_CMOV_RM(32, condition);\
        m[which ## 64rr] = EMIT_CMOV_RR(32, condition);

void CMOV_populateDispatchMap(DispatchMap &m) {
        EMIT_CMOV(X86::CMOVA,   AND(b, NOT(b, CF), NOT(b, ZF)));
        EMIT_CMOV(X86::CMOVAE,  NOT(b, CF));
        EMIT_CMOV(X86::CMOVB,   F_READ(b, CF));
        EMIT_CMOV(X86::CMOVBE,  OR(b, F_READ(b, CF), F_READ(b, ZF)));
        EMIT_CMOV(X86::CMOVE,   F_READ(b, ZF));
        EMIT_CMOV(X86::CMOVG,   AND(b, NOT(b, ZF), EQ(b, SF, OF)));
        EMIT_CMOV(X86::CMOVGE,  EQ(b, SF, OF));
        EMIT_CMOV(X86::CMOVL,   NE(b, SF, OF));
        EMIT_CMOV(X86::CMOVLE,  OR(b, F_READ(b, ZF), NE(b, SF, OF)));
        EMIT_CMOV(X86::CMOVNE,  NOT(b, ZF));
        EMIT_CMOV(X86::CMOVNO,  NOT(b, OF));
        EMIT_CMOV(X86::CMOVNP,  NOT(b, PF));
        EMIT_CMOV(X86::CMOVNS,  NOT(b, SF));
        EMIT_CMOV(X86::CMOVO,   F_READ(b, OF));
        EMIT_CMOV(X86::CMOVP,   F_READ(b, PF));
        EMIT_CMOV(X86::CMOVS,   F_READ(b, SF));
}
<|endoftext|>


<commit_before>#include "deferred_task.hpp"

namespace my
{
DeferredTask::DeferredTask(TDuration const & duration) : m_duration(duration)
{
  m_thread = thread([this]
  {
    unique_lock<mutex> l(m_mutex);
    while (!m_terminate)
    {
      if (!m_fn)
      {
        m_cv.wait(l);
        continue;
      }

      if (m_cv.wait_for(l, m_duration) != cv_status::timeout)
        continue;

      auto fn = move(m_fn);
      m_fn = nullptr;

      if (fn)
      {
        l.unlock();
        fn();
        l.lock();
      }
    }
  });
}

DeferredTask::~DeferredTask()
{
  {
    unique_lock<mutex> l(m_mutex);
    m_terminate = true;
  }
  m_cv.notify_one();
  m_thread.join();
}

void DeferredTask::Drop()
{
  {
    unique_lock<mutex> l(m_mutex);
    m_fn = nullptr;
  }
  m_cv.notify_one();
}
}  // namespace my
<commit_msg>Review fix<commit_after>#include "deferred_task.hpp"

namespace my
{
DeferredTask::DeferredTask(TDuration const & duration) : m_duration(duration)
{
  m_thread = thread([this]
  {
    unique_lock<mutex> l(m_mutex);
    while (!m_terminate)
    {
      if (!m_fn)
      {
        m_cv.wait(l);
        continue;
      }

      if (m_cv.wait_for(l, m_duration) != cv_status::timeout || !m_fn)
        continue;

      auto fn = move(m_fn);
      m_fn = nullptr;

      l.unlock();
      fn();
      l.lock();
    }
  });
}

DeferredTask::~DeferredTask()
{
  {
    unique_lock<mutex> l(m_mutex);
    m_terminate = true;
  }
  m_cv.notify_one();
  m_thread.join();
}

void DeferredTask::Drop()
{
  {
    unique_lock<mutex> l(m_mutex);
    m_fn = nullptr;
  }
  m_cv.notify_one();
}
}  // namespace my
<|endoftext|>


<commit_before>// Copyright 2015 The Enquery Authors.
//
// 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. See the AUTHORS file for names of
// contributors.

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "enquery/executive.h"
#include "enquery/status.h"
#include "enquery/testing.h"

using ::enquery::Executive;
using ::enquery::Future;
using ::enquery::Status;

int negate(int x) { return -x; }

int main(int argc, char* argv[]) {
  const int input_value = 42;

  Executive* executive = Executive::Create(NULL, true);

  Future<int> future_result;
  Status status = executive->Submit(negate, input_value, &future_result);
  ASSERT_TRUE(status.IsSuccess());
  ASSERT_EQUALS(future_result.GetValue(), negate(input_value));

  delete executive;

  return EXIT_SUCCESS;
}
<commit_msg>more work on executive's thread ppol<commit_after>// Copyright 2015 The Enquery Authors.
//
// 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. See the AUTHORS file for names of
// contributors.

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "enquery/execution.h"
#include "enquery/executive.h"
#include "enquery/status.h"
#include "enquery/testing.h"

using ::enquery::Execution;
using ::enquery::Executive;
using ::enquery::Future;
using ::enquery::Status;

namespace enquery {

// Execution implementation that always fails. The constructor accepts a
// a pointer-to-bool, which is set to 'false' on construction, and set to
// 'true' on destruction; this can be used by the test to determine the
// correct behavior of Executive's optional mechanism for taking ownership
// of the Execution instance that's passed during creation.
class Task;
class FailingExecution : public Execution {
 public:
  FailingExecution(bool* set_when_destroyed)
      : set_when_destroyed_(set_when_destroyed) {
    *set_when_destroyed_ = false;
  }

  virtual ~FailingExecution() { *set_when_destroyed_ = true; }

  virtual Status Execute(Task*) {
    return Status::MakeError("test", "failed to execute");
  }

 private:
  bool* set_when_destroyed_;
};

}  // namespace enquery

// Sample function for unit test (simply negates integer that's passed.)
int negate(int x) { return -x; }

void test_default_use() {
  const int input_value = 42;

  // Create an Executive with default options; pass NULL to use execute
  // everything on the curren thread. The boolean parameter indicates
  // that Executive should own the 'Execution' object, however when
  // NULL is passed, the current thread executive is used, and the
  // Executive *always* owns that.
  Executive* executive = Executive::Create(NULL, true);

  // Create an empty future, to be populated later via Submit()
  Future<int> future_result;
  ASSERT_FALSE(future_result.Valid());

  // Submit a task; in this case, we're making a call to the 'negate'
  // type, passing input_value as the argument; if successful,
  // 'future_result' is populated with a future that will eventually
  // hold the result of the calculation.
  Status status = executive->Submit(negate, input_value, &future_result);

  // We should succeed
  ASSERT_TRUE(status.IsSuccess());

  // We should get the correct answer
  ASSERT_EQUALS(future_result.GetValue(), negate(input_value));

  delete executive;
}

void test_failing_use_with_ownership() {
  const int input_value = 42;

  // First, create an execution method that always fails.
  bool destroyed = false;
  Execution* exm = new enquery::FailingExecution(&destroyed);

  // Create an executive that's configured to take ownership of
  // the execution method that's passed in.
  Executive* executive = Executive::Create(exm, true);

  // Create an empty future to hold the result.
  Future<int> future_result;
  ASSERT_FALSE(future_result.Valid());

  // Submit the task for execution, which should fail fail.
  Status status = executive->Submit(negate, input_value, &future_result);
  ASSERT_FALSE(status.IsSuccess());

  // Delete the executive.
  delete executive;

  // Assert that Execution owned by Executive was actually destroyed.
  ASSERT_TRUE(destroyed);
}

int main(int argc, char* argv[]) {
  test_default_use();
  test_failing_use_with_ownership();
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <algorithm>
#include <vector>
#include <gtest/gtest.h>

#include "test_api.h"

#include "common_types.h"
#include "rtp_rtcp.h"
#include "rtp_rtcp_defines.h"

using namespace webrtc;

const int kVideoNackListSize = 10;
const int kTestId = 123;
const WebRtc_UWord32 kTestSsrc = 3456;
const WebRtc_UWord16 kTestSequenceNumber = 2345;
const WebRtc_UWord32 kTestNumberOfPackets = 450;
const int kTestNumberOfRtxPackets = 49;

class VerifyingNackReceiver : public RtpData
{
 public:
  VerifyingNackReceiver() {}

  virtual WebRtc_Word32 OnReceivedPayloadData(
      const WebRtc_UWord8* data,
      const WebRtc_UWord16 size,
      const webrtc::WebRtcRTPHeader* rtp_header) {

    EXPECT_EQ(kTestSsrc, rtp_header->header.ssrc);
    EXPECT_EQ(find(sequence_numbers_.begin(),
                    sequence_numbers_.end(),
                    rtp_header->header.sequenceNumber),
              sequence_numbers_.end());
    sequence_numbers_.push_back(rtp_header->header.sequenceNumber);
    return 0;
  }
  std::vector<WebRtc_UWord16 > sequence_numbers_;
};

class NackLoopBackTransport : public webrtc::Transport {
 public:
  NackLoopBackTransport(RtpRtcp* rtp_rtcp_module, uint32_t rtx_ssrc)
    : count_(0),
      packet_loss_(0),
      rtx_ssrc_(rtx_ssrc),
      count_rtx_ssrc_(0),
      module_(rtp_rtcp_module) {
  }
  void DropEveryNthPacket(int n) {
    packet_loss_ = n;
  }
  virtual int SendPacket(int channel, const void *data, int len) {
    count_++;
    const unsigned char* ptr = static_cast<const unsigned  char*>(data);
    uint32_t ssrc = (ptr[8] << 24) + (ptr[9] << 16) + (ptr[10] << 8) + ptr[11];
    if (ssrc == rtx_ssrc_) count_rtx_ssrc_++;

    if (packet_loss_ > 0) {
      if ((count_ % packet_loss_) == 0) {
        return len;
      }
    }
    if (module_->IncomingPacket((const WebRtc_UWord8*)data, len) == 0) {
      return len;
    }
    return -1;
  }
  virtual int SendRTCPPacket(int channel, const void *data, int len) {
    if (module_->IncomingPacket((const WebRtc_UWord8*)data, len) == 0) {
      return len;
    }
    return -1;
  }
  int count_;
  int packet_loss_;
  uint32_t rtx_ssrc_;
  int count_rtx_ssrc_;
  RtpRtcp* module_;
};

class RtpRtcpNackTest : public ::testing::Test {
 protected:
  RtpRtcpNackTest() {}
  ~RtpRtcpNackTest() {}

  virtual void SetUp() {
    video_module_ = RtpRtcp::CreateRtpRtcp(kTestId, false, &fake_clock);
    EXPECT_EQ(0, video_module_->InitReceiver());
    EXPECT_EQ(0, video_module_->InitSender());
    EXPECT_EQ(0, video_module_->SetRTCPStatus(kRtcpCompound));
    EXPECT_EQ(0, video_module_->SetSSRC(kTestSsrc));
    EXPECT_EQ(0, video_module_->SetNACKStatus(kNackRtcp));
    EXPECT_EQ(0, video_module_->SetStorePacketsStatus(true));
    EXPECT_EQ(0, video_module_->SetSendingStatus(true));
    EXPECT_EQ(0, video_module_->SetSequenceNumber(kTestSequenceNumber));
    EXPECT_EQ(0, video_module_->SetStartTimestamp(111111));

    transport_ = new NackLoopBackTransport(video_module_, kTestSsrc + 1);
    EXPECT_EQ(0, video_module_->RegisterSendTransport(transport_));

    nack_receiver_ = new VerifyingNackReceiver();
    EXPECT_EQ(0, video_module_->RegisterIncomingDataCallback(nack_receiver_));

    VideoCodec video_codec;
    memset(&video_codec, 0, sizeof(video_codec));
    video_codec.plType = 123;
    memcpy(video_codec.plName, "I420", 5);

    EXPECT_EQ(0, video_module_->RegisterSendPayload(video_codec));
    EXPECT_EQ(0, video_module_->RegisterReceivePayload(video_codec));

    payload_data_length = sizeof(payload_data);

    for (int n = 0; n < payload_data_length; n++) {
      payload_data[n] = n % 10;
    }
  }

  virtual void TearDown() {
    RtpRtcp::DestroyRtpRtcp(video_module_);
    delete transport_;
    delete nack_receiver_;
  }

  RtpRtcp* video_module_;
  NackLoopBackTransport* transport_;
  VerifyingNackReceiver* nack_receiver_;
  WebRtc_UWord8  payload_data[65000];
  int payload_data_length;
  FakeRtpRtcpClock fake_clock;
};

TEST_F(RtpRtcpNackTest, RTCP) {
  WebRtc_UWord32 timestamp = 3000;
  WebRtc_UWord16 nack_list[kVideoNackListSize];
  transport_->DropEveryNthPacket(10);

  for (int frame = 0; frame < 10; ++frame) {
    EXPECT_EQ(0, video_module_->SendOutgoingData(webrtc::kVideoFrameDelta, 123,
                                                timestamp,
                                                payload_data,
                                                payload_data_length));

    std::sort(nack_receiver_->sequence_numbers_.begin(),
              nack_receiver_->sequence_numbers_.end());

    std::vector<WebRtc_UWord16> missing_sequence_numbers;
    std::vector<WebRtc_UWord16>::iterator it =
        nack_receiver_->sequence_numbers_.begin();

    while (it != nack_receiver_->sequence_numbers_.end()) {
      WebRtc_UWord16 sequence_number_1 = *it;
      ++it;
      if (it != nack_receiver_->sequence_numbers_.end()) {
        WebRtc_UWord16 sequence_number_2 = *it;
        // Add all missing sequence numbers to list
        for (WebRtc_UWord16 i = sequence_number_1 + 1; i < sequence_number_2;
            ++i) {
          missing_sequence_numbers.push_back(i);
        }
      }
    }
    int n = 0;
    for (it = missing_sequence_numbers.begin();
        it != missing_sequence_numbers.end(); ++it) {
      nack_list[n++] = (*it);
    }
    video_module_->SendNACK(nack_list, n);
    fake_clock.IncrementTime(33);
    video_module_->Process();

    // Prepare next frame.
    timestamp += 3000;
  }
  std::sort(nack_receiver_->sequence_numbers_.begin(),
            nack_receiver_->sequence_numbers_.end());
  EXPECT_EQ(kTestSequenceNumber, *(nack_receiver_->sequence_numbers_.begin()));
  EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
            *(nack_receiver_->sequence_numbers_.rbegin()));
  EXPECT_EQ(kTestNumberOfPackets, nack_receiver_->sequence_numbers_.size());
  EXPECT_EQ(0, transport_->count_rtx_ssrc_);
}

TEST_F(RtpRtcpNackTest, RTX) {
  EXPECT_EQ(0, video_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
  EXPECT_EQ(0, video_module_->SetRTXSendStatus(true, true, kTestSsrc + 1));

  transport_->DropEveryNthPacket(10);

  WebRtc_UWord32 timestamp = 3000;
  WebRtc_UWord16 nack_list[kVideoNackListSize];

  for (int frame = 0; frame < 10; ++frame) {
    EXPECT_EQ(0, video_module_->SendOutgoingData(webrtc::kVideoFrameDelta, 123,
                                               timestamp,
                                               payload_data,
                                               payload_data_length));

    std::sort(nack_receiver_->sequence_numbers_.begin(),
              nack_receiver_->sequence_numbers_.end());

    std::vector<WebRtc_UWord16> missing_sequence_numbers;

    std::vector<WebRtc_UWord16>::iterator it =
        nack_receiver_->sequence_numbers_.begin();
    while (it != nack_receiver_->sequence_numbers_.end()) {
      int sequence_number_1 = *it;
      ++it;
      if (it != nack_receiver_->sequence_numbers_.end()) {
        int sequence_number_2 = *it;
        // Add all missing sequence numbers to list.
        for (int i = sequence_number_1 + 1; i < sequence_number_2; ++i) {
          missing_sequence_numbers.push_back(i);
        }
      }
    }
    int n = 0;
    for (it = missing_sequence_numbers.begin();
        it != missing_sequence_numbers.end(); ++it) {
      nack_list[n++] = (*it);
    }
    video_module_->SendNACK(nack_list, n);
    fake_clock.IncrementTime(33);
    video_module_->Process();

    // Prepare next frame.
    timestamp += 3000;
  }
  std::sort(nack_receiver_->sequence_numbers_.begin(),
            nack_receiver_->sequence_numbers_.end());
  EXPECT_EQ(kTestSequenceNumber, *(nack_receiver_->sequence_numbers_.begin()));
  EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
            *(nack_receiver_->sequence_numbers_.rbegin()));
  EXPECT_EQ(kTestNumberOfPackets, nack_receiver_->sequence_numbers_.size());
  EXPECT_EQ(kTestNumberOfRtxPackets, transport_->count_rtx_ssrc_);
}

<commit_msg>Fix compilation error on android Review URL: https://webrtc-codereview.appspot.com/426006<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <algorithm>
#include <vector>
#include <gtest/gtest.h>

#include "test_api.h"

#include "common_types.h"
#include "rtp_rtcp.h"
#include "rtp_rtcp_defines.h"

using namespace webrtc;

const int kVideoNackListSize = 10;
const int kTestId = 123;
const WebRtc_UWord32 kTestSsrc = 3456;
const WebRtc_UWord16 kTestSequenceNumber = 2345;
const WebRtc_UWord32 kTestNumberOfPackets = 450;
const int kTestNumberOfRtxPackets = 49;

class VerifyingNackReceiver : public RtpData
{
 public:
  VerifyingNackReceiver() {}

  virtual WebRtc_Word32 OnReceivedPayloadData(
      const WebRtc_UWord8* data,
      const WebRtc_UWord16 size,
      const webrtc::WebRtcRTPHeader* rtp_header) {

    EXPECT_EQ(kTestSsrc, rtp_header->header.ssrc);
    EXPECT_EQ(std::find(sequence_numbers_.begin(),
                    sequence_numbers_.end(),
                    rtp_header->header.sequenceNumber),
              sequence_numbers_.end());
    sequence_numbers_.push_back(rtp_header->header.sequenceNumber);
    return 0;
  }
  std::vector<WebRtc_UWord16 > sequence_numbers_;
};

class NackLoopBackTransport : public webrtc::Transport {
 public:
  NackLoopBackTransport(RtpRtcp* rtp_rtcp_module, uint32_t rtx_ssrc)
    : count_(0),
      packet_loss_(0),
      rtx_ssrc_(rtx_ssrc),
      count_rtx_ssrc_(0),
      module_(rtp_rtcp_module) {
  }
  void DropEveryNthPacket(int n) {
    packet_loss_ = n;
  }
  virtual int SendPacket(int channel, const void *data, int len) {
    count_++;
    const unsigned char* ptr = static_cast<const unsigned  char*>(data);
    uint32_t ssrc = (ptr[8] << 24) + (ptr[9] << 16) + (ptr[10] << 8) + ptr[11];
    if (ssrc == rtx_ssrc_) count_rtx_ssrc_++;

    if (packet_loss_ > 0) {
      if ((count_ % packet_loss_) == 0) {
        return len;
      }
    }
    if (module_->IncomingPacket((const WebRtc_UWord8*)data, len) == 0) {
      return len;
    }
    return -1;
  }
  virtual int SendRTCPPacket(int channel, const void *data, int len) {
    if (module_->IncomingPacket((const WebRtc_UWord8*)data, len) == 0) {
      return len;
    }
    return -1;
  }
  int count_;
  int packet_loss_;
  uint32_t rtx_ssrc_;
  int count_rtx_ssrc_;
  RtpRtcp* module_;
};

class RtpRtcpNackTest : public ::testing::Test {
 protected:
  RtpRtcpNackTest() {}
  ~RtpRtcpNackTest() {}

  virtual void SetUp() {
    video_module_ = RtpRtcp::CreateRtpRtcp(kTestId, false, &fake_clock);
    EXPECT_EQ(0, video_module_->InitReceiver());
    EXPECT_EQ(0, video_module_->InitSender());
    EXPECT_EQ(0, video_module_->SetRTCPStatus(kRtcpCompound));
    EXPECT_EQ(0, video_module_->SetSSRC(kTestSsrc));
    EXPECT_EQ(0, video_module_->SetNACKStatus(kNackRtcp));
    EXPECT_EQ(0, video_module_->SetStorePacketsStatus(true));
    EXPECT_EQ(0, video_module_->SetSendingStatus(true));
    EXPECT_EQ(0, video_module_->SetSequenceNumber(kTestSequenceNumber));
    EXPECT_EQ(0, video_module_->SetStartTimestamp(111111));

    transport_ = new NackLoopBackTransport(video_module_, kTestSsrc + 1);
    EXPECT_EQ(0, video_module_->RegisterSendTransport(transport_));

    nack_receiver_ = new VerifyingNackReceiver();
    EXPECT_EQ(0, video_module_->RegisterIncomingDataCallback(nack_receiver_));

    VideoCodec video_codec;
    memset(&video_codec, 0, sizeof(video_codec));
    video_codec.plType = 123;
    memcpy(video_codec.plName, "I420", 5);

    EXPECT_EQ(0, video_module_->RegisterSendPayload(video_codec));
    EXPECT_EQ(0, video_module_->RegisterReceivePayload(video_codec));

    payload_data_length = sizeof(payload_data);

    for (int n = 0; n < payload_data_length; n++) {
      payload_data[n] = n % 10;
    }
  }

  virtual void TearDown() {
    RtpRtcp::DestroyRtpRtcp(video_module_);
    delete transport_;
    delete nack_receiver_;
  }

  RtpRtcp* video_module_;
  NackLoopBackTransport* transport_;
  VerifyingNackReceiver* nack_receiver_;
  WebRtc_UWord8  payload_data[65000];
  int payload_data_length;
  FakeRtpRtcpClock fake_clock;
};

TEST_F(RtpRtcpNackTest, RTCP) {
  WebRtc_UWord32 timestamp = 3000;
  WebRtc_UWord16 nack_list[kVideoNackListSize];
  transport_->DropEveryNthPacket(10);

  for (int frame = 0; frame < 10; ++frame) {
    EXPECT_EQ(0, video_module_->SendOutgoingData(webrtc::kVideoFrameDelta, 123,
                                                timestamp,
                                                payload_data,
                                                payload_data_length));

    std::sort(nack_receiver_->sequence_numbers_.begin(),
              nack_receiver_->sequence_numbers_.end());

    std::vector<WebRtc_UWord16> missing_sequence_numbers;
    std::vector<WebRtc_UWord16>::iterator it =
        nack_receiver_->sequence_numbers_.begin();

    while (it != nack_receiver_->sequence_numbers_.end()) {
      WebRtc_UWord16 sequence_number_1 = *it;
      ++it;
      if (it != nack_receiver_->sequence_numbers_.end()) {
        WebRtc_UWord16 sequence_number_2 = *it;
        // Add all missing sequence numbers to list
        for (WebRtc_UWord16 i = sequence_number_1 + 1; i < sequence_number_2;
            ++i) {
          missing_sequence_numbers.push_back(i);
        }
      }
    }
    int n = 0;
    for (it = missing_sequence_numbers.begin();
        it != missing_sequence_numbers.end(); ++it) {
      nack_list[n++] = (*it);
    }
    video_module_->SendNACK(nack_list, n);
    fake_clock.IncrementTime(33);
    video_module_->Process();

    // Prepare next frame.
    timestamp += 3000;
  }
  std::sort(nack_receiver_->sequence_numbers_.begin(),
            nack_receiver_->sequence_numbers_.end());
  EXPECT_EQ(kTestSequenceNumber, *(nack_receiver_->sequence_numbers_.begin()));
  EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
            *(nack_receiver_->sequence_numbers_.rbegin()));
  EXPECT_EQ(kTestNumberOfPackets, nack_receiver_->sequence_numbers_.size());
  EXPECT_EQ(0, transport_->count_rtx_ssrc_);
}

TEST_F(RtpRtcpNackTest, RTX) {
  EXPECT_EQ(0, video_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
  EXPECT_EQ(0, video_module_->SetRTXSendStatus(true, true, kTestSsrc + 1));

  transport_->DropEveryNthPacket(10);

  WebRtc_UWord32 timestamp = 3000;
  WebRtc_UWord16 nack_list[kVideoNackListSize];

  for (int frame = 0; frame < 10; ++frame) {
    EXPECT_EQ(0, video_module_->SendOutgoingData(webrtc::kVideoFrameDelta, 123,
                                               timestamp,
                                               payload_data,
                                               payload_data_length));

    std::sort(nack_receiver_->sequence_numbers_.begin(),
              nack_receiver_->sequence_numbers_.end());

    std::vector<WebRtc_UWord16> missing_sequence_numbers;

    std::vector<WebRtc_UWord16>::iterator it =
        nack_receiver_->sequence_numbers_.begin();
    while (it != nack_receiver_->sequence_numbers_.end()) {
      int sequence_number_1 = *it;
      ++it;
      if (it != nack_receiver_->sequence_numbers_.end()) {
        int sequence_number_2 = *it;
        // Add all missing sequence numbers to list.
        for (int i = sequence_number_1 + 1; i < sequence_number_2; ++i) {
          missing_sequence_numbers.push_back(i);
        }
      }
    }
    int n = 0;
    for (it = missing_sequence_numbers.begin();
        it != missing_sequence_numbers.end(); ++it) {
      nack_list[n++] = (*it);
    }
    video_module_->SendNACK(nack_list, n);
    fake_clock.IncrementTime(33);
    video_module_->Process();

    // Prepare next frame.
    timestamp += 3000;
  }
  std::sort(nack_receiver_->sequence_numbers_.begin(),
            nack_receiver_->sequence_numbers_.end());
  EXPECT_EQ(kTestSequenceNumber, *(nack_receiver_->sequence_numbers_.begin()));
  EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
            *(nack_receiver_->sequence_numbers_.rbegin()));
  EXPECT_EQ(kTestNumberOfPackets, nack_receiver_->sequence_numbers_.size());
  EXPECT_EQ(kTestNumberOfRtxPackets, transport_->count_rtx_ssrc_);
}
<|endoftext|>


<commit_before>//  Copyright 2011 Google Inc.
//
//  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.

// Author: morlovich@google.com (Maksim Orlovich)

// Test the pollable async -> sync fetcher adapter and its callback helper

#include "net/instaweb/http/public/sync_fetcher_adapter.h"

#include <algorithm>

#include "base/basictypes.h"
#include "net/instaweb/http/public/request_headers.h"
#include "net/instaweb/http/public/response_headers.h"
#include "net/instaweb/util/public/google_url.h"
#include "net/instaweb/util/public/gtest.h"
#include "net/instaweb/util/public/mock_message_handler.h"
#include "net/instaweb/util/public/mock_timer.h"
#include "net/instaweb/util/public/string_writer.h"
#include "net/instaweb/util/public/writer.h"

namespace net_instaweb {

namespace {

const char kText[] = "Result";
const char kHeader[] = "X-Test-HeaderCopy";

// Writer that should never be invoked.
class TrapWriter : public Writer {
 public:
  TrapWriter() {}

  virtual bool Write(const StringPiece& str, MessageHandler* message_handler) {
    ADD_FAILURE() << "Should not do a Write";
    return false;
  }

  virtual bool Flush(MessageHandler* message_handler) {
    ADD_FAILURE() << "Should not do a Flush";
    return false;
  }
 private:
  DISALLOW_COPY_AND_ASSIGN(TrapWriter);
};

// A pollable fetcher that writes out a response at given number of microseconds
// elapsed, or when asked to immediately. Note that it's only capable of one
// fetch at a time!
class DelayedFetcher : public UrlPollableAsyncFetcher {
 public:
  // Note: if sim_delay <= 0, will report immediately at StreamingFetch
  DelayedFetcher(Timer* timer, MessageHandler* handler,
                 int64 sim_delay_ms, bool sim_success)
      : timer_(timer), handler_(handler), sim_delay_(sim_delay_ms*1000),
        sim_success_(sim_success) {
    CleanFetchSettings();
  }

  virtual bool StreamingFetch(const std::string& url,
                              const RequestHeaders& request_headers,
                              ResponseHeaders* response_headers,
                              Writer* response_writer,
                              MessageHandler* message_handler,
                              Callback* callback) {
    CHECK(!fetch_pending_);
    response_headers_ = response_headers;
    response_writer_ = response_writer;
    callback_ = callback;
    remaining_us_ = sim_delay_;
    fetch_pending_ = true;

    if (remaining_us_ <= 0) {
      ReportResult();
      return true;
    } else {
      return false;
    }
  }

  virtual int Poll(int64 microseconds) {
    if (fetch_pending_) {
      int64 delay = std::min(microseconds, remaining_us_);
      timer_->SleepUs(delay);
      remaining_us_ -= delay;

      if (remaining_us_ <= 0) {
        ReportResult();
      }
    }

    return fetch_pending_ ? 1 : 0;
  }

 private:
  void CleanFetchSettings() {
    fetch_pending_ = false;

    // Defensively set active fetch variables to catch us doing something silly.
    response_headers_ = NULL;
    response_writer_ = NULL;
    callback_ = NULL;
    remaining_us_ = 0;
  }

  void ReportResult() {
    ResponseHeaders headers;
    if (sim_success_) {
      response_headers_->CopyFrom(headers);
      response_headers_->Add(kHeader, kText);
      response_writer_->Write(kText, handler_);
      response_writer_->Flush(handler_);
    }
    callback_->Done(sim_success_);
    CleanFetchSettings();
  }

  // Simulation settings:
  Timer* timer_;
  MessageHandler* handler_;
  int64 sim_delay_;  // how long till we report the result
  bool sim_success_;  // whether to report success or failure

  // Fetch session:
  bool fetch_pending_;
  ResponseHeaders* response_headers_;
  Writer* response_writer_;
  Callback* callback_;  // callback for current fetch
  int64 remaining_us_;  // how much time left to report result of current fetch
};

}  // namespace

class SyncFetcherAdapterTest : public testing::Test {
 public:
  SyncFetcherAdapterTest(): timer_(0) {}

 protected:
  bool DoFetch(UrlFetcher* fetcher, ResponseHeaders* response_headers,
               Writer* response_writer) {
    return fetcher->StreamingFetchUrl("http://www.example.com/",
                                      RequestHeaders(),
                                      response_headers,
                                      response_writer,
                                      &handler_);
  }

  void TestSuccessfulFetch(UrlFetcher* fetcher) {
    ResponseHeaders out_headers;
    std::string out_str;
    StringWriter out_writer(&out_str);
    EXPECT_TRUE(DoFetch(fetcher, &out_headers, &out_writer));
    EXPECT_EQ(kText, out_str);

    CharStarVector values;
    EXPECT_TRUE(out_headers.Lookup(kHeader, &values));
    ASSERT_EQ(1, values.size());
    EXPECT_EQ(std::string(kText), values[0]);
  }

  void TestFailedFetch(UrlFetcher* fetcher) {
    ResponseHeaders out_headers;
    TrapWriter trap_writer;
    EXPECT_FALSE(DoFetch(fetcher, &out_headers, &trap_writer));
  }

  void TestTimeoutFetch(UrlPollableAsyncFetcher* async_fetcher,
                        UrlFetcher* fetcher) {
    // First let the sync fetcher tineout, and return failure.
    TestFailedFetch(fetcher);

    // Now spin until async fetcher delivers the result, to make sure
    // we do not blow up
    while (async_fetcher->Poll(1000) != 0) {}
  }

  MockMessageHandler handler_;
  MockTimer timer_;
};

TEST_F(SyncFetcherAdapterTest, QuickOk) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 0, true);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestSuccessfulFetch(&sync_fetcher);
}

TEST_F(SyncFetcherAdapterTest, SlowOk) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 500, true);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestSuccessfulFetch(&sync_fetcher);
}

TEST_F(SyncFetcherAdapterTest, QuickFail) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 0, false);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestFailedFetch(&sync_fetcher);
}

TEST_F(SyncFetcherAdapterTest, SlowFail) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 500, false);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestFailedFetch(&sync_fetcher);
}

TEST_F(SyncFetcherAdapterTest, TimeoutOk) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 5000, true);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestTimeoutFetch(&async_fetcher, &sync_fetcher);
}

TEST_F(SyncFetcherAdapterTest, TimeoutFail) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 5000, false);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestTimeoutFetch(&async_fetcher, &sync_fetcher);
}

}  // namespace net_instaweb
<commit_msg>Compilation fix for some gcc versions.<commit_after>//  Copyright 2011 Google Inc.
//
//  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.

// Author: morlovich@google.com (Maksim Orlovich)

// Test the pollable async -> sync fetcher adapter and its callback helper

#include "net/instaweb/http/public/sync_fetcher_adapter.h"

#include <algorithm>

#include "base/basictypes.h"
#include "net/instaweb/http/public/request_headers.h"
#include "net/instaweb/http/public/response_headers.h"
#include "net/instaweb/util/public/google_url.h"
#include "net/instaweb/util/public/gtest.h"
#include "net/instaweb/util/public/mock_message_handler.h"
#include "net/instaweb/util/public/mock_timer.h"
#include "net/instaweb/util/public/string_writer.h"
#include "net/instaweb/util/public/writer.h"

namespace net_instaweb {

namespace {

const char kText[] = "Result";
const char kHeader[] = "X-Test-HeaderCopy";

// Writer that should never be invoked.
class TrapWriter : public Writer {
 public:
  TrapWriter() {}

  virtual bool Write(const StringPiece& str, MessageHandler* message_handler) {
    ADD_FAILURE() << "Should not do a Write";
    return false;
  }

  virtual bool Flush(MessageHandler* message_handler) {
    ADD_FAILURE() << "Should not do a Flush";
    return false;
  }
 private:
  DISALLOW_COPY_AND_ASSIGN(TrapWriter);
};

// A pollable fetcher that writes out a response at given number of microseconds
// elapsed, or when asked to immediately. Note that it's only capable of one
// fetch at a time!
class DelayedFetcher : public UrlPollableAsyncFetcher {
 public:
  // Note: if sim_delay <= 0, will report immediately at StreamingFetch
  DelayedFetcher(Timer* timer, MessageHandler* handler,
                 int64 sim_delay_ms, bool sim_success)
      : timer_(timer), handler_(handler), sim_delay_(sim_delay_ms*1000),
        sim_success_(sim_success) {
    CleanFetchSettings();
  }

  virtual bool StreamingFetch(const std::string& url,
                              const RequestHeaders& request_headers,
                              ResponseHeaders* response_headers,
                              Writer* response_writer,
                              MessageHandler* message_handler,
                              Callback* callback) {
    CHECK(!fetch_pending_);
    response_headers_ = response_headers;
    response_writer_ = response_writer;
    callback_ = callback;
    remaining_us_ = sim_delay_;
    fetch_pending_ = true;

    if (remaining_us_ <= 0) {
      ReportResult();
      return true;
    } else {
      return false;
    }
  }

  virtual int Poll(int64 microseconds) {
    if (fetch_pending_) {
      int64 delay = std::min(microseconds, remaining_us_);
      timer_->SleepUs(delay);
      remaining_us_ -= delay;

      if (remaining_us_ <= 0) {
        ReportResult();
      }
    }

    return fetch_pending_ ? 1 : 0;
  }

 private:
  void CleanFetchSettings() {
    fetch_pending_ = false;

    // Defensively set active fetch variables to catch us doing something silly.
    response_headers_ = NULL;
    response_writer_ = NULL;
    callback_ = NULL;
    remaining_us_ = 0;
  }

  void ReportResult() {
    ResponseHeaders headers;
    if (sim_success_) {
      response_headers_->CopyFrom(headers);
      response_headers_->Add(kHeader, kText);
      response_writer_->Write(kText, handler_);
      response_writer_->Flush(handler_);
    }
    callback_->Done(sim_success_);
    CleanFetchSettings();
  }

  // Simulation settings:
  Timer* timer_;
  MessageHandler* handler_;
  int64 sim_delay_;  // how long till we report the result
  bool sim_success_;  // whether to report success or failure

  // Fetch session:
  bool fetch_pending_;
  ResponseHeaders* response_headers_;
  Writer* response_writer_;
  Callback* callback_;  // callback for current fetch
  int64 remaining_us_;  // how much time left to report result of current fetch
};

}  // namespace

class SyncFetcherAdapterTest : public testing::Test {
 public:
  SyncFetcherAdapterTest(): timer_(0) {}

 protected:
  bool DoFetch(UrlFetcher* fetcher, ResponseHeaders* response_headers,
               Writer* response_writer) {
    RequestHeaders request_headers;
    return fetcher->StreamingFetchUrl("http://www.example.com/",
                                      request_headers,
                                      response_headers,
                                      response_writer,
                                      &handler_);
  }

  void TestSuccessfulFetch(UrlFetcher* fetcher) {
    ResponseHeaders out_headers;
    std::string out_str;
    StringWriter out_writer(&out_str);
    EXPECT_TRUE(DoFetch(fetcher, &out_headers, &out_writer));
    EXPECT_EQ(kText, out_str);

    CharStarVector values;
    EXPECT_TRUE(out_headers.Lookup(kHeader, &values));
    ASSERT_EQ(1, values.size());
    EXPECT_EQ(std::string(kText), values[0]);
  }

  void TestFailedFetch(UrlFetcher* fetcher) {
    ResponseHeaders out_headers;
    TrapWriter trap_writer;
    EXPECT_FALSE(DoFetch(fetcher, &out_headers, &trap_writer));
  }

  void TestTimeoutFetch(UrlPollableAsyncFetcher* async_fetcher,
                        UrlFetcher* fetcher) {
    // First let the sync fetcher tineout, and return failure.
    TestFailedFetch(fetcher);

    // Now spin until async fetcher delivers the result, to make sure
    // we do not blow up
    while (async_fetcher->Poll(1000) != 0) {}
  }

  MockMessageHandler handler_;
  MockTimer timer_;
};

TEST_F(SyncFetcherAdapterTest, QuickOk) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 0, true);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestSuccessfulFetch(&sync_fetcher);
}

TEST_F(SyncFetcherAdapterTest, SlowOk) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 500, true);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestSuccessfulFetch(&sync_fetcher);
}

TEST_F(SyncFetcherAdapterTest, QuickFail) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 0, false);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestFailedFetch(&sync_fetcher);
}

TEST_F(SyncFetcherAdapterTest, SlowFail) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 500, false);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestFailedFetch(&sync_fetcher);
}

TEST_F(SyncFetcherAdapterTest, TimeoutOk) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 5000, true);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestTimeoutFetch(&async_fetcher, &sync_fetcher);
}

TEST_F(SyncFetcherAdapterTest, TimeoutFail) {
  DelayedFetcher async_fetcher(&timer_, &handler_, 5000, false);
  SyncFetcherAdapter sync_fetcher(&timer_, 1000, &async_fetcher);
  TestTimeoutFetch(&async_fetcher, &sync_fetcher);
}

}  // namespace net_instaweb
<|endoftext|>


<commit_before>#include <osgDB/FileNameUtils>
#include <osgDB/Registry>

#include "ESRIShape.h"
#include "ESRIShapeParser.h"

class ESRIShapeReaderWriter : public osgDB::ReaderWriter
{
    public:
        ESRIShapeReaderWriter() {}

        virtual const char* className() { return "ESRI Shape ReaderWriter"; }

        virtual bool acceptsExtension(const std::string& extension) const
        {
            return osgDB::equalCaseInsensitive(extension,"shp");
        }

        virtual ReadResult readObject(const std::string& fileName, const Options* opt) const
        { return readNode(fileName,opt); }

        virtual ReadResult readNode(const std::string& fileName, const Options* ) const
        {
            std::string ext = osgDB::getFileExtension(fileName);
            if (!acceptsExtension(ext))
                return ReadResult::FILE_NOT_HANDLED;

            ESRIShape::ESRIShapeParser sp(fileName);
            return sp.getGeode();
        }

    private:
};

osgDB::RegisterReaderWriterProxy<ESRIShapeReaderWriter> g_esriShapeReaderWriter_Proxy;

<commit_msg>Added file search path to ESRI reader.<commit_after>#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/Registry>

#include "ESRIShape.h"
#include "ESRIShapeParser.h"

class ESRIShapeReaderWriter : public osgDB::ReaderWriter
{
    public:
        ESRIShapeReaderWriter() {}

        virtual const char* className() { return "ESRI Shape ReaderWriter"; }

        virtual bool acceptsExtension(const std::string& extension) const
        {
            return osgDB::equalCaseInsensitive(extension,"shp");
        }

        virtual ReadResult readObject(const std::string& fileName, const Options* opt) const
        { return readNode(fileName,opt); }

        virtual ReadResult readNode(const std::string& file, const Options* options) const
        {
            std::string ext = osgDB::getFileExtension(file);
            if (!acceptsExtension(ext))
                return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile(file, options);
            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

            ESRIShape::ESRIShapeParser sp(fileName);
            return sp.getGeode();
        }

    private:
};

osgDB::RegisterReaderWriterProxy<ESRIShapeReaderWriter> g_esriShapeReaderWriter_Proxy;

<|endoftext|>


<commit_before>#include "../../SDP_Solver.hxx"

// dualResidues[p] = primalObjective[p] - Tr(A_p Y) - (FreeVarMatrix y)_p,
// for 0 <= p < primalObjective.size()
//
// The pairings Tr(A_p Y) can be written in terms of BilinearPairingsY:
//
//   Tr(A_(j,r,s,k) Y) = \sum_{b \in blocks[j]}
//                       (1/2) (BilinearPairingsY_{ej r + k, ej s + k} +
//                              swap (r <-> s))
// where ej = d_j + 1.
//
// Inputs: sdp, y, BilinearPairingsY
// Output: dualResidues (overwriten)
//
void compute_dual_residues(const Block_Info &block_info, const SDP &sdp,
                           const Block_Vector &y,
                           const Block_Diagonal_Matrix &bilinear_pairings_Y,
                           Block_Vector &dual_residues)
{
  auto dual_residues_block(dual_residues.blocks.begin());
  auto primal_objective_c_block(sdp.primal_objective_c.blocks.begin());
  auto y_block(y.blocks.begin());
  auto free_var_matrix_block(sdp.free_var_matrix.blocks.begin());
  auto bilinear_pairings_Y_block(bilinear_pairings_Y.blocks.begin());
  // dualResidues[p] = -Tr(A_p Y)
  for(auto &block_index : block_info.block_indices)
    {
      Zero(*dual_residues_block);
      const size_t block_size(block_info.degrees[block_index] + 1);

      // Not sure whether it is better to first loop over blocks in
      // the result or over sub-blocks in bilinear_pairings_Y
      for(size_t bb = 2 * block_index; bb < 2 * block_index + 2; ++bb)
        {
          for(size_t column_block = 0;
              column_block < block_info.dimensions[block_index];
              ++column_block)
            for(size_t row_block = 0; row_block <= column_block; ++row_block)
              {
                size_t column_offset(column_block * block_size),
                  row_offset(row_block * block_size);

                El::DistMatrix<El::BigFloat> lower_diagonal(El::GetDiagonal(
                  El::LockedView(*bilinear_pairings_Y_block, row_offset,
                                 column_offset, block_size, block_size))),
                  upper_diagonal(El::GetDiagonal(
                    El::LockedView(*bilinear_pairings_Y_block, column_offset,
                                   row_offset, block_size, block_size)));

                size_t residue_row_offset(
                  ((column_block * (column_block + 1)) / 2 + row_block)
                  * block_size);

                El::DistMatrix<El::BigFloat> residue_sub_block(El::View(
                  *dual_residues_block, residue_row_offset, 0, block_size, 1));

                // FIXME: This does twice as much work as needed when
                // column_block==row_block.
                El::Axpy(El::BigFloat(-0.5), lower_diagonal,
                         residue_sub_block);
                El::Axpy(El::BigFloat(-0.5), upper_diagonal,
                         residue_sub_block);
              }
          ++bilinear_pairings_Y_block;
        }
      // dualResidues -= FreeVarMatrix * y
      Gemm(El::Orientation::NORMAL, El::Orientation::NORMAL, El::BigFloat(-1),
           *free_var_matrix_block, *y_block, El::BigFloat(1),
           *dual_residues_block);
      // dualResidues += primalObjective
      Axpy(El::BigFloat(1), *primal_objective_c_block, *dual_residues_block);

      ++primal_objective_c_block;
      ++y_block;
      ++free_var_matrix_block;
      ++dual_residues_block;
    }
}
<commit_msg>Optimize compute_dual_residues a little<commit_after>#include "../../SDP_Solver.hxx"

// dualResidues[p] = primalObjective[p] - Tr(A_p Y) - (FreeVarMatrix y)_p,
// for 0 <= p < primalObjective.size()
//
// The pairings Tr(A_p Y) can be written in terms of BilinearPairingsY:
//
//   Tr(A_(j,r,s,k) Y) = \sum_{b \in blocks[j]}
//                       (1/2) (BilinearPairingsY_{ej r + k, ej s + k} +
//                              swap (r <-> s))
// where ej = d_j + 1.
//
// Inputs: sdp, y, BilinearPairingsY
// Output: dualResidues (overwriten)
//
void compute_dual_residues(const Block_Info &block_info, const SDP &sdp,
                           const Block_Vector &y,
                           const Block_Diagonal_Matrix &bilinear_pairings_Y,
                           Block_Vector &dual_residues)
{
  auto dual_residues_block(dual_residues.blocks.begin());
  auto primal_objective_c_block(sdp.primal_objective_c.blocks.begin());
  auto y_block(y.blocks.begin());
  auto free_var_matrix_block(sdp.free_var_matrix.blocks.begin());
  auto bilinear_pairings_Y_block(bilinear_pairings_Y.blocks.begin());
  // dualResidues[p] = -Tr(A_p Y)
  for(auto &block_index : block_info.block_indices)
    {
      Zero(*dual_residues_block);
      const size_t block_size(block_info.degrees[block_index] + 1);

      // Not sure whether it is better to first loop over blocks in
      // the result or over sub-blocks in bilinear_pairings_Y
      for(size_t bb = 2 * block_index; bb < 2 * block_index + 2; ++bb)
        {
          for(size_t column_block = 0;
              column_block < block_info.dimensions[block_index];
              ++column_block)
            for(size_t row_block = 0; row_block <= column_block; ++row_block)
              {
                size_t column_offset(column_block * block_size),
                  row_offset(row_block * block_size);

                El::DistMatrix<El::BigFloat> lower_diagonal(El::GetDiagonal(
                  El::LockedView(*bilinear_pairings_Y_block, row_offset,
                                 column_offset, block_size, block_size)));

                size_t residue_row_offset(
                  ((column_block * (column_block + 1)) / 2 + row_block)
                  * block_size);

                El::DistMatrix<El::BigFloat> residue_sub_block(El::View(
                  *dual_residues_block, residue_row_offset, 0, block_size, 1));

                // Do a little less work when on a diagonal block.
                if(column_offset == row_offset)
                  {
                    El::Axpy(El::BigFloat(-1.0), lower_diagonal,
                             residue_sub_block);
                  }
                else
                  {
                    El::Axpy(El::BigFloat(-0.5), lower_diagonal,
                             residue_sub_block);

                    El::DistMatrix<El::BigFloat> upper_diagonal(
                      El::GetDiagonal(El::LockedView(
                        *bilinear_pairings_Y_block, column_offset, row_offset,
                        block_size, block_size)));

                    El::Axpy(El::BigFloat(-0.5), upper_diagonal,
                             residue_sub_block);
                  }
              }
          ++bilinear_pairings_Y_block;
        }
      // dualResidues -= FreeVarMatrix * y
      Gemm(El::Orientation::NORMAL, El::Orientation::NORMAL, El::BigFloat(-1),
           *free_var_matrix_block, *y_block, El::BigFloat(1),
           *dual_residues_block);
      // dualResidues += primalObjective
      Axpy(El::BigFloat(1), *primal_objective_c_block, *dual_residues_block);

      ++primal_objective_c_block;
      ++y_block;
      ++free_var_matrix_block;
      ++dual_residues_block;
    }
}
<|endoftext|>


<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h"

#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
#include "tensorflow/lite/micro/micro_utils.h"

namespace tflite {

namespace {

constexpr int kInputTensor = 0;
constexpr int kBlockShapeTensor = 1;
constexpr int kCropsTensor = 2;
constexpr int kOutputTensor = 0;

// Currently, only 3D NHC and 4D NHWC input/output op_context are supported.
// In case of 3D input, it will be extended to 3D NHWC by adding W=1.
// The 4D array need to have exactly 2 spatial dimensions.
// TODO(b/149952582): Support arbitrary dimension in SpaceToBatchND.
const int kInputOutputMinDimensionNum = 3;
const int kInputOutputMaxDimensionNum = 4;

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TF_LITE_ENSURE_EQ(context, NumInputs(node), 3);
  TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);

  const TfLiteTensor* input = GetInput(context, node, kInputTensor);
  TfLiteTensor* output = GetOutput(context, node, kOutputTensor);
  TF_LITE_ENSURE(context, input != nullptr && output != nullptr);

  TF_LITE_ENSURE(context, NumDimensions(input) >= kInputOutputMinDimensionNum);
  TF_LITE_ENSURE(context, NumDimensions(output) >= kInputOutputMinDimensionNum);
  TF_LITE_ENSURE(context, NumDimensions(input) <= kInputOutputMaxDimensionNum);
  TF_LITE_ENSURE(context, NumDimensions(output) <= kInputOutputMaxDimensionNum);
  TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type);

  // Padding can result in a larger output than input.
  TF_LITE_ENSURE(context,
                 ElementCount(*output->dims) >= ElementCount(*input->dims));

  return kTfLiteOk;
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  const TfLiteEvalTensor* input =
      tflite::micro::GetEvalInput(context, node, kInputTensor);
  const TfLiteEvalTensor* block_shape =
      tflite::micro::GetEvalInput(context, node, kBlockShapeTensor);
  const TfLiteEvalTensor* crops =
      tflite::micro::GetEvalInput(context, node, kCropsTensor);
  TfLiteEvalTensor* output =
      tflite::micro::GetEvalOutput(context, node, kOutputTensor);

  switch (input->type) {  // Already know in/out types are same.
    case kTfLiteFloat32:
      reference_ops::BatchToSpaceND(
          tflite::micro::GetTensorShape(input),
          tflite::micro::GetTensorData<float>(input),
          tflite::micro::GetTensorShape(block_shape),
          tflite::micro::GetTensorData<int32_t>(block_shape),
          tflite::micro::GetTensorShape(crops),
          tflite::micro::GetTensorData<int32_t>(crops),
          tflite::micro::GetTensorShape(output),
          tflite::micro::GetTensorData<float>(output));
      break;
    case kTfLiteInt8:
      reference_ops::BatchToSpaceND(
          tflite::micro::GetTensorShape(input),
          tflite::micro::GetTensorData<int8_t>(input),
          tflite::micro::GetTensorShape(block_shape),
          tflite::micro::GetTensorData<int32_t>(block_shape),
          tflite::micro::GetTensorShape(crops),
          tflite::micro::GetTensorData<int32_t>(crops),
          tflite::micro::GetTensorShape(output),
          tflite::micro::GetTensorData<int8_t>(output));
      break;
    default:
      TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
                         TfLiteTypeGetName(input->type), input->type);
      return kTfLiteError;
  }
  return kTfLiteOk;
}

}  // namespace.

TfLiteRegistration Register_BATCH_TO_SPACE_ND() {
  return {/*init=*/nullptr,
          /*free=*/nullptr,
          /*prepare=*/Prepare,
          /*invoke=*/Eval,
          /*profiling_string=*/nullptr,
          /*builtin_code=*/0,
          /*custom_name=*/nullptr,
          /*version=*/0};
}

}  // namespace tflite
<commit_msg>Fixed ensure criterion<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h"

#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
#include "tensorflow/lite/micro/micro_utils.h"

namespace tflite {

namespace {

constexpr int kInputTensor = 0;
constexpr int kBlockShapeTensor = 1;
constexpr int kCropsTensor = 2;
constexpr int kOutputTensor = 0;

// Currently, only 3D NHC and 4D NHWC input/output op_context are supported.
// In case of 3D input, it will be extended to 3D NHWC by adding W=1.
// The 4D array need to have exactly 2 spatial dimensions.
// TODO(b/149952582): Support arbitrary dimension in SpaceToBatchND.
const int kInputOutputMinDimensionNum = 3;
const int kInputOutputMaxDimensionNum = 4;

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TF_LITE_ENSURE_EQ(context, NumInputs(node), 3);
  TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);

  const TfLiteTensor* input = GetInput(context, node, kInputTensor);
  TfLiteTensor* output = GetOutput(context, node, kOutputTensor);
  TF_LITE_ENSURE(context, input != nullptr && output != nullptr);

  TF_LITE_ENSURE(context, NumDimensions(input) >= kInputOutputMinDimensionNum);
  TF_LITE_ENSURE(context, NumDimensions(output) >= kInputOutputMinDimensionNum);
  TF_LITE_ENSURE(context, NumDimensions(input) <= kInputOutputMaxDimensionNum);
  TF_LITE_ENSURE(context, NumDimensions(output) <= kInputOutputMaxDimensionNum);
  TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type);

  // Padding can result in a larger output than input.
  TF_LITE_ENSURE(context,
                 ElementCount(*output->dims) <= ElementCount(*input->dims));

  return kTfLiteOk;
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  const TfLiteEvalTensor* input =
      tflite::micro::GetEvalInput(context, node, kInputTensor);
  const TfLiteEvalTensor* block_shape =
      tflite::micro::GetEvalInput(context, node, kBlockShapeTensor);
  const TfLiteEvalTensor* crops =
      tflite::micro::GetEvalInput(context, node, kCropsTensor);
  TfLiteEvalTensor* output =
      tflite::micro::GetEvalOutput(context, node, kOutputTensor);

  switch (input->type) {  // Already know in/out types are same.
    case kTfLiteFloat32:
      reference_ops::BatchToSpaceND(
          tflite::micro::GetTensorShape(input),
          tflite::micro::GetTensorData<float>(input),
          tflite::micro::GetTensorShape(block_shape),
          tflite::micro::GetTensorData<int32_t>(block_shape),
          tflite::micro::GetTensorShape(crops),
          tflite::micro::GetTensorData<int32_t>(crops),
          tflite::micro::GetTensorShape(output),
          tflite::micro::GetTensorData<float>(output));
      break;
    case kTfLiteInt8:
      reference_ops::BatchToSpaceND(
          tflite::micro::GetTensorShape(input),
          tflite::micro::GetTensorData<int8_t>(input),
          tflite::micro::GetTensorShape(block_shape),
          tflite::micro::GetTensorData<int32_t>(block_shape),
          tflite::micro::GetTensorShape(crops),
          tflite::micro::GetTensorData<int32_t>(crops),
          tflite::micro::GetTensorShape(output),
          tflite::micro::GetTensorData<int8_t>(output));
      break;
    default:
      TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
                         TfLiteTypeGetName(input->type), input->type);
      return kTfLiteError;
  }
  return kTfLiteOk;
}

}  // namespace.

TfLiteRegistration Register_BATCH_TO_SPACE_ND() {
  return {/*init=*/nullptr,
          /*free=*/nullptr,
          /*prepare=*/Prepare,
          /*invoke=*/Eval,
          /*profiling_string=*/nullptr,
          /*builtin_code=*/0,
          /*custom_name=*/nullptr,
          /*version=*/0};
}

}  // namespace tflite
<|endoftext|>


<commit_before>/*
 Copyright (c) 2010, The Barbarian Group
 All rights reserved.

 Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list 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.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
*/

#include "cinder/msw/CinderMsw.h"
#include "cinder/ip/Fill.h"
#include "cinder/Exception.h"

#include <vector>

#if ! defined( CINDER_WINRT ) && ( _MSC_VER < 1900 )
#include <boost/thread/tss.hpp>
#endif

namespace cinder { namespace msw {

#if !defined( CINDER_WINRT )
Surface8uRef convertHBitmap( HBITMAP hbitmap )
{
	// create a temporary DC
	HDC hdc = ::CreateCompatibleDC( 0 );

	// determine the dimensions first
	BITMAP bm;
	::GetObject( hbitmap, sizeof(BITMAP), &bm );

	BITMAPINFO bmi;
	memset( &bmi, 0, sizeof(BITMAPINFO) );
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biHeight = -bm.bmHeight;
	bmi.bmiHeader.biWidth = bm.bmWidth;
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = 32;
	bmi.bmiHeader.biCompression = BI_RGB;
	bmi.bmiHeader.biSizeImage = 0;
	bmi.bmiHeader.biXPelsPerMeter = 0;
	bmi.bmiHeader.biYPelsPerMeter = 0;
	bmi.bmiHeader.biClrUsed = 0;
	bmi.bmiHeader.biClrImportant = 0;

	int width = bmi.bmiHeader.biWidth;
	int height = -bmi.bmiHeader.biHeight;

	// allocate enough space to hold the result
	// We use GlobalAlloc / GlobalFree to ensure 8-byte alignment
	DWORD dwBmpSize = ((width * 32 + 31) / 32) * 4 * height;
	uint8_t *data = reinterpret_cast<uint8_t*>( ::GlobalAlloc( GMEM_FIXED, dwBmpSize ) );
	Surface8u *newSurface = new Surface8u( data, width, height, width * 4, SurfaceChannelOrder::BGRX );
	Surface8uRef result( newSurface, [=] ( Surface8u *s ) { ::GlobalFree( (HGLOBAL)data ); delete s; } );
	// have the Surface's destructor call this to call ::GlobalFree

	if( ::GetDIBits( hdc, hbitmap, 0, height, result->getData(), &bmi, DIB_RGB_COLORS ) == 0 )
		throw Exception( "Invalid HBITMAP" );

	::ReleaseDC( NULL, hdc );

	return result;
}
#endif

void ComDelete( void *p )
{
	if( p ) {
		IUnknown *unknown = reinterpret_cast<IUnknown*>( p );
		unknown->Release();
	}
}

/////////////////////////////////////////////////////////////////////
// ComOStream

HRESULT STDMETHODCALLTYPE ComOStream::QueryInterface(REFIID iid, void ** ppvObject)
{
    if (iid == __uuidof(IUnknown)
        || iid == __uuidof(IStream)
        || iid == __uuidof(ISequentialStream))
    {
        *ppvObject = static_cast<IStream*>(this);
        AddRef();
        return S_OK;
    }
    else
        return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE ComOStream::AddRef()
{
    return (ULONG)InterlockedIncrement(&_refcount);
}

ULONG STDMETHODCALLTYPE ComOStream::Release()
{
    ULONG res = (ULONG) InterlockedDecrement(&_refcount);
    if (res == 0)
        delete this;
    return res;
}

HRESULT STDMETHODCALLTYPE ComOStream::Write( void const* pv, ULONG cb, ULONG* pcbWritten )
{
	mOStream->writeData( pv, cb );
	*pcbWritten = cb;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE ComOStream::Seek( LARGE_INTEGER liDistanceToMove, DWORD dwOrigin, ULARGE_INTEGER* lpNewFilePointer )
{
	switch( dwOrigin ) {
		case STREAM_SEEK_SET:
			mOStream->seekAbsolute( (off_t)liDistanceToMove.QuadPart );
		break;
		case STREAM_SEEK_CUR:
			mOStream->seekRelative( (off_t)liDistanceToMove.QuadPart );
		break;
		case STREAM_SEEK_END:
			mOStream->seekAbsolute( (off_t)(-liDistanceToMove.QuadPart) );
		break;
		default:
			return STG_E_INVALIDFUNCTION;
		break;
	}

	lpNewFilePointer->QuadPart = mOStream->tell();

	return S_OK;
}

std::wstring toWideString( const std::string &utf8String )
{
	int wideSize = ::MultiByteToWideChar( CP_UTF8, 0, utf8String.c_str(), -1, NULL, 0 );
	if( wideSize == ERROR_NO_UNICODE_TRANSLATION ) {
		throw Exception( "Invalid UTF-8 sequence." );
	}
	else if( wideSize == 0 ) {
		throw Exception( "Error in UTF-8 to UTF-16 conversion." );
	}

	std::vector<wchar_t> resultString( wideSize );
	int convResult = ::MultiByteToWideChar( CP_UTF8, 0, utf8String.c_str(), -1, &resultString[0], wideSize );
	if( convResult != wideSize ) {
		throw Exception( "Error in UTF-8 to UTF-16 conversion." );
	}

	return std::wstring( &resultString[0] );
}

std::string toUtf8String( const std::wstring &wideString )
{
	int utf8Size = ::WideCharToMultiByte( CP_UTF8, 0, wideString.c_str(), -1, NULL, 0, NULL, NULL );
	if( utf8Size == 0 ) {
		throw Exception( "Error in UTF-16 to UTF-8 conversion." );
	}

	std::vector<char> resultString( utf8Size );

	int convResult = ::WideCharToMultiByte( CP_UTF8, 0, wideString.c_str(), -1, &resultString[0], utf8Size, NULL, NULL );

	if( convResult != utf8Size ) {
		throw Exception( "Error in UTF-16 to UTF-8 conversion." );
	}

	return std::string( &resultString[0] );
}

/////////////////////////////////////////////////////////////////////
// ComIStream

HRESULT STDMETHODCALLTYPE ComIStream::QueryInterface(REFIID iid, void ** ppvObject)
{
	if (iid == __uuidof(IUnknown)
		|| iid == __uuidof(IStream)
		|| iid == __uuidof(ISequentialStream))
	{
		*ppvObject = static_cast<IStream*>(this);
		AddRef();
		return S_OK;
	}
	else
		return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE ComIStream::AddRef()
{
	return (ULONG)InterlockedIncrement(&_refcount);
}

ULONG STDMETHODCALLTYPE ComIStream::Release()
{
	ULONG res = (ULONG) InterlockedDecrement(&_refcount);
	if (res == 0)
		delete this;
	return res;
}

HRESULT STDMETHODCALLTYPE ComIStream::Read( void* pv, ULONG cb, ULONG* pcbRead )
{
	ULONG dataLeft = mIStream->size() - mIStream->tell();
	if( dataLeft < cb ) {
		mIStream->readData( pv, dataLeft );
		*pcbRead = dataLeft;
		return S_FALSE;
	}
	else {
		mIStream->readData( pv, cb );
		*pcbRead = cb;
		return S_OK;
	}
}

HRESULT STDMETHODCALLTYPE ComIStream::Seek( LARGE_INTEGER liDistanceToMove, DWORD dwOrigin, ULARGE_INTEGER* lpNewFilePointer )
{
	switch( dwOrigin ) {
	case STREAM_SEEK_SET:
		mIStream->seekAbsolute( (off_t)liDistanceToMove.QuadPart );
		break;
	case STREAM_SEEK_CUR:
		mIStream->seekRelative( (off_t)liDistanceToMove.QuadPart );
		break;
	case STREAM_SEEK_END:
		mIStream->seekAbsolute( (off_t)( - liDistanceToMove.QuadPart ) );
		break;
	default:
		return STG_E_INVALIDFUNCTION;
		break;
	}
	off_t pos = mIStream->tell();
	if( lpNewFilePointer )
		lpNewFilePointer->QuadPart = pos;

	return S_OK;
}

HRESULT STDMETHODCALLTYPE ComIStream::Stat( STATSTG* pStatstg, DWORD grfStatFlag)
{
	pStatstg->pwcsName = NULL;
	pStatstg->cbSize.QuadPart = (ULONGLONG)mIStream->size();

	return S_OK;
}

/////////////////////////////////////////////////////////////////////
// ComInitializer

struct ComInitializer {
	ComInitializer( DWORD params ) {
		::CoInitializeEx( NULL, params );
	}

	~ComInitializer()
	{
		::CoUninitialize();
	}
};

#if defined( CINDER_WINRT )

void initializeCom( DWORD params )
{
	::CoInitializeEx( NULL, params );
}
#elif ( _MSC_VER >= 1900 )
thread_local ComInitializer *threadComInitializer = nullptr;

void initializeCom(DWORD params)
{
	if( ! threadComInitializer )
		threadComInitializer = new ComInitializer(params);
}
#else
boost::thread_specific_ptr<ComInitializer> threadComInitializer;

void initializeCom( DWORD params )
{
	if( threadComInitializer.get() == NULL )
		threadComInitializer.reset( new ComInitializer( params ) );
}
#endif

} } // namespace cinder::msw
<commit_msg>Removing CinderMsw.cpp dependency on Boost.thread<commit_after>/*
 Copyright (c) 2010, The Barbarian Group
 All rights reserved.

 Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list 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.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
*/

#include "cinder/msw/CinderMsw.h"
#include "cinder/ip/Fill.h"
#include "cinder/Exception.h"

#include <vector>

namespace cinder { namespace msw {

#if !defined( CINDER_WINRT )
Surface8uRef convertHBitmap( HBITMAP hbitmap )
{
	// create a temporary DC
	HDC hdc = ::CreateCompatibleDC( 0 );

	// determine the dimensions first
	BITMAP bm;
	::GetObject( hbitmap, sizeof(BITMAP), &bm );

	BITMAPINFO bmi;
	memset( &bmi, 0, sizeof(BITMAPINFO) );
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biHeight = -bm.bmHeight;
	bmi.bmiHeader.biWidth = bm.bmWidth;
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = 32;
	bmi.bmiHeader.biCompression = BI_RGB;
	bmi.bmiHeader.biSizeImage = 0;
	bmi.bmiHeader.biXPelsPerMeter = 0;
	bmi.bmiHeader.biYPelsPerMeter = 0;
	bmi.bmiHeader.biClrUsed = 0;
	bmi.bmiHeader.biClrImportant = 0;

	int width = bmi.bmiHeader.biWidth;
	int height = -bmi.bmiHeader.biHeight;

	// allocate enough space to hold the result
	// We use GlobalAlloc / GlobalFree to ensure 8-byte alignment
	DWORD dwBmpSize = ((width * 32 + 31) / 32) * 4 * height;
	uint8_t *data = reinterpret_cast<uint8_t*>( ::GlobalAlloc( GMEM_FIXED, dwBmpSize ) );
	Surface8u *newSurface = new Surface8u( data, width, height, width * 4, SurfaceChannelOrder::BGRX );
	Surface8uRef result( newSurface, [=] ( Surface8u *s ) { ::GlobalFree( (HGLOBAL)data ); delete s; } );
	// have the Surface's destructor call this to call ::GlobalFree

	if( ::GetDIBits( hdc, hbitmap, 0, height, result->getData(), &bmi, DIB_RGB_COLORS ) == 0 )
		throw Exception( "Invalid HBITMAP" );

	::ReleaseDC( NULL, hdc );

	return result;
}
#endif

void ComDelete( void *p )
{
	if( p ) {
		IUnknown *unknown = reinterpret_cast<IUnknown*>( p );
		unknown->Release();
	}
}

/////////////////////////////////////////////////////////////////////
// ComOStream

HRESULT STDMETHODCALLTYPE ComOStream::QueryInterface(REFIID iid, void ** ppvObject)
{
    if (iid == __uuidof(IUnknown)
        || iid == __uuidof(IStream)
        || iid == __uuidof(ISequentialStream))
    {
        *ppvObject = static_cast<IStream*>(this);
        AddRef();
        return S_OK;
    }
    else
        return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE ComOStream::AddRef()
{
    return (ULONG)InterlockedIncrement(&_refcount);
}

ULONG STDMETHODCALLTYPE ComOStream::Release()
{
    ULONG res = (ULONG) InterlockedDecrement(&_refcount);
    if (res == 0)
        delete this;
    return res;
}

HRESULT STDMETHODCALLTYPE ComOStream::Write( void const* pv, ULONG cb, ULONG* pcbWritten )
{
	mOStream->writeData( pv, cb );
	*pcbWritten = cb;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE ComOStream::Seek( LARGE_INTEGER liDistanceToMove, DWORD dwOrigin, ULARGE_INTEGER* lpNewFilePointer )
{
	switch( dwOrigin ) {
		case STREAM_SEEK_SET:
			mOStream->seekAbsolute( (off_t)liDistanceToMove.QuadPart );
		break;
		case STREAM_SEEK_CUR:
			mOStream->seekRelative( (off_t)liDistanceToMove.QuadPart );
		break;
		case STREAM_SEEK_END:
			mOStream->seekAbsolute( (off_t)(-liDistanceToMove.QuadPart) );
		break;
		default:
			return STG_E_INVALIDFUNCTION;
		break;
	}

	lpNewFilePointer->QuadPart = mOStream->tell();

	return S_OK;
}

std::wstring toWideString( const std::string &utf8String )
{
	int wideSize = ::MultiByteToWideChar( CP_UTF8, 0, utf8String.c_str(), -1, NULL, 0 );
	if( wideSize == ERROR_NO_UNICODE_TRANSLATION ) {
		throw Exception( "Invalid UTF-8 sequence." );
	}
	else if( wideSize == 0 ) {
		throw Exception( "Error in UTF-8 to UTF-16 conversion." );
	}

	std::vector<wchar_t> resultString( wideSize );
	int convResult = ::MultiByteToWideChar( CP_UTF8, 0, utf8String.c_str(), -1, &resultString[0], wideSize );
	if( convResult != wideSize ) {
		throw Exception( "Error in UTF-8 to UTF-16 conversion." );
	}

	return std::wstring( &resultString[0] );
}

std::string toUtf8String( const std::wstring &wideString )
{
	int utf8Size = ::WideCharToMultiByte( CP_UTF8, 0, wideString.c_str(), -1, NULL, 0, NULL, NULL );
	if( utf8Size == 0 ) {
		throw Exception( "Error in UTF-16 to UTF-8 conversion." );
	}

	std::vector<char> resultString( utf8Size );

	int convResult = ::WideCharToMultiByte( CP_UTF8, 0, wideString.c_str(), -1, &resultString[0], utf8Size, NULL, NULL );

	if( convResult != utf8Size ) {
		throw Exception( "Error in UTF-16 to UTF-8 conversion." );
	}

	return std::string( &resultString[0] );
}

/////////////////////////////////////////////////////////////////////
// ComIStream

HRESULT STDMETHODCALLTYPE ComIStream::QueryInterface(REFIID iid, void ** ppvObject)
{
	if (iid == __uuidof(IUnknown)
		|| iid == __uuidof(IStream)
		|| iid == __uuidof(ISequentialStream))
	{
		*ppvObject = static_cast<IStream*>(this);
		AddRef();
		return S_OK;
	}
	else
		return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE ComIStream::AddRef()
{
	return (ULONG)InterlockedIncrement(&_refcount);
}

ULONG STDMETHODCALLTYPE ComIStream::Release()
{
	ULONG res = (ULONG) InterlockedDecrement(&_refcount);
	if (res == 0)
		delete this;
	return res;
}

HRESULT STDMETHODCALLTYPE ComIStream::Read( void* pv, ULONG cb, ULONG* pcbRead )
{
	ULONG dataLeft = mIStream->size() - mIStream->tell();
	if( dataLeft < cb ) {
		mIStream->readData( pv, dataLeft );
		*pcbRead = dataLeft;
		return S_FALSE;
	}
	else {
		mIStream->readData( pv, cb );
		*pcbRead = cb;
		return S_OK;
	}
}

HRESULT STDMETHODCALLTYPE ComIStream::Seek( LARGE_INTEGER liDistanceToMove, DWORD dwOrigin, ULARGE_INTEGER* lpNewFilePointer )
{
	switch( dwOrigin ) {
	case STREAM_SEEK_SET:
		mIStream->seekAbsolute( (off_t)liDistanceToMove.QuadPart );
		break;
	case STREAM_SEEK_CUR:
		mIStream->seekRelative( (off_t)liDistanceToMove.QuadPart );
		break;
	case STREAM_SEEK_END:
		mIStream->seekAbsolute( (off_t)( - liDistanceToMove.QuadPart ) );
		break;
	default:
		return STG_E_INVALIDFUNCTION;
		break;
	}
	off_t pos = mIStream->tell();
	if( lpNewFilePointer )
		lpNewFilePointer->QuadPart = pos;

	return S_OK;
}

HRESULT STDMETHODCALLTYPE ComIStream::Stat( STATSTG* pStatstg, DWORD grfStatFlag)
{
	pStatstg->pwcsName = NULL;
	pStatstg->cbSize.QuadPart = (ULONGLONG)mIStream->size();

	return S_OK;
}

/////////////////////////////////////////////////////////////////////
// ComInitializer

struct ComInitializer {
	ComInitializer( DWORD params ) {
		::CoInitializeEx( NULL, params );
	}

	~ComInitializer()
	{
		::CoUninitialize();
	}
};

#if defined( CINDER_WINRT )

void initializeCom( DWORD params )
{
	::CoInitializeEx( NULL, params );
}
#else
__declspec(thread) ComInitializer *threadComInitializer = nullptr;

void initializeCom(DWORD params)
{
	if( ! threadComInitializer )
		threadComInitializer = new ComInitializer(params);
}
#endif

} } // namespace cinder::msw
<|endoftext|>