<commit_before>/*
[CyoJSON] detail/cyojson.hpp

The MIT License (MIT)

Copyright (c) 2016 Graham Bull

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#ifndef __CYOJSON_HPP
#   error Do not #include this file!
#endif

#include <cassert>
#include <cctype>
#include <string>

////////////////////////////////////////////////////////////////////////////////

namespace cyojson
{
    namespace detail
    {
        class ParserImpl final
        {
        public:
            ParserImpl(const char* next, Parser::Callbacks& callbacks)
                : next_(next),
                callbacks_(callbacks)
            {
            }

            ParserImpl(const ParserImpl&) = delete;

            void operator=(const ParserImpl&) = delete;

            bool Parse(int& line, int& column)
            {
                if (!ParseObject())
                {
                    line = line_;
                    column = column_;
                    return false;
                }

                SkipWhitespace();

                line = line_;
                column = column_;
                return (*next_ == '\0');
            }

        private:
            const int c_firstLine = 1;
            const int c_firstColumnOfLine = 1;
            const char* const c_true = "true";
            const char* const c_false = "false";
            const char* const c_null = "null";

            void NextChar()
            {
                ++next_;
                ++column_;
            }

            void NewLine()
            {
                column_ = c_firstColumnOfLine;
                ++line_;
            }

            void SkipWhitespace()
            {
                while (*next_ != '\0')
                {
                    switch (*next_)
                    {
                    case '\r':
                        if (*(next_ + 1) == '\n')
                            next_ += 2;
                        else
                            ++next_;
                        NewLine();
                        continue;

                    case '\n':
                        ++next_;
                        NewLine();
                        continue;
                    }

                    if (std::isspace(*next_))
                        NextChar();
                    else
                        break;
                }
            }

            bool IsNext(char ch, bool skipWhitespace = true)
            {
                assert(ch != '\0');
                assert(!std::isspace(ch));

                if (skipWhitespace)
                    SkipWhitespace();

                if (*next_ != ch)
                    return false;

                NextChar();
                return true;
            }

            bool IsNext(char ch1, char ch2, bool skipWhitespace = true)
            {
                assert(ch1 != '\0' && ch2 != '\0');
                assert(!std::isspace(ch1) && !std::isspace(ch2));

                if (skipWhitespace)
                    SkipWhitespace();

                if (*next_ != ch1 && *next_ != ch2)
                    return false;

                NextChar();
                return true;
            }

            bool IsNext(const char* str, bool skipWhitespace = true)
            {
                assert(str && *str);

                if (skipWhitespace)
                    SkipWhitespace();

                const char* next = next_;
                const char* nextStr = str;
                while (*nextStr && *nextStr == *next)
                {
                    ++next;
                    ++nextStr;
                }

                if (*nextStr)
                    return false;

                next_ += (nextStr - str);

                return true;
            }

            bool ParseString(std::string& out)
            {
                assert(out.empty());

                if (!IsNext('\"'))
                    return false;

                const char* stringStart = next_;
#if 1 //TEMP
                while (*next_ != '\"') //TEMP
                    NextChar(); //TEMP
#else //TEMP
                //TODO: handle unicode characters and control characters
#endif //TEMP

                const char* stringEnd = next_;
                out = std::string(stringStart, stringEnd - stringStart);

                if (!IsNext('\"'))
                    return false;

                return true;
            }

            bool ParseNumber(std::string& out)
            {
                assert(out.empty());

                SkipWhitespace();

                const char* numberStart = next_;

                IsNext('-', false);

                if (!IsNext('0', false))
                {
                    while (std::isdigit(*next_))
                        NextChar();
                }

                if (IsNext('.', false))
                {
                    while (std::isdigit(*next_))
                        NextChar();
                }

                if (IsNext('e', 'E', false))
                {
                    IsNext('+', '-', false);

                    while (std::isdigit(*next_))
                        NextChar();
                }

                const char* numberEnd = next_;
                if (numberStart == numberEnd)
                    return false;

                out = std::string(numberStart, numberEnd - numberStart);
                return true;
            }

            bool ParseValue()
            {
                SkipWhitespace();

                switch (*next_)
                {
                case '{':
                    return ParseObject();

                case '[':
                    return ParseArray();

                case '\"':
                {
                    std::string str;
                    if (!ParseString(str))
                        return false;
                    callbacks_.Value(path_.c_str(), str.c_str());
                    return true;
                }

                case 't':
                    if (!IsNext(c_true))
                        return false;
                    callbacks_.Value(path_.c_str(), c_true);
                    return true;

                case 'f':
                    if (!IsNext(c_false))
                        return false;
                    callbacks_.Value(path_.c_str(), c_false);
                    return true;

                case 'n':
                    if (!IsNext(c_null))
                        return false;
                    callbacks_.Value(path_.c_str(), c_null);
                    return true;

                default:
                {
                    std::string num;
                    if (!ParseNumber(num))
                        return false;
                    callbacks_.Value(path_.c_str(), num.c_str());
                    return true;
                }
                }
            }

            bool ParseArray()
            {
                if (!IsNext('['))
                    return false;

                callbacks_.ArrayStart(path_.c_str());

                if (!IsNext(']'))
                {
                    for (;;)
                    {
                        if (!ParseValue())
                            return false;

                        if (!IsNext(','))
                            break;
                    }
                }

                if (!IsNext(']'))
                    return false;

                callbacks_.ArrayEnd(path_.c_str());

                return true;
            }

            bool ParseObject()
            {
                if (!IsNext('{'))
                    return false;

                callbacks_.ObjectStart(path_.c_str());

                if (!IsNext('}'))
                {
                    for (;;)
                    {
                        std::string name;
                        if (!ParseString(name))
                            return false;
                        if (!path_.empty())
                            path_ += ':';
                        path_ += name;

                        if (!IsNext(':'))
                            return false;

                        if (!ParseValue())
                            return false;

                        auto pos = path_.find_last_of(':');
                        if (pos != path_.npos)
                            path_.erase(pos);
                        else
                            path_.clear();

                        if (!IsNext(','))
                            break;
                    }
                }

                if (!IsNext('}'))
                    return false;

                callbacks_.ObjectEnd(path_.c_str());

                return true;
            }

        private:
            int line_ = c_firstLine;
            int column_ = c_firstColumnOfLine;
            const char* next_;
            std::string path_;
            Parser::Callbacks& callbacks_;
        };
    }

    bool Parser::Parse(const char* json, Callbacks& callbacks)
    {
        if (!json)
            return false;

        return detail::ParserImpl(json, callbacks).Parse(line_, column_);
    }
}
<commit_msg>prevent linker error<commit_after>/*
[CyoJSON] detail/cyojson.hpp

The MIT License (MIT)

Copyright (c) 2016 Graham Bull

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#ifndef __CYOJSON_HPP
#   error Do not #include this file!
#endif

#include <cassert>
#include <cctype>
#include <string>

////////////////////////////////////////////////////////////////////////////////

namespace cyojson
{
    namespace detail
    {
        class ParserImpl final
        {
        public:
            ParserImpl(const char* next, Parser::Callbacks& callbacks)
                : next_(next),
                callbacks_(callbacks)
            {
            }

            ParserImpl(const ParserImpl&) = delete;

            void operator=(const ParserImpl&) = delete;

            bool Parse(int& line, int& column)
            {
                if (!ParseObject())
                {
                    line = line_;
                    column = column_;
                    return false;
                }

                SkipWhitespace();

                line = line_;
                column = column_;
                return (*next_ == '\0');
            }

        private:
            const int c_firstLine = 1;
            const int c_firstColumnOfLine = 1;
            const char* const c_true = "true";
            const char* const c_false = "false";
            const char* const c_null = "null";

            void NextChar()
            {
                ++next_;
                ++column_;
            }

            void NewLine()
            {
                column_ = c_firstColumnOfLine;
                ++line_;
            }

            void SkipWhitespace()
            {
                while (*next_ != '\0')
                {
                    switch (*next_)
                    {
                    case '\r':
                        if (*(next_ + 1) == '\n')
                            next_ += 2;
                        else
                            ++next_;
                        NewLine();
                        continue;

                    case '\n':
                        ++next_;
                        NewLine();
                        continue;
                    }

                    if (std::isspace(*next_))
                        NextChar();
                    else
                        break;
                }
            }

            bool IsNext(char ch, bool skipWhitespace = true)
            {
                assert(ch != '\0');
                assert(!std::isspace(ch));

                if (skipWhitespace)
                    SkipWhitespace();

                if (*next_ != ch)
                    return false;

                NextChar();
                return true;
            }

            bool IsNext(char ch1, char ch2, bool skipWhitespace = true)
            {
                assert(ch1 != '\0' && ch2 != '\0');
                assert(!std::isspace(ch1) && !std::isspace(ch2));

                if (skipWhitespace)
                    SkipWhitespace();

                if (*next_ != ch1 && *next_ != ch2)
                    return false;

                NextChar();
                return true;
            }

            bool IsNext(const char* str, bool skipWhitespace = true)
            {
                assert(str && *str);

                if (skipWhitespace)
                    SkipWhitespace();

                const char* next = next_;
                const char* nextStr = str;
                while (*nextStr && *nextStr == *next)
                {
                    ++next;
                    ++nextStr;
                }

                if (*nextStr)
                    return false;

                next_ += (nextStr - str);

                return true;
            }

            bool ParseString(std::string& out)
            {
                assert(out.empty());

                if (!IsNext('\"'))
                    return false;

                const char* stringStart = next_;
#if 1 //TEMP
                while (*next_ != '\"') //TEMP
                    NextChar(); //TEMP
#else //TEMP
                //TODO: handle unicode characters and control characters
#endif //TEMP

                const char* stringEnd = next_;
                out = std::string(stringStart, stringEnd - stringStart);

                if (!IsNext('\"'))
                    return false;

                return true;
            }

            bool ParseNumber(std::string& out)
            {
                assert(out.empty());

                SkipWhitespace();

                const char* numberStart = next_;

                IsNext('-', false);

                if (!IsNext('0', false))
                {
                    while (std::isdigit(*next_))
                        NextChar();
                }

                if (IsNext('.', false))
                {
                    while (std::isdigit(*next_))
                        NextChar();
                }

                if (IsNext('e', 'E', false))
                {
                    IsNext('+', '-', false);

                    while (std::isdigit(*next_))
                        NextChar();
                }

                const char* numberEnd = next_;
                if (numberStart == numberEnd)
                    return false;

                out = std::string(numberStart, numberEnd - numberStart);
                return true;
            }

            bool ParseValue()
            {
                SkipWhitespace();

                switch (*next_)
                {
                case '{':
                    return ParseObject();

                case '[':
                    return ParseArray();

                case '\"':
                {
                    std::string str;
                    if (!ParseString(str))
                        return false;
                    callbacks_.Value(path_.c_str(), str.c_str());
                    return true;
                }

                case 't':
                    if (!IsNext(c_true))
                        return false;
                    callbacks_.Value(path_.c_str(), c_true);
                    return true;

                case 'f':
                    if (!IsNext(c_false))
                        return false;
                    callbacks_.Value(path_.c_str(), c_false);
                    return true;

                case 'n':
                    if (!IsNext(c_null))
                        return false;
                    callbacks_.Value(path_.c_str(), c_null);
                    return true;

                default:
                {
                    std::string num;
                    if (!ParseNumber(num))
                        return false;
                    callbacks_.Value(path_.c_str(), num.c_str());
                    return true;
                }
                }
            }

            bool ParseArray()
            {
                if (!IsNext('['))
                    return false;

                callbacks_.ArrayStart(path_.c_str());

                if (!IsNext(']'))
                {
                    for (;;)
                    {
                        if (!ParseValue())
                            return false;

                        if (!IsNext(','))
                            break;
                    }
                }

                if (!IsNext(']'))
                    return false;

                callbacks_.ArrayEnd(path_.c_str());

                return true;
            }

            bool ParseObject()
            {
                if (!IsNext('{'))
                    return false;

                callbacks_.ObjectStart(path_.c_str());

                if (!IsNext('}'))
                {
                    for (;;)
                    {
                        std::string name;
                        if (!ParseString(name))
                            return false;
                        if (!path_.empty())
                            path_ += ':';
                        path_ += name;

                        if (!IsNext(':'))
                            return false;

                        if (!ParseValue())
                            return false;

                        auto pos = path_.find_last_of(':');
                        if (pos != path_.npos)
                            path_.erase(pos);
                        else
                            path_.clear();

                        if (!IsNext(','))
                            break;
                    }
                }

                if (!IsNext('}'))
                    return false;

                callbacks_.ObjectEnd(path_.c_str());

                return true;
            }

        private:
            int line_ = c_firstLine;
            int column_ = c_firstColumnOfLine;
            const char* next_;
            std::string path_;
            Parser::Callbacks& callbacks_;
        };
    }

    inline bool Parser::Parse(const char* json, Callbacks& callbacks)
    {
        if (!json)
            return false;

        return detail::ParserImpl(json, callbacks).Parse(line_, column_);
    }
}
<|endoftext|>


<commit_before>namespace mant {
  namespace bbob {
    template <typename T = double>
    class BuecheRastriginFunction : public BlackBoxOptimisationBenchmark<T> {
      static_assert(std::is_floating_point<T>::value, "T must be a floating point type.");

      public:
        explicit BuecheRastriginFunction(
            const std::size_t numberOfDimensions) noexcept;

        std::string toString() const noexcept override;

      protected:
        const arma::Col<T> parameterConditioning_;

        T getSoftConstraintsValueImplementation(
            const arma::Col<T>& parameter) const noexcept override;

        T getObjectiveValueImplementation(
            const arma::Col<T>& parameter) const noexcept override;

#if defined(MANTELLA_USE_PARALLEL)
        friend class cereal::access;
        template <typename Archive>
        void serialize(
            Archive& archive) noexcept {
          archive(cereal::make_nvp("BlackBoxOptimisationBenchmark", cereal::base_class<BlackBoxOptimisationBenchmark>(this)));
          archive(cereal::make_nvp("numberOfDimensions", numberOfDimensions_));
        }

        template <typename Archive>
        static void load_and_construct(
            Archive& archive,
            cereal::construct<BuecheRastriginFunction>& construct) noexcept {
          unsigned int numberOfDimensions;
          archive(cereal::make_nvp("numberOfDimensions", numberOfDimensions));
          construct(numberOfDimensions);

          archive(cereal::make_nvp("BlackBoxOptimisationBenchmark", cereal::base_class<BlackBoxOptimisationBenchmark>(construct.ptr())));
        }
#endif
    };

    //
    // Implementation
    //

    template <typename T>
    BuecheRastriginFunction<T>::BuecheRastriginFunction(
        const std::size_t numberOfDimensions) noexcept
      : BlackBoxOptimisationBenchmark<T>(numberOfDimensions),
        parameterConditioning_(this->getParameterConditioning(std::sqrt(static_cast<T>(10.0L)))) {
      arma::Col<T> parameterTranslation = this->getRandomParameterTranslation();
      for (std::size_t n = 0; n < parameterTranslation.n_elem; n += 2) {
        parameterTranslation(n) = std::abs(parameterTranslation(n));
      }
      this->setParameterTranslation(parameterTranslation);
    }

    template <typename T>
    T BuecheRastriginFunction<T>::getSoftConstraintsValueImplementation(
        const arma::Col<T>& parameter) const noexcept {
      return static_cast<T>(100.0L) * this->getBoundConstraintsValue(parameter);
    }

    template <typename T>
    T BuecheRastriginFunction<T>::getObjectiveValueImplementation(
        const arma::Col<T>& parameter) const noexcept {
      arma::Col<T> z = parameterConditioning_ % this->getOscillatedParameter(parameter);
      for (std::size_t n = 0; n < z.n_elem; n += 2) {
        if (z(n) > static_cast<T>(0.0L)) {
          z(n) *= static_cast<T>(10.0L);
        }
      }

      return static_cast<T>(10.0L) * (static_cast<T>(this->numberOfDimensions_) - arma::accu(arma::cos(static_cast<T>(2.0L) * arma::datum::pi * z))) + std::pow(arma::norm(z), static_cast<T>(2.0L));
    }

    template <typename T>
    std::string BuecheRastriginFunction<T>::toString() const noexcept {
      return "bbob_bueche_rastrigin_function";
    }
  }
}
<commit_msg>Added serialisation support for the Bücke-Rastrigin function<commit_after>namespace mant {
  namespace bbob {
    template <typename T = double>
    class BuecheRastriginFunction : public BlackBoxOptimisationBenchmark<T> {
      static_assert(std::is_floating_point<T>::value, "T must be a floating point type.");

      public:
        explicit BuecheRastriginFunction(
            const std::size_t numberOfDimensions) noexcept;

        std::string toString() const noexcept override;

      protected:
        const arma::Col<T> parameterConditioning_;

        T getSoftConstraintsValueImplementation(
            const arma::Col<T>& parameter) const noexcept override;

        T getObjectiveValueImplementation(
            const arma::Col<T>& parameter) const noexcept override;

#if defined(MANTELLA_USE_PARALLEL_ALGORITHMS)
        friend class OptimisationAlgorithm;

        std::vector<long double> serialise() const noexcept;

        void deserialise(
            const std::vector<long double>& serialisedOptimisationProblem);
#endif
    };

    //
    // Implementation
    //

    template <typename T>
    BuecheRastriginFunction<T>::BuecheRastriginFunction(
        const std::size_t numberOfDimensions) noexcept
      : BlackBoxOptimisationBenchmark<T>(numberOfDimensions),
        parameterConditioning_(this->getParameterConditioning(std::sqrt(static_cast<T>(10.0L)))) {
      arma::Col<T> parameterTranslation = this->getRandomParameterTranslation();
      for (std::size_t n = 0; n < parameterTranslation.n_elem; n += 2) {
        parameterTranslation(n) = std::abs(parameterTranslation(n));
      }
      this->setParameterTranslation(parameterTranslation);
    }

    template <typename T>
    T BuecheRastriginFunction<T>::getSoftConstraintsValueImplementation(
        const arma::Col<T>& parameter) const noexcept {
      return static_cast<T>(100.0L) * this->getBoundConstraintsValue(parameter);
    }

    template <typename T>
    T BuecheRastriginFunction<T>::getObjectiveValueImplementation(
        const arma::Col<T>& parameter) const noexcept {
      arma::Col<T> z = parameterConditioning_ % this->getOscillatedParameter(parameter);
      for (std::size_t n = 0; n < z.n_elem; n += 2) {
        if (z(n) > static_cast<T>(0.0L)) {
          z(n) *= static_cast<T>(10.0L);
        }
      }

      return static_cast<T>(10.0L) * (static_cast<T>(this->numberOfDimensions_) - arma::accu(arma::cos(static_cast<T>(2.0L) * arma::datum::pi * z))) + std::pow(arma::norm(z), static_cast<T>(2.0L));
    }

    template <typename T>
    std::string BuecheRastriginFunction<T>::toString() const noexcept {
      return "bbob_bueche_rastrigin_function";
    }

#if defined(MANTELLA_USE_PARALLEL_ALGORITHMS)
    template <typename T>
    std::vector<long double> BentCigarFunction<T>::serialise() const noexcept {
      return BlackBoxOptimisationBenchmark<T, T>::serialise();;
    }

    template <typename T>
    void BentCigarFunction<T>::deserialise(
        const std::vector<long double>& serialisedOptimisationProblem) {
      BlackBoxOptimisationBenchmark<T, T>::deserialise(serialisedOptimisationProblem);
    }
#endif
  }
}
<|endoftext|>


<commit_before>/* Copyright 2016 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/core/distributed_runtime/remote_device.h"

#include <vector>
#include "tensorflow/core/common_runtime/device.h"
#include "tensorflow/core/common_runtime/process_util.h"
#include "tensorflow/core/distributed_runtime/worker_cache.h"
#include "tensorflow/core/distributed_runtime/worker_interface.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/macros.h"
#include "tensorflow/core/protobuf/worker.pb.h"

namespace tensorflow {

using std::placeholders::_1;

// TODO(zhifengc): We need to consolidate (full/partial) device name
// parsing into one place.
//
// Parses and returns the local device part (e.g., cpu:0, gpu:4).
string GetLocalDeviceName(StringPiece fullname) {
  auto pos = fullname.rfind('/');
  CHECK_NE(pos, StringPiece::npos);
  fullname.remove_prefix(pos + 1);
  return fullname.ToString();
}

class RemoteDevice : public Device {
 public:
  RemoteDevice(Env* env, const DeviceAttributes& da)
      : Device(env, da, nullptr),
        local_dev_name_(GetLocalDeviceName(da.name())) {}

  Status Sync() override { return Status::OK(); }
  Allocator* GetAllocator(AllocatorAttributes attr) override { return nullptr; }

 private:
  const string local_dev_name_;

  TF_DISALLOW_COPY_AND_ASSIGN(RemoteDevice);
};

void NewRemoteDevices(Env* env, WorkerCacheInterface* worker_cache,
                      const string& worker_name, NewRemoteDevicesDone done) {
  WorkerInterface* wi = worker_cache->CreateWorker(worker_name);
  if (wi == nullptr) {
    std::vector<Device*> empty;
    done(errors::NotFound("Device ", worker_name, " is not found."), &empty);
    return;
  }
  struct Call {
    GetStatusRequest req;
    GetStatusResponse resp;
  };
  Call* call = new Call;
  auto cb = [env, worker_cache, worker_name, done, wi, call](const Status& s) {
    std::vector<Device*> remote_devices;
    if (s.ok()) {
      remote_devices.reserve(call->resp.device_attributes_size());
      for (const DeviceAttributes& da : call->resp.device_attributes()) {
        auto d = new RemoteDevice(env, da);
        remote_devices.push_back(d);
      }
    }
    done(s, &remote_devices);
    worker_cache->ReleaseWorker(worker_name, wi);
    delete call;
  };
  wi->GetStatusAsync(&call->req, &call->resp, cb);
}

}  // namespace tensorflow
<commit_msg>Fix potential use-after-free of `worker_cache` in NewRemoteDevices(). Change: 142623343<commit_after>/* Copyright 2016 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/core/distributed_runtime/remote_device.h"

#include <vector>
#include "tensorflow/core/common_runtime/device.h"
#include "tensorflow/core/common_runtime/process_util.h"
#include "tensorflow/core/distributed_runtime/worker_cache.h"
#include "tensorflow/core/distributed_runtime/worker_interface.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/macros.h"
#include "tensorflow/core/protobuf/worker.pb.h"

namespace tensorflow {

using std::placeholders::_1;

// TODO(zhifengc): We need to consolidate (full/partial) device name
// parsing into one place.
//
// Parses and returns the local device part (e.g., cpu:0, gpu:4).
string GetLocalDeviceName(StringPiece fullname) {
  auto pos = fullname.rfind('/');
  CHECK_NE(pos, StringPiece::npos);
  fullname.remove_prefix(pos + 1);
  return fullname.ToString();
}

class RemoteDevice : public Device {
 public:
  RemoteDevice(Env* env, const DeviceAttributes& da)
      : Device(env, da, nullptr),
        local_dev_name_(GetLocalDeviceName(da.name())) {}

  Status Sync() override { return Status::OK(); }
  Allocator* GetAllocator(AllocatorAttributes attr) override { return nullptr; }

 private:
  const string local_dev_name_;

  TF_DISALLOW_COPY_AND_ASSIGN(RemoteDevice);
};

void NewRemoteDevices(Env* env, WorkerCacheInterface* worker_cache,
                      const string& worker_name, NewRemoteDevicesDone done) {
  WorkerInterface* wi = worker_cache->CreateWorker(worker_name);
  if (wi == nullptr) {
    std::vector<Device*> empty;
    done(errors::NotFound("Device ", worker_name, " is not found."), &empty);
    return;
  }
  struct Call {
    GetStatusRequest req;
    GetStatusResponse resp;
  };
  Call* call = new Call;
  auto cb = [env, worker_cache, worker_name, done, wi, call](const Status& s) {
    std::vector<Device*> remote_devices;
    if (s.ok()) {
      remote_devices.reserve(call->resp.device_attributes_size());
      for (const DeviceAttributes& da : call->resp.device_attributes()) {
        auto d = new RemoteDevice(env, da);
        remote_devices.push_back(d);
      }
    }
    worker_cache->ReleaseWorker(worker_name, wi);
    done(s, &remote_devices);
    delete call;
  };
  wi->GetStatusAsync(&call->req, &call->resp, cb);
}

}  // namespace tensorflow
<|endoftext|>


<commit_before>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file traits.hpp
 * \date October 2014
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__UTIL__TRAITS_HPP
#define FL__UTIL__TRAITS_HPP

#include <Eigen/Dense>

namespace fl
{

/**
 * \struct Traits
 * \ingroup traits
 * \brief Generic trait template
 *
 * Filters, models and distributions may specify a \c Traits specialization
 */
template <typename> struct Traits { };

/**
 * \ingroup traits
 *
 * \brief \c IsDynamic<int> trait for static dynamic-size checks.
 *
 * Generic IsDynamic<int> definition which evaluates to false.
 *
 * Examples
 *
 * static_assert(IsDynamic<MyEigenMatrixType::SizeAtCompileTime>(), "");
 *
 * if (IsDynamic<MyEigenMatrixType::SizeAtCompileTime>::value) ...
 */
template <int> struct IsDynamic
{
    static constexpr bool value = false;
    constexpr operator bool () { return value; }
};

/**
 * \ingroup traits
 * \brief \c IsDynamic<-1> or \c IsDynamic<Eigen::Dynamic> trait for static
 * dynamic-size checks.
 *
 * A specialization IsDynamic<Eigen::Dynamic> definition which evaluates to
 * true.
 *
 * Examples
 *
 * // overloaded operator bool ()
 * static_assert(!IsDynamic<MyEigenMatrixType::SizeAtCompileTime>(), "");
 *
 * if (!IsDynamic<MyEigenMatrixType::SizeAtCompileTime>::value) ...
 */
template <> struct IsDynamic<Eigen::Dynamic>
{
    static constexpr bool value = true;
    constexpr operator bool () { return value; }
};

/**
 * \ingroup traits
 *
 * \brief \c IsFixed<int> trait for static fixed-size checks.
 *
 * Generic IsFixed<int> definition which evaluates to true. This traits is the
 * opposite of IsDynamic.
 *
 * Examples
 *
 * static_assert(IsFixed<MyEigenMatrixType::SizeAtCompileTime>::value, "");
 *
 * // overloaded operator bool ()
 * if (IsFixed<MyEigenMatrixType::SizeAtCompileTime>()) ...
 */
template <int> struct IsFixed
{
    static constexpr bool value = true;
    constexpr operator bool () { return value; }
};

/**
 * \ingroup traits
 * \brief \c IsFixed<-1> or \c IsFixed<Eigen::Dynamic> trait for static
 * fixed-size checks.
 *
 * A specialization IsFixed<Eigen::Dynamic> definition which evaluates to
 * false. This traits is the opposite of IsDynamic<Eigen::Dynamic>.
 *
 * Examples
 *
 * static_assert(!IsFixed<MyEigenMatrixType::SizeAtCompileTime>(), "");
 *
 * if (!IsFixed<MyEigenMatrixType::SizeAtCompileTime>::value) ...
 */
template <> struct IsFixed<Eigen::Dynamic>
{
    static constexpr bool value = false;
    constexpr operator bool () { return value; }
};

/**
 * \ingroup traits
 *
 * \brief Mapps Eigen::Dynamic onto 0.
 *
 * For any type matrix or column vector the dimension is the number of rows,
 * i.e. Matrix::RowsAtCompileTime. If the Matrix::SizeAtCompileTime enum is not
 * equal Eigen::Dynamic (-1) the dimension is set to Matrix::RowsAtCompileTime.
 * Otherwise, 0 is returned.
 *
 * Examples
 *
 * static_assert(DimensionOf<MyEigenMatrixType>() > 0, "Dim must be greater 0");
 * static_assert(DimensionOf<MyEigenMatrixType>::value > 0, "Dim must be .. 0");
 *
 * Eigen::VectorXd vector(DimensionOf<MyEigenMatrixType>());
 */
template <typename Matrix> struct DimensionOf
{
    static constexpr size_t value = IsFixed<Matrix::SizeAtCompileTime>()
                                        ? Matrix::RowsAtCompileTime
                                        : 0;
    constexpr operator size_t () { return value; }
};

/**
 * \ingroup traits
 *
 * \brief Returns simple the max integer of A and B
 */
template <int A, int B> struct MaxOf
{
    static constexpr int value = (A > B) ? A : B;
    constexpr operator int () { return value; }
};

}

namespace fl
{

namespace internal
{
//struct Empty { };
typedef Eigen::Matrix<double, 0, 0> Empty;

enum SpaceType
{
    Scalar,
    Vectorial
};
}

}

#endif

<commit_msg>Minor DimensionOf doc fix<commit_after>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file traits.hpp
 * \date October 2014
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__UTIL__TRAITS_HPP
#define FL__UTIL__TRAITS_HPP

#include <Eigen/Dense>

namespace fl
{

/**
 * \struct Traits
 * \ingroup traits
 * \brief Generic trait template
 *
 * Filters, models and distributions may specify a \c Traits specialization
 */
template <typename> struct Traits { };

/**
 * \ingroup traits
 *
 * \brief \c IsDynamic<int> trait for static dynamic-size checks.
 *
 * Generic IsDynamic<int> definition which evaluates to false.
 *
 * Examples
 *
 * static_assert(IsDynamic<MyEigenMatrixType::SizeAtCompileTime>(), "");
 *
 * if (IsDynamic<MyEigenMatrixType::SizeAtCompileTime>::value) ...
 */
template <int> struct IsDynamic
{
    static constexpr bool value = false;
    constexpr operator bool () { return value; }
};

/**
 * \ingroup traits
 * \brief \c IsDynamic<-1> or \c IsDynamic<Eigen::Dynamic> trait for static
 * dynamic-size checks.
 *
 * A specialization IsDynamic<Eigen::Dynamic> definition which evaluates to
 * true.
 *
 * Examples
 *
 * // overloaded operator bool ()
 * static_assert(!IsDynamic<MyEigenMatrixType::SizeAtCompileTime>(), "");
 *
 * if (!IsDynamic<MyEigenMatrixType::SizeAtCompileTime>::value) ...
 */
template <> struct IsDynamic<Eigen::Dynamic>
{
    static constexpr bool value = true;
    constexpr operator bool () { return value; }
};

/**
 * \ingroup traits
 *
 * \brief \c IsFixed<int> trait for static fixed-size checks.
 *
 * Generic IsFixed<int> definition which evaluates to true. This traits is the
 * opposite of IsDynamic.
 *
 * Examples
 *
 * static_assert(IsFixed<MyEigenMatrixType::SizeAtCompileTime>::value, "");
 *
 * // overloaded operator bool ()
 * if (IsFixed<MyEigenMatrixType::SizeAtCompileTime>()) ...
 */
template <int> struct IsFixed
{
    static constexpr bool value = true;
    constexpr operator bool () { return value; }
};

/**
 * \ingroup traits
 * \brief \c IsFixed<-1> or \c IsFixed<Eigen::Dynamic> trait for static
 * fixed-size checks.
 *
 * A specialization IsFixed<Eigen::Dynamic> definition which evaluates to
 * false. This traits is the opposite of IsDynamic<Eigen::Dynamic>.
 *
 * Examples
 *
 * static_assert(!IsFixed<MyEigenMatrixType::SizeAtCompileTime>(), "");
 *
 * if (!IsFixed<MyEigenMatrixType::SizeAtCompileTime>::value) ...
 */
template <> struct IsFixed<Eigen::Dynamic>
{
    static constexpr bool value = false;
    constexpr operator bool () { return value; }
};

/**
 * \ingroup traits
 *
 * \brief Mapps Eigen::Dynamic onto 0.
 *
 * For any type matrix or column vector the dimension is the number of rows,
 * i.e. Matrix::RowsAtCompileTime. If the Matrix::SizeAtCompileTime enum is not
 * equal Eigen::Dynamic (-1) the dimension is set to Matrix::RowsAtCompileTime.
 * Otherwise, 0 is returned.
 *
 * Examples
 *
 * static_assert(DimensionOf<MyEigenMatrixType>() > 0, "Dim must be greater 0");
 *
 * static_assert(DimensionOf<MyEigenMatrixType>::value > 0, "Dim must be .. 0");
 *
 * Eigen::VectorXd vector(DimensionOf<MyEigenMatrixType>());
 */
template <typename Matrix> struct DimensionOf
{
    static constexpr size_t value = IsFixed<Matrix::SizeAtCompileTime>()
                                        ? Matrix::RowsAtCompileTime
                                        : 0;
    constexpr operator size_t () { return value; }
};

/**
 * \ingroup traits
 *
 * \brief Returns simple the max integer of A and B
 */
template <int A, int B> struct MaxOf
{
    static constexpr int value = (A > B) ? A : B;
    constexpr operator int () { return value; }
};

}

namespace fl
{

namespace internal
{
//struct Empty { };
typedef Eigen::Matrix<double, 0, 0> Empty;

enum SpaceType
{
    Scalar,
    Vectorial
};
}

}

#endif

<|endoftext|>


<commit_before>/* Tests the ttasim device driver.

   Copyright (c) 2012 Pekka Jääskeläinen / Tampere University of Technology

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.
*/

// Enable OpenCL C++ exceptions
#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cassert>

#include "poclu.h"

static char
kernelSourceCode[] =
"int putchar(int c);\n"
"kernel \n"
"void test_kernel(constant char *input,\n"
"                 __global char *output,\n"
"                 float a,\n"
"                 int b) {\n"
"    constant char* pos = input; \n"
"    while (*pos) {\n"
"        putchar (*pos);\n"
"        ++pos;\n"
"    }\n"
"    printf(\"%f %d\", a, b);\n"
"    output[0] = 'P'; \n"
"    output[1] = 'O'; \n"
"    output[2] = 'N'; \n"
"    output[3] = 'G'; \n"
"    output[4] = '\\0'; \n"
"}\n";

int
main(void)
{
    const int OUTPUT_SIZE = 5;
    const char *input = "PING\0";
    char output[OUTPUT_SIZE];
    float a = 23456.0f;
    int b = 2000001;

    try {
        std::vector<cl::Platform> platformList;

        // Pick platform
        cl::Platform::get(&platformList);

        // Pick first platform
        cl_context_properties cprops[] = {
            CL_CONTEXT_PLATFORM, (cl_context_properties)(platformList[0])(), 0};
        cl::Context context(CL_DEVICE_TYPE_GPU, cprops);

        // Query the set of devices attched to the context
        std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();

        assert (devices.size() == 1);

        cl::Device device = devices.at(0);

        assert (device.getInfo<CL_DEVICE_NAME>() == "ttasim");

        a = poclu_bswap_cl_float (device(), a);
        b = poclu_bswap_cl_int (device(), b);

        // Create and program from source
        cl::Program::Sources sources(1, std::make_pair(kernelSourceCode, 0));
        cl::Program program(context, sources);

        // Build program
        program.build(devices);

        cl::Buffer inputBuffer = cl::Buffer(
            context,
            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
            strlen (input), (void *) &input[0]);

        // Create buffer for that uses the host ptr C
        cl::Buffer outputBuffer = cl::Buffer(
            context,
            CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
            OUTPUT_SIZE, (void *) &output[0]);

        // Create kernel object
        cl::Kernel kernel(program, "test_kernel");

        // Set kernel args
        kernel.setArg(0, inputBuffer);
        kernel.setArg(1, outputBuffer);
        kernel.setArg(2, a);
        kernel.setArg(3, b);

        // Create command queue
        cl::CommandQueue queue(context, devices[0], CL_QUEUE_PROFILING_ENABLE);

        cl::Event enqEvent;

        // Do the work
        queue.enqueueNDRangeKernel(
            kernel,
            cl::NullRange,
            cl::NDRange(1),
            cl::NullRange,
            NULL, &enqEvent);

        cl::Event mapEvent;
        (int *) queue.enqueueMapBuffer(
            outputBuffer,
            CL_TRUE, // block
            CL_MAP_READ,
            0, OUTPUT_SIZE, NULL, &mapEvent);

        if (std::string(output) == "PONG")
            std::cout << "OK\n";
        else
            std::cerr << "FAIL, received: " << output << "\n";

        cl::Event unmapEvent;
        // Finally release our hold on accessing the memory
        queue.enqueueUnmapMemObject(
            outputBuffer,
            (void *) &output[0],
            NULL,
            &unmapEvent);

        queue.finish();

        assert (enqEvent.getInfo<CL_EVENT_COMMAND_EXECUTION_STATUS>() == CL_COMPLETE);
        assert (mapEvent.getInfo<CL_EVENT_COMMAND_EXECUTION_STATUS>() == CL_COMPLETE);
        assert (unmapEvent.getInfo<CL_EVENT_COMMAND_EXECUTION_STATUS>() == CL_COMPLETE);

        assert (
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_QUEUED>() <=
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>());

        assert (
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>() <=
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>());

        assert (
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>() <
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>());

#if 0
        std::cerr << "exec time: "
                  << enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>() -
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>() << std::endl;
#endif

        assert (
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_QUEUED>() <=
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>());

        assert (
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>() <=
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>());

        assert (
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>() <=
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>());

        assert (
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_QUEUED>() <=
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>());

        assert (
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>() <=
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>());

        assert (
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>() <=
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>());

        assert (enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>() <
                mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>());

        assert (mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>() <
                unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>());

    }
    catch (cl::Error err) {
         std::cerr
             << "ERROR: "
             << err.what()
             << "("
             << err.err()
             << ")"
             << std::endl;

         return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
<commit_msg>Allow the events have equal time stamps as it can happen with the time stamp granularity of the ttasim. Its timestamps are not realistic for other events than the kernel execution events.<commit_after>/* Tests the ttasim device driver.

   Copyright (c) 2012 Pekka Jääskeläinen / Tampere University of Technology

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.
*/

// Enable OpenCL C++ exceptions
#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cassert>

#include "poclu.h"

static char
kernelSourceCode[] =
"int putchar(int c);\n"
"kernel \n"
"void test_kernel(constant char *input,\n"
"                 __global char *output,\n"
"                 float a,\n"
"                 int b) {\n"
"    constant char* pos = input; \n"
"    while (*pos) {\n"
"        putchar (*pos);\n"
"        ++pos;\n"
"    }\n"
"    printf(\"%f %d\", a, b);\n"
"    output[0] = 'P'; \n"
"    output[1] = 'O'; \n"
"    output[2] = 'N'; \n"
"    output[3] = 'G'; \n"
"    output[4] = '\\0'; \n"
"}\n";

int
main(void)
{
    const int OUTPUT_SIZE = 5;
    const char *input = "PING\0";
    char output[OUTPUT_SIZE];
    float a = 23456.0f;
    int b = 2000001;

    try {
        std::vector<cl::Platform> platformList;

        // Pick platform
        cl::Platform::get(&platformList);

        // Pick first platform
        cl_context_properties cprops[] = {
            CL_CONTEXT_PLATFORM, (cl_context_properties)(platformList[0])(), 0};
        cl::Context context(CL_DEVICE_TYPE_GPU, cprops);

        // Query the set of devices attched to the context
        std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();

        assert (devices.size() == 1);

        cl::Device device = devices.at(0);

        assert (device.getInfo<CL_DEVICE_NAME>() == "ttasim");

        a = poclu_bswap_cl_float (device(), a);
        b = poclu_bswap_cl_int (device(), b);

        // Create and program from source
        cl::Program::Sources sources(1, std::make_pair(kernelSourceCode, 0));
        cl::Program program(context, sources);

        // Build program
        program.build(devices);

        cl::Buffer inputBuffer = cl::Buffer(
            context,
            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
            strlen (input), (void *) &input[0]);

        // Create buffer for that uses the host ptr C
        cl::Buffer outputBuffer = cl::Buffer(
            context,
            CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
            OUTPUT_SIZE, (void *) &output[0]);

        // Create kernel object
        cl::Kernel kernel(program, "test_kernel");

        // Set kernel args
        kernel.setArg(0, inputBuffer);
        kernel.setArg(1, outputBuffer);
        kernel.setArg(2, a);
        kernel.setArg(3, b);

        // Create command queue
        cl::CommandQueue queue(context, devices[0], CL_QUEUE_PROFILING_ENABLE);

        cl::Event enqEvent;

        // Do the work
        queue.enqueueNDRangeKernel(
            kernel,
            cl::NullRange,
            cl::NDRange(1),
            cl::NullRange,
            NULL, &enqEvent);

        cl::Event mapEvent;
        (int *) queue.enqueueMapBuffer(
            outputBuffer,
            CL_TRUE, // block
            CL_MAP_READ,
            0, OUTPUT_SIZE, NULL, &mapEvent);

        if (std::string(output) == "PONG")
            std::cout << "OK\n";
        else
            std::cerr << "FAIL, received: " << output << "\n";

        cl::Event unmapEvent;
        // Finally release our hold on accessing the memory
        queue.enqueueUnmapMemObject(
            outputBuffer,
            (void *) &output[0],
            NULL,
            &unmapEvent);

        queue.finish();

        assert (enqEvent.getInfo<CL_EVENT_COMMAND_EXECUTION_STATUS>() == CL_COMPLETE);
        assert (mapEvent.getInfo<CL_EVENT_COMMAND_EXECUTION_STATUS>() == CL_COMPLETE);
        assert (unmapEvent.getInfo<CL_EVENT_COMMAND_EXECUTION_STATUS>() == CL_COMPLETE);

        assert (
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_QUEUED>() <=
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>());

        assert (
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>() <=
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>());

        assert (
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>() <
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>());

#if 0
        std::cerr << "exec time: "
                  << enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>() -
            enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>() << std::endl;
#endif

        assert (
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_QUEUED>() <=
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>());

        assert (
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>() <=
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>());

        assert (
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>() <=
            mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>());

        assert (
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_QUEUED>() <=
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>());

        assert (
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>() <=
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>());

        assert (
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_START>() <=
            unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>());

        assert (enqEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>() <=
                mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>());

        assert (mapEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>() <=
                unmapEvent.getProfilingInfo<CL_PROFILING_COMMAND_END>());

    }
    catch (cl::Error err) {
         std::cerr
             << "ERROR: "
             << err.what()
             << "("
             << err.err()
             << ")"
             << std::endl;

         return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 WiFiUdp.cpp - Adaptation of Arduino WiFi library for Energia and CC3200 launchpad
 Author: Noah Luskey | LuskeyNoah@gmail.com

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

extern "C" {
    #include "utility/SimpleLink.h"
    #include "utility/socket.h"
    #include "utility/wl_definitions.h"
}

#include <string.h>

#include "WiFi.h"
#include "WiFiUdp.h"

//--tested, working--//
WiFiUDP::WiFiUDP()
{
    //
    //fill the buffers with zeroes
    //
    memset(rx_buf, 0, UDP_RX_PACKET_MAX_SIZE);
    memset(tx_buf, 0, UDP_TX_PACKET_MAX_SIZE);
    rx_currentIndex = 0;
    rx_fillLevel = 0;
    tx_fillLevel = 0;
    _remotePort = 0;
    _remoteIP = 0;
    _socketIndex = NO_SOCKET_AVAIL;
}

//--tested, working--//
uint8_t WiFiUDP::begin(uint16_t port)
{

    //
    //get a socket from the WiFiClass (convoluted method from the arduino library)
    //
    int socketIndex = WiFiClass::getSocket();
    if (socketIndex == NO_SOCKET_AVAIL) {
        return 0;
    }

    //
    //get a socket handle from the simplelink api and make sure it's valid
    //
    int socketHandle = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, IPPROTO_UDP);
    if (socketHandle < 0) {
        return 0;
    }

    //
    //bind the socket to the requested port and check for success
    //if failure, gracefully close the socket and return
    //
    SlSockAddrIn_t portAddress;
    portAddress.sin_family = SL_AF_INET;
    portAddress.sin_port = sl_Htons(port);
    portAddress.sin_addr.s_addr = 0;
    int iRet = sl_Bind(socketHandle, (SlSockAddr_t*)&portAddress, sizeof(portAddress));
    if (iRet < 0) {
        sl_Close(socketHandle);
        return 0;
    }

    //
    //now that simplelink api calls are done, set the object's variables
    //
    _socketIndex = socketIndex;
    WiFiClass::_handleArray[socketIndex] = socketHandle;
    WiFiClass::_portArray[socketIndex] = port;
    WiFiClass::_typeArray[socketIndex] = TYPE_UDP_PORT;
    return 1;
}

//--tested, working--//
int WiFiUDP::available()
{
    //
    //returns to number of bytes left to read in the current packet
    //bytesLeft should never be negative... but just in case it's restricted positive
    //
    int bytesLeft = rx_fillLevel - rx_currentIndex;
    if (bytesLeft < 0) {
        return 0;
    } else {
        return bytesLeft;
    }
}

void WiFiUDP::stop()
{
    //
    //only do the rest of this function if a socket actually exists
    //
    if (_socketIndex == NO_SOCKET_AVAIL) {
        return;
    }

    //
    //close the socket and reset any important variables
    //
    flush();
    sl_Close(WiFiClass::_handleArray[_socketIndex]);
    WiFiClass::_handleArray[_socketIndex] = -1;
    WiFiClass::_portArray[_socketIndex] = -1;
    WiFiClass::_typeArray[_socketIndex] = -1;
    _socketIndex = NO_SOCKET_AVAIL;
}

//--tested, working--//
int WiFiUDP::beginPacket(const char *host, uint16_t port)
{
    //
    //look up host's IP address
    //
    IPAddress ip;
    int success = WiFi.hostByName((char*)host, ip);

    //
    //if host successfully resolved to IP, begin packet to that IP
    //
    if (success) {
        return beginPacket(ip, port);
    } else {
        return 0;
    }
}

//--tested, working--//
//!!sending packets causes problems occasionally. Odd null pointer bugs!!//
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port)
{
    //
    //make sure a port has been created
    //!! this doesn't create a port if one doesn't exist. Is that ok?
    //
    if (_socketIndex == NO_SOCKET_AVAIL) {
        return 0;
    }

    //
    //store the address information for when endPacket is called
    //
    _sendIP = ip;
    _sendPort = port;

    //
    //reset all tx buffer indicators
    //
    memset(tx_buf, 0, UDP_TX_PACKET_MAX_SIZE);
    rx_currentIndex = 0;
    tx_fillLevel = 0;

    return 1;

}

//--tested, working--//
//!!sending packets causes problems occasionally. Odd null pointer bugs!!//
int WiFiUDP::endPacket()
{
    //
    //only do the rest of this function if a socket actually exists
    //
    if (_socketIndex == NO_SOCKET_AVAIL) {
        return 0;
    }

    //
    //fill in the address structure
    //
    SlSockAddrIn_t sendAddress;
    memset(&sendAddress, 0, sizeof(SlSockAddrIn_t));
    sendAddress.sin_family = SL_AF_INET;
    sendAddress.sin_port = sl_Htons(_sendPort);
    sendAddress.sin_addr.s_addr = _sendIP;

    //
    //use the simplelink library to send the tx buffer
    //
    int socketHandle = WiFiClass::_handleArray[_socketIndex];
    int iRet = sl_SendTo(socketHandle, tx_buf, tx_fillLevel, NULL, (SlSockAddr_t*)&sendAddress, sizeof(SlSockAddrIn_t));
    if (iRet < 0) {
        return 0;
    }

    //
    //reset all tx buffer indicators
    //
    memset(tx_buf, 0, UDP_TX_PACKET_MAX_SIZE);
    tx_fillLevel = 0;
    return 1;
}

//--tested, working--//
//!!sending packets causes problems occasionally. Odd null pointer bugs!!//
size_t WiFiUDP::write(char *buffer) {
    //
    //this function assumes a well formatted string (char array) has been passed in
    //
    return write((uint8_t*)buffer, strlen(buffer));

}

//--tested, working--//
//!!sending packets causes problems occasionally. Odd null pointer bugs!!//
size_t WiFiUDP::write(uint8_t byte)
{
    //
    //write a single byte into the buffer using overloaded method
    //
    return write(&byte, 1);
}

//--tested, working--//
//!!sending packets causes problems occasionally. Odd null pointer bugs!!//
size_t WiFiUDP::write(uint8_t *buffer, size_t size)
{
    //
    //it's possible that size is more than can fit in the tx_buffer
    //so check it and make it smaller if necessary
    //
    if (tx_fillLevel + size > UDP_TX_PACKET_MAX_SIZE) {
        size = UDP_TX_PACKET_MAX_SIZE - tx_fillLevel;
    }

    //
    //copy the appropriate number of bytes into the buffer
    //
    memcpy(&tx_buf[tx_fillLevel], buffer, size);
    tx_fillLevel += size;
    return size;
}

//
//--tested, working--//
//bit of a misnomer. This waits to receive a packet and then stores it in a buffer
//it is important that this is called before any of the read or available commands
//are called. This does the actual work. Read, peek, etc. are just organizational.
//
int WiFiUDP::parsePacket()
{
    //
    //make sure we actually have a socket
    //
    if (_socketIndex == NO_SOCKET_AVAIL) {
        return 0;
    }

    //
    //the sl_select command blocks until something interesting happens or
    //it times out (current timeout set for 10 ms, the minimum)
    //
    SlTimeval_t timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 10000;

    int socketHandle = WiFiClass::_handleArray[_socketIndex];

    SlFdSet_t readSocketHandles, errorSocketHandles;
    SL_FD_ZERO(&readSocketHandles);
    SL_FD_ZERO(&errorSocketHandles);
    SL_FD_SET(socketHandle, &readSocketHandles);
    SL_FD_SET(socketHandle, &errorSocketHandles);

    int iRet = sl_Select(socketHandle+1, &readSocketHandles, NULL, &errorSocketHandles, &timeout);
    if (iRet <= 0) {
        return 0;
    }

    //
    //Since we've reached this point, the sl_select command has indicated
    //that either we're going to get an error, or an immediate read
    //
    SlSockAddrIn_t  address;
    int AddrSize = sizeof(address);
    int bytes = sl_RecvFrom(socketHandle, rx_buf, UDP_RX_PACKET_MAX_SIZE, NULL, (SlSockAddr_t*)&address, (SlSocklen_t*)&AddrSize);

    //
    //store the sender's address (sl_HtonX reorders bits to processor order)
    //!! Although this follows some examples (upd_socket), it goes agains the
    //!! API documentation. The API maintains that the 5th arg to RecvFrom is not in/out
    //
    _remoteIP = sl_Htonl(address.sin_addr.s_addr);
    _remotePort = sl_Htons(address.sin_port);

    //
    //If an error occured, return 0, otherwise return the byte length of the packet
    //and reset the buffer index counter and fill level variables
    //
    if (bytes < 0) {
        rx_fillLevel = 0;
        return 0;
    } else {
        rx_currentIndex = 0;
        rx_fillLevel = bytes;
        return bytes;
    }
}

//--tested, working--//
int WiFiUDP::read()
{
    //
    //don't read past the available data in the buffer
    //
    if (rx_currentIndex >= rx_fillLevel) {
        return 0;
    }

    //
    //return the byte at the current index and increment that index
    //
    return rx_buf[rx_currentIndex++];
}

int WiFiUDP::read(unsigned char* buffer, size_t len)
{
    //
    //copy the requested number of bytes up to the length of the packet
    //
    int bytesCopied = 0;
    while ( (bytesCopied <= len) && (rx_currentIndex < rx_fillLevel) ) {
        buffer[bytesCopied] = rx_buf[rx_currentIndex];
        bytesCopied++;
        rx_currentIndex++;
    }

    return bytesCopied;
}

//--tested, working--//
int WiFiUDP::peek()
{
    //
    //return the next byte without incrementing the index counter
    //
    return rx_buf[rx_currentIndex];
}

//--tested, working--//
void WiFiUDP::flush()
{
    //
    //destroy the remaining data in the buffer and reset index and length variables
    //
    memset(rx_buf, 0, UDP_RX_PACKET_MAX_SIZE);
    rx_currentIndex = 0;
    rx_fillLevel = 0;
}

IPAddress  WiFiUDP::remoteIP()
{
    //
    //this value is maintained by ParsePacket method
    //
    return _remoteIP;
}

uint16_t  WiFiUDP::remotePort()
{
    //
    //this value is maintained by ParsePacket method
    //
    return _remotePort;
}

<commit_msg>Complete sync of all changes<commit_after>/*
 WiFiUdp.cpp - Adaptation of Arduino WiFi library for Energia and CC3200 launchpad
 Author: Noah Luskey | LuskeyNoah@gmail.com

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

extern "C" {
    #include "utility/SimpleLink.h"
    #include "utility/socket.h"
    #include "utility/wl_definitions.h"
}

#include <string.h>

#include "WiFi.h"
#include "WiFiUdp.h"

//--tested, working--//
WiFiUDP::WiFiUDP()
{
    //
    //fill the buffers with zeroes
    //
    memset(rx_buf, 0, UDP_RX_PACKET_MAX_SIZE);
    memset(tx_buf, 0, UDP_TX_PACKET_MAX_SIZE);
    rx_currentIndex = 0;
    rx_fillLevel = 0;
    tx_fillLevel = 0;
    _remotePort = 0;
    _remoteIP = 0;
    _socketIndex = NO_SOCKET_AVAIL;
}

//--tested, working--//
uint8_t WiFiUDP::begin(uint16_t port)
{

    //
    //get a socket from the WiFiClass (convoluted method from the arduino library)
    //
    int socketIndex = WiFiClass::getSocket();
    if (socketIndex == NO_SOCKET_AVAIL) {
        return 0;
    }

    //
    //get a socket handle from the simplelink api and make sure it's valid
    //
    int socketHandle = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, IPPROTO_UDP);
    if (socketHandle < 0) {
        return 0;
    }

    //
    //bind the socket to the requested port and check for success
    //if failure, gracefully close the socket and return
    //
    SlSockAddrIn_t portAddress;
    portAddress.sin_family = SL_AF_INET;
    portAddress.sin_port = sl_Htons(port);
    portAddress.sin_addr.s_addr = 0;
    int iRet = sl_Bind(socketHandle, (SlSockAddr_t*)&portAddress, sizeof(portAddress));
    if (iRet < 0) {
        sl_Close(socketHandle);
        return 0;
    }

    //
    //now that simplelink api calls are done, set the object's variables
    //
    _socketIndex = socketIndex;
    WiFiClass::_handleArray[socketIndex] = socketHandle;
    WiFiClass::_portArray[socketIndex] = port;
    WiFiClass::_typeArray[socketIndex] = TYPE_UDP_PORT;
    return 1;
}

//--tested, working--//
int WiFiUDP::available()
{
    //
    //returns to number of bytes left to read in the current packet
    //bytesLeft should never be negative... but just in case it's restricted positive
    //
    int bytesLeft = rx_fillLevel - rx_currentIndex;
    if (bytesLeft < 0) {
        return 0;
    } else {
        return bytesLeft;
    }
}

void WiFiUDP::stop()
{
    //
    //only do the rest of this function if a socket actually exists
    //
    if (_socketIndex == NO_SOCKET_AVAIL) {
        return;
    }

    //
    //close the socket and reset any important variables
    //
    flush();
    sl_Close(WiFiClass::_handleArray[_socketIndex]);
    WiFiClass::_handleArray[_socketIndex] = -1;
    WiFiClass::_portArray[_socketIndex] = -1;
    WiFiClass::_typeArray[_socketIndex] = -1;
    _socketIndex = NO_SOCKET_AVAIL;
}

//--tested, working--//
int WiFiUDP::beginPacket(const char *host, uint16_t port)
{
    //
    //look up host's IP address
    //
    IPAddress ip;
    int success = WiFi.hostByName((char*)host, ip);

    //
    //if host successfully resolved to IP, begin packet to that IP
    //
    if (success) {
        return beginPacket(ip, port);
    } else {
        return 0;
    }
}

//--tested, working--//
//!!sending packets causes problems occasionally. Odd null pointer bugs!!//
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port)
{
    //
    //make sure a port has been created
    //!! this doesn't create a port if one doesn't exist. Is that ok?
    //
    if (_socketIndex == NO_SOCKET_AVAIL) {
        return 0;
    }

    //
    //store the address information for when endPacket is called
    //
    _sendIP = ip;
    _sendPort = port;

    //
    //reset all tx buffer indicators
    //
    memset(tx_buf, 0, UDP_TX_PACKET_MAX_SIZE);
    rx_currentIndex = 0;
    tx_fillLevel = 0;

    return 1;

}

//--tested, working--//
//!!sending packets causes problems occasionally. Odd null pointer bugs!!//
int WiFiUDP::endPacket()
{
    //
    //only do the rest of this function if a socket actually exists
    //
    if (_socketIndex == NO_SOCKET_AVAIL) {
        return 0;
    }

    //
    //fill in the address structure
    //
    SlSockAddrIn_t sendAddress;
    memset(&sendAddress, 0, sizeof(SlSockAddrIn_t));
    sendAddress.sin_family = SL_AF_INET;
    sendAddress.sin_port = sl_Htons(_sendPort);
    sendAddress.sin_addr.s_addr = _sendIP;

    //
    //use the simplelink library to send the tx buffer
    //
    int socketHandle = WiFiClass::_handleArray[_socketIndex];
    int iRet = sl_SendTo(socketHandle, tx_buf, tx_fillLevel, NULL, (SlSockAddr_t*)&sendAddress, sizeof(SlSockAddrIn_t));
    if (iRet < 0) {
        return 0;
    }

    //
    //reset all tx buffer indicators
    //
    memset(tx_buf, 0, UDP_TX_PACKET_MAX_SIZE);
    tx_fillLevel = 0;
    return 1;
}

//--tested, working--//
//!!sending packets causes problems occasionally. Odd null pointer bugs!!//
size_t WiFiUDP::write(char *buffer) {
    //
    //this function assumes a well formatted string (char array) has been passed in
    //
    return write((uint8_t*)buffer, strlen(buffer));

}

//--tested, working--//
//!!sending packets causes problems occasionally. Odd null pointer bugs!!//
size_t WiFiUDP::write(uint8_t byte)
{
    //
    //write a single byte into the buffer using overloaded method
    //
    return write(&byte, 1);
}

//--tested, working--//
//!!sending packets causes problems occasionally. Odd null pointer bugs!!//
size_t WiFiUDP::write(uint8_t *buffer, size_t size)
{
    //
    //it's possible that size is more than can fit in the tx_buffer
    //so check it and make it smaller if necessary
    //
    if (tx_fillLevel + size > UDP_TX_PACKET_MAX_SIZE) {
        size = UDP_TX_PACKET_MAX_SIZE - tx_fillLevel;
    }

    //
    //copy the appropriate number of bytes into the buffer
    //
    memcpy(&tx_buf[tx_fillLevel], buffer, size);
    tx_fillLevel += size;
    return size;
}

//
//--tested, working--//
//bit of a misnomer. This waits to receive a packet and then stores it in a buffer
//it is important that this is called before any of the read or available commands
//are called. This does the actual work. Read, peek, etc. are just organizational.
//
int WiFiUDP::parsePacket()
{
    //
    //make sure we actually have a socket
    //
    if (_socketIndex == NO_SOCKET_AVAIL) {
        return 0;
    }

    //
    //the sl_select command blocks until something interesting happens or
    //it times out (current timeout set for 10 ms, the minimum)
    //
    SlTimeval_t timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 10000;

    int socketHandle = WiFiClass::_handleArray[_socketIndex];

    SlFdSet_t readSocketHandles, errorSocketHandles;
    SL_FD_ZERO(&readSocketHandles);
    SL_FD_ZERO(&errorSocketHandles);
    SL_FD_SET(socketHandle, &readSocketHandles);
    SL_FD_SET(socketHandle, &errorSocketHandles);

    int iRet = sl_Select(socketHandle+1, &readSocketHandles, NULL, &errorSocketHandles, &timeout);
    if (iRet <= 0) {
        return 0;
    }

    //
    //Since we've reached this point, the sl_select command has indicated
    //that either we're going to get an error, or an immediate read
    //
    SlSockAddrIn_t  address = {0};
    int AddrSize = sizeof(address);
    int bytes = sl_RecvFrom(socketHandle, rx_buf, UDP_RX_PACKET_MAX_SIZE, NULL, (SlSockAddr_t*)&address, (SlSocklen_t*)&AddrSize);

    //
    //store the sender's address (sl_HtonX reorders bits to processor order)
    //!! Although this follows some examples (upd_socket), it goes agains the
    //!! API documentation. The API maintains that the 5th arg to RecvFrom is not in/out
    //
    _remoteIP = address.sin_addr.s_addr;
    _remotePort = sl_Htons(address.sin_port);

    //
    //If an error occured, return 0, otherwise return the byte length of the packet
    //and reset the buffer index counter and fill level variables
    //
    if (bytes < 0) {
        rx_fillLevel = 0;
        return 0;
    } else {
        rx_currentIndex = 0;
        rx_fillLevel = bytes;
        return bytes;
    }
}

//--tested, working--//
int WiFiUDP::read()
{
    //
    //don't read past the available data in the buffer
    //
    if (rx_currentIndex >= rx_fillLevel) {
        return 0;
    }

    //
    //return the byte at the current index and increment that index
    //
    return rx_buf[rx_currentIndex++];
}

int WiFiUDP::read(unsigned char* buffer, size_t len)
{
    //
    //copy the requested number of bytes up to the length of the packet
    //
    int bytesCopied = 0;
    while ( (bytesCopied <= len) && (rx_currentIndex < rx_fillLevel) ) {
        buffer[bytesCopied] = rx_buf[rx_currentIndex];
        bytesCopied++;
        rx_currentIndex++;
    }

    return bytesCopied;
}

//--tested, working--//
int WiFiUDP::peek()
{
    //
    //return the next byte without incrementing the index counter
    //
    return rx_buf[rx_currentIndex];
}

//--tested, working--//
void WiFiUDP::flush()
{
    //
    //destroy the remaining data in the buffer and reset index and length variables
    //
    memset(rx_buf, 0, UDP_RX_PACKET_MAX_SIZE);
    rx_currentIndex = 0;
    rx_fillLevel = 0;
}

IPAddress  WiFiUDP::remoteIP()
{
    //
    //this value is maintained by ParsePacket method
    //
    IPAddress retIP;
    retIP = _remoteIP;
    return retIP;
}

uint16_t  WiFiUDP::remotePort()
{
    //
    //this value is maintained by ParsePacket method
    //
    uint16_t retPort = _remotePort;
    return retPort;
}

<|endoftext|>


<commit_before>#ifndef MAP_THREAD_SAFE
#define MAP_THREAD_SAFE

#include <map>
#include <thread>
#include <mutex>
#include <shared_mutex>

namespace std
{
    namespace threadsafe
    {
        /*
        Concurrent Map prototype, it allows concurrent reads and safe writes.

        */
        template<class K,class V>
        class map
        {
            std::map<K,V> internal_map;

            std::shared_mutex mutex;

            public:
                map(){}
                map(const std::map<K,V> &m) : internal_map(m){}
                map(const std::threadsafe::map &m) = delete;

                V get(const K& key)
                {
                    std::shared_lock<std::shared_mutex> lock(mutex);
                    auto it = internal_map.find(key);
                    if (it == internal_map.end())
                    {
                        return nullptr;
                    }
                    else{
                        return V(it->second);
                    }
                }

                bool insert(const K & key,V & value){
                    std::unique_lock<std::shared_mutex> lock(mutex);
                    return internal_map.insert(std::make_pair(key,value)).second;
                }

                size_t erase(const K & key){
                    std::unique_lock<std::shared_mutex> lock(mutex);
                    return internal_map.erase(key);
                }

                size_t size(){
                    std::shared_lock<std::shared_mutex> lock(mutex);
                    return internal_map.size();
                }

                bool contains(const K& key){
                    std::shared_lock<std::shared_mutex> lock(mutex);
                    auto it = internal_map.find(key);
                    return it == internal_map.end();
                }

                V putIfAbsent(const K& key,const V& value){
			std::unique_lock<std::shared_mutex> lock(mutex);
			auto it = internal_map.find(key);
			if (it == internal_map.end()){
				internal_map.insert(std::make_pair(key,value));
				return value;
			}
			else
				return it->second;
		}

		bool remove(const K& key,const V& value){
			std::unique_lock<std::shared_mutex> lock(mutex);
			auto it = internal_map.find(key);
			if (it == internal_map.end() || it->second != value)
				return false
			else
			{
				internal_map.erase(it);
				return true;
			}
		}

		bool replace(const K& key,const V& value,V &output){
			std::unique_lock<std::shared_mutex> lock(mutex);

			auto it = internal_map.find(key);
			if (it != internal_map.end()){
				output = it-> second;
				it->second = value;
				return true;
			}
			return false;
		}
        };
    }
}

#endif
<commit_msg>Implemented method replace only if old value in map<commit_after>#ifndef MAP_THREAD_SAFE
#define MAP_THREAD_SAFE

#include <map>
#include <thread>
#include <mutex>
#include <shared_mutex>

namespace std
{
    namespace threadsafe
    {
        /*
        Concurrent Map prototype, it allows concurrent reads and safe writes.

        */
        template<class K,class V>
        class map
        {
            std::map<K,V> internal_map;

            std::shared_mutex mutex;

            public:
                map(){}
                map(const std::map<K,V> &m) : internal_map(m){}
                map(const std::threadsafe::map &m) = delete;

                V get(const K& key)
                {
                    std::shared_lock<std::shared_mutex> lock(mutex);
                    auto it = internal_map.find(key);
                    if (it == internal_map.end())
                    {
                        return nullptr;
                    }
                    else{
                        return V(it->second);
                    }
                }

                bool insert(const K & key,V & value){
                    std::unique_lock<std::shared_mutex> lock(mutex);
                    return internal_map.insert(std::make_pair(key,value)).second;
                }

                size_t erase(const K & key){
                    std::unique_lock<std::shared_mutex> lock(mutex);
                    return internal_map.erase(key);
                }

                size_t size(){
                    std::shared_lock<std::shared_mutex> lock(mutex);
                    return internal_map.size();
                }

                bool contains(const K& key){
                    std::shared_lock<std::shared_mutex> lock(mutex);
                    auto it = internal_map.find(key);
                    return it == internal_map.end();
                }

                V putIfAbsent(const K& key,const V& value){
			std::unique_lock<std::shared_mutex> lock(mutex);
			auto it = internal_map.find(key);
			if (it == internal_map.end()){
				internal_map.insert(std::make_pair(key,value));
				return value;
			}
			else
				return it->second;
		}

		bool remove(const K& key,const V& value){
			std::unique_lock<std::shared_mutex> lock(mutex);
			auto it = internal_map.find(key);
			if (it == internal_map.end() || it->second != value)
				return false
			else
			{
				internal_map.erase(it);
				return true;
			}
		}

		bool replace(const K& key,const V& value){
			std::unique_lock<std::shared_mutex> lock(mutex);

			auto it = internal_map.find(key);
			if (it != internal_map.end()){
				it->second = value;
				return true;
			}
			return false;
		}

		bool replace(const K& key,V& oldValue,V& newValue){
			std::unique_lock<std::shared_mutex> lock(mutex);

			auto it = internal_map.find(key);
			if (it != internal_map.end() && it->second == oldValue){
				it->second = newValue;
				return true;
			}
			return false;
		}
        };
    }
}

#endif
<|endoftext|>


<commit_before>#ifndef LIBTEN_HTTP_SERVER_HH
#define LIBTEN_HTTP_SERVER_HH

#include <fnmatch.h>
#include <boost/algorithm/string/predicate.hpp>
#include <chrono>
#include <functional>
#include <netinet/tcp.h>

#include "ten/buffer.hh"
#include "ten/logging.hh"
#include "ten/task.hh"
#include "ten/net.hh"
#include "ten/http/http_message.hh"
#include "ten/uri.hh"

namespace ten {

//! basic http server
class http_server : public netsock_server {
public:
    //! wrapper around an http request/response
    struct request {
        request(http_request &req_, netsock &sock_)
            : req(req_), resp(404), sock(sock_),
            start(std::chrono::steady_clock::now()),
            resp_sent(false) {}

        //! compose a uri from the request uri
        uri get_uri(std::string host="") {
            if (host.empty()) {
                host = req.get("Host");
                // TODO: transform to preserve passed in host
                if (boost::starts_with(req.uri, "http://")) {
                    return req.uri;
                }
            }

            if (host.empty()) {
                // just make up a host
                host = "localhost";
            }
            uri tmp;
            tmp.host = host;
            tmp.scheme = "http";
            tmp.path = req.uri.c_str();
            return tmp.compose();
        }

        //! send response to this request
        ssize_t send_response() {
            if (resp_sent) return 0;
            resp_sent = true;
            std::string data;
            // TODO: Content-Length might be another good one to add here
            // but only if Transfer-Encoding isn't chunked?
            // HTTP/1.1 requires Date, so lets add it
            if (resp.get("Date").empty()) {
                char buf[128];
                struct tm tm;
                time_t now = std::chrono::system_clock::to_time_t(procnow());
                strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S GMT", gmtime_r(&now, &tm));
                resp.set("Date", buf);
            }
            std::string conn = req.get("Connection");
            if (!conn.empty() && resp.get("Connection").empty()) {
                // obey clients wishes if we have none of our own
                resp.set("Connection", conn);
            }
            if (req.http_version == "HTTP/1.0" && req.get("Connection").empty()) {
                resp.set("Connection", "close");
            }

            data = resp.data();
            if (!resp.body.empty() && req.method != "HEAD") {
                data += resp.body;
            }
            ssize_t nw = sock.send(data.data(), data.size());
            return nw;
        }

        //! the ip of the host making the request
        //! might use the X-Forwarded-For header
        std::string agent_ip(bool use_xff=false) const {
            if (use_xff) {
                std::string xffs = req.get("X-Forwarded-For");
                const char *xff = xffs.c_str();
                if (xff) {
                    // pick the first addr
                    int i;
                    for (i=0; *xff && i<256 && !isdigit((unsigned char)*xff); i++, xff++) {}
                    if (*xff && i < 256) {
                        // now, find the end
                        const char *e = xff;
                        for (i = 0; *e && i<256 && (isdigit((unsigned char)*e) || *e == '.'); i++, e++) {}
                        if (i < 256 && e >= xff + 7 ) {
                            return std::string(xff, e - xff);
                        }
                    }
                }
            }
            address addr;
            if (sock.getpeername(addr)) {
                char buf[INET6_ADDRSTRLEN];
                if (addr.ntop(buf, sizeof(buf))) {
                    return buf;
                }
            }
            return "";
        }

        ~request() {
            if (!resp_sent) {
                // ensure a response is sent
                resp = http_response(404, Headers("Content-Length", 0));
                send_response();
            }

            if (resp.get("Connection") == "close") {
                sock.close();
            }
        }

        http_request &req;
        http_response resp;
        netsock &sock;
        std::chrono::high_resolution_clock::time_point start;
        bool resp_sent;
    };

    typedef std::function<void (request &)> callback_type;
    struct route {
        std::string pattern;
        callback_type callback;
        int fnmatch_flags;

        route(const std::string &pattern_,
                const callback_type &callback_,
                int fnmatch_flags_=0)
            : pattern(pattern_), callback(callback_), fnmatch_flags(fnmatch_flags_) {}
    };

public:
    http_server(size_t stacksize_=default_stacksize, unsigned timeout_ms_=0)
        : netsock_server("http", stacksize_, timeout_ms_),
        _routes(std::make_shared<std::vector<route> >())
    {
    }

    //! add a callback for a uri with an fnmatch pattern
    void add_route(const std::string &pattern,
            const callback_type &callback,
            int fnmatch_flags = 0)
    {
      _routes->push_back(route(pattern, callback, fnmatch_flags));
    }

    //! set logging function, called after every request
    void set_log_callback(const callback_type &f) {
        _log_func = f;
    }

private:
    std::shared_ptr<std::vector<route> > _routes;
    callback_type _log_func;

    void on_shutdown() {
        // release any memory held by bound callbacks
        // this shared ptr madness is for threaded shutdown
        auto rr = _routes;
        rr->clear();
    }

    void on_connection(netsock &s) {
        // TODO: tuneable buffer sizes
        buffer buf(4*1024);
        http_parser parser;

        // TODO: might want to enable this later after
        // we know this will be a long-lived connection
        // otherwise the overhead of the syscall hurts concurrency
        //s.s.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1);

        http_request req;
        for (;;) {
            req.parser_init(&parser);
            bool got_headers = false;
            for (;;) {
                buf.reserve(4*1024);
                ssize_t nr = -1;
                if (buf.size() == 0) {
                    nr = s.recv(buf.back(), buf.available(), timeout_ms);
                    if (nr < 0) return;
                    buf.commit(nr);
                }
                size_t nparse = buf.size();
                req.parse(&parser, buf.front(), nparse);
                buf.remove(nparse);
                if (req.complete) {
                    // handle request
                    handle_request(req, s);
                    break;
                }
                if (nr == 0) return;
                if (!got_headers && !req.method.empty()) {
                    got_headers = true;
                    if (req.get("Expect") == "100-continue") {
                        http_response cont_resp(100);
                        std::string data = cont_resp.data();
                        ssize_t nw = s.send(data.data(), data.size());
                        (void)nw;
                    }
                }
            }
        }
    }

    void handle_request(http_request &req, netsock &s) {
        request r(req, s);
        std::string path = req.path();
        DVLOG(5) << "path: " << path;
        // not super efficient, but good enough
        for (auto i= _routes->cbegin(); i!= _routes->cend(); i++) {
            DVLOG(5) << "matching pattern: " << i->pattern;
            if (fnmatch(i->pattern.c_str(), path.c_str(), i->fnmatch_flags) == 0) {
                try {
                    i->callback(r);
                } catch (std::exception &e) {
                    DVLOG(2) << "unhandled exception in route [" << i->pattern << "]: " << e.what();
                    r.resp = http_response(500,
                            Headers("Connection", "close"));
                    std::string msg = e.what();
                    msg += "\n";
                    r.resp.set_body(msg);
                    r.send_response();
                }
                break;
            }
        }
        if (_log_func) {
            _log_func(r);
        }
    }
};

} // end namespace ten

#endif // LIBTEN_HTTP_SERVER_HH
<commit_msg>watchers for connect/disconnect events<commit_after>#ifndef LIBTEN_HTTP_SERVER_HH
#define LIBTEN_HTTP_SERVER_HH

#include <fnmatch.h>
#include <boost/algorithm/string/predicate.hpp>
#include <chrono>
#include <functional>
#include <netinet/tcp.h>

#include "ten/buffer.hh"
#include "ten/logging.hh"
#include "ten/task.hh"
#include "ten/net.hh"
#include "ten/http/http_message.hh"
#include "ten/uri.hh"

namespace ten {

//! basic http server
class http_server : public netsock_server {
public:
    //! wrapper around an http request/response
    struct request {
        request(http_request &req_, netsock &sock_)
            : req(req_), resp(404), sock(sock_),
            start(std::chrono::steady_clock::now()),
            resp_sent(false) {}

        //! compose a uri from the request uri
        uri get_uri(std::string host="") {
            if (host.empty()) {
                host = req.get("Host");
                // TODO: transform to preserve passed in host
                if (boost::starts_with(req.uri, "http://")) {
                    return req.uri;
                }
            }

            if (host.empty()) {
                // just make up a host
                host = "localhost";
            }
            uri tmp;
            tmp.host = host;
            tmp.scheme = "http";
            tmp.path = req.uri.c_str();
            return tmp.compose();
        }

        //! send response to this request
        ssize_t send_response() {
            if (resp_sent) return 0;
            resp_sent = true;
            std::string data;
            // TODO: Content-Length might be another good one to add here
            // but only if Transfer-Encoding isn't chunked?
            // HTTP/1.1 requires Date, so lets add it
            if (resp.get("Date").empty()) {
                char buf[128];
                struct tm tm;
                time_t now = std::chrono::system_clock::to_time_t(procnow());
                strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S GMT", gmtime_r(&now, &tm));
                resp.set("Date", buf);
            }
            std::string conn = req.get("Connection");
            if (!conn.empty() && resp.get("Connection").empty()) {
                // obey clients wishes if we have none of our own
                resp.set("Connection", conn);
            }
            if (req.http_version == "HTTP/1.0" && req.get("Connection").empty()) {
                resp.set("Connection", "close");
            }

            data = resp.data();
            if (!resp.body.empty() && req.method != "HEAD") {
                data += resp.body;
            }
            ssize_t nw = sock.send(data.data(), data.size());
            return nw;
        }

        //! the ip of the host making the request
        //! might use the X-Forwarded-For header
        std::string agent_ip(bool use_xff=false) const {
            if (use_xff) {
                std::string xffs = req.get("X-Forwarded-For");
                const char *xff = xffs.c_str();
                if (xff) {
                    // pick the first addr
                    int i;
                    for (i=0; *xff && i<256 && !isdigit((unsigned char)*xff); i++, xff++) {}
                    if (*xff && i < 256) {
                        // now, find the end
                        const char *e = xff;
                        for (i = 0; *e && i<256 && (isdigit((unsigned char)*e) || *e == '.'); i++, e++) {}
                        if (i < 256 && e >= xff + 7 ) {
                            return std::string(xff, e - xff);
                        }
                    }
                }
            }
            address addr;
            if (sock.getpeername(addr)) {
                char buf[INET6_ADDRSTRLEN];
                if (addr.ntop(buf, sizeof(buf))) {
                    return buf;
                }
            }
            return "";
        }

        ~request() {
            if (!resp_sent) {
                // ensure a response is sent
                resp = http_response(404, Headers("Content-Length", 0));
                send_response();
            }

            if (resp.get("Connection") == "close") {
                sock.close();
            }
        }

        http_request &req;
        http_response resp;
        netsock &sock;
        std::chrono::high_resolution_clock::time_point start;
        bool resp_sent;
    };

    typedef std::function<void (request &)> callback_type;
    struct route {
        std::string pattern;
        callback_type callback;
        int fnmatch_flags;

        route(const std::string &pattern_,
                const callback_type &callback_,
                int fnmatch_flags_=0)
            : pattern(pattern_), callback(callback_), fnmatch_flags(fnmatch_flags_) {}
    };

public:
    http_server(size_t stacksize_=default_stacksize, unsigned timeout_ms_=0)
        : netsock_server("http", stacksize_, timeout_ms_),
        _routes(std::make_shared<std::vector<route> >())
    {
    }

    //! add a callback for a uri with an fnmatch pattern
    void add_route(const std::string &pattern,
            const callback_type &callback,
            int fnmatch_flags = 0)
    {
      _routes->push_back(route(pattern, callback, fnmatch_flags));
    }

    //! set logging function, called after every request
    void set_log_callback(const callback_type &f) {
        _log_func = f;
    }

    std::function<void ()> connect_watch;
    std::function<void ()> disconnect_watch;
private:
    std::shared_ptr<std::vector<route> > _routes;
    callback_type _log_func;

    void on_shutdown() {
        // release any memory held by bound callbacks
        // this shared ptr madness is for threaded shutdown
        auto rr = _routes;
        rr->clear();
    }

    void on_connection(netsock &s) {
        // TODO: tuneable buffer sizes
        buffer buf(4*1024);
        http_parser parser;

        if (connect_watch) {
            connect_watch();
        }
        // TODO: might want to enable this later after
        // we know this will be a long-lived connection
        // otherwise the overhead of the syscall hurts concurrency
        //s.s.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1);

        http_request req;
        for (;;) {
            req.parser_init(&parser);
            bool got_headers = false;
            for (;;) {
                buf.reserve(4*1024);
                ssize_t nr = -1;
                if (buf.size() == 0) {
                    nr = s.recv(buf.back(), buf.available(), timeout_ms);
                    if (nr < 0) goto done;
                    buf.commit(nr);
                }
                size_t nparse = buf.size();
                req.parse(&parser, buf.front(), nparse);
                buf.remove(nparse);
                if (req.complete) {
                    // handle request
                    handle_request(req, s);
                    break;
                }
                if (nr == 0) goto done;
                if (!got_headers && !req.method.empty()) {
                    got_headers = true;
                    if (req.get("Expect") == "100-continue") {
                        http_response cont_resp(100);
                        std::string data = cont_resp.data();
                        ssize_t nw = s.send(data.data(), data.size());
                        (void)nw;
                    }
                }
            }
        }
done:
        if (disconnect_watch) {
            disconnect_watch();
        }
    }

    void handle_request(http_request &req, netsock &s) {
        request r(req, s);
        std::string path = req.path();
        DVLOG(5) << "path: " << path;
        // not super efficient, but good enough
        for (auto i= _routes->cbegin(); i!= _routes->cend(); i++) {
            DVLOG(5) << "matching pattern: " << i->pattern;
            if (fnmatch(i->pattern.c_str(), path.c_str(), i->fnmatch_flags) == 0) {
                try {
                    i->callback(r);
                } catch (std::exception &e) {
                    DVLOG(2) << "unhandled exception in route [" << i->pattern << "]: " << e.what();
                    r.resp = http_response(500,
                            Headers("Connection", "close"));
                    std::string msg = e.what();
                    msg += "\n";
                    r.resp.set_body(msg);
                    r.send_response();
                }
                break;
            }
        }
        if (_log_func) {
            _log_func(r);
        }
    }
};

} // end namespace ten

#endif // LIBTEN_HTTP_SERVER_HH
<|endoftext|>