<commit_before>#include "AndroidServiceHandler.h"
#include "protocol/AmmoMessages.pb.h"
#include "AndroidMessageProcessor.h"

#include <iostream>

#include "ace/OS_NS_errno.h"

#include "log.h"

using namespace std;

extern std::string gatewayAddress;
extern int gatewayPort;

AndroidServiceHandler::AndroidServiceHandler() :
messageProcessor(NULL),
sendQueueMutex(),
receiveQueueMutex()
{

}

int AndroidServiceHandler::open(void *ptr) {
  if(super::open(ptr) == -1) {
    return -1;

  }
  state = READING_SIZE;
  dataSize = 0;
  checksum = 0;
  collectedData = NULL;
  position = 0;

  dataToSend = NULL;
  position = 0;

  connectionClosing = false;

  messageProcessor = new AndroidMessageProcessor(this);
  messageProcessor->activate();

  return 0;
}

int AndroidServiceHandler::handle_close(ACE_HANDLE fd, ACE_Reactor_Mask m) {
  connectionClosing = true;
  LOG_TRACE("Closing Message Processor");
  messageProcessor->close(0);
  LOG_TRACE("Waiting for message processor thread to finish...");
  messageProcessor->wait();
  LOG_TRACE("Message processor finished.");
  super::handle_close(fd, m);

  return 0;
}

int AndroidServiceHandler::handle_input(ACE_HANDLE fd) {
  LOG_TRACE("In handle_input");
  int count = 0;

  if(state == READING_SIZE) {
    count = this->peer().recv_n(&dataSize, sizeof(dataSize));
    LOG_TRACE("SIZE Read " << count << " bytes");
  } else if(state == READING_CHECKSUM) {
    count = this->peer().recv_n(&checksum, sizeof(checksum));
    LOG_TRACE("SUM Read " << count << " bytes");
  } else if(state == READING_DATA) {
    count = this->peer().recv(collectedData + position, dataSize - position);
    LOG_TRACE("DATA Read " << count << " bytes");
  } else {
    LOG_ERROR("Invalid state!");
  }

  if(count > 0) {
    if(state == READING_SIZE) {
      collectedData = new char[dataSize];
      position = 0;
      LOG_TRACE("Got data size (" << dataSize << ")");
      state = READING_CHECKSUM;
    } else if(state == READING_CHECKSUM) {
      LOG_TRACE("Got data checksum (" << checksum << ")");
      state = READING_DATA;
    } else if(state == READING_DATA) {
      LOG_TRACE("Got some data...");
      position += count;
      if(position == dataSize) {
        LOG_TRACE("Got all the data... processing");
        processData(collectedData, dataSize, checksum);
        LOG_TRACE("Processsing complete.  Deleting buffer.");
        delete[] collectedData;
        collectedData = NULL;
        dataSize = 0;
        position = 0;
        state = READING_SIZE;
      }
    }
  } else if(count == 0) {
    LOG_INFO("Connection closed.");
    return -1;
  } else if(count == -1 && ACE_OS::last_error () != EWOULDBLOCK) {
    LOG_ERROR("Socket error occurred. (" << ACE_OS::last_error() << ")");
    return -1;
  }
  LOG_TRACE("Leaving handle_input()");
  return 0;
}

int AndroidServiceHandler::handle_output(ACE_HANDLE fd) {
  int count = 0;

  do {
    if(dataToSend == NULL) {
      ammo::protocol::MessageWrapper *msg = getNextMessageToSend();
      if(msg != NULL) {
        if(!msg->IsInitialized()) {
          LOG_WARN("Protocol Buffers message is missing a required element.");
        }
        unsigned int messageSize = msg->ByteSize();
        sendBufferSize = messageSize + 2*sizeof(unsigned int);
        dataToSend = new char[sendBufferSize];
        unsigned int *size = (unsigned int *) dataToSend;
        unsigned int *messageChecksum = (unsigned int *) (dataToSend + sizeof(unsigned int));
        char *protobufSerializedMessage = dataToSend + 2*sizeof(unsigned int);

        *size = messageSize;
        msg->SerializeToArray(protobufSerializedMessage, messageSize);
        *messageChecksum = ACE::crc32(protobufSerializedMessage, messageSize);

        sendPosition = 0;

        delete msg;
      } else {
        //don't wake up the reactor when there's no data that needs to be sent
        //(wake-up will be rescheduled when data becomes available in sendMessage
        //below)
        this->reactor()->cancel_wakeup(this, ACE_Event_Handler::WRITE_MASK);
        return 0;
      }
    }

    count = this->peer().send(dataToSend, sendBufferSize - sendPosition);
    if(count >= 0) {
      sendPosition += count;
    }

    if(sendPosition >= (sendBufferSize - 1)) {
      delete[] dataToSend;
      dataToSend = NULL;
      sendBufferSize = 0;
      sendPosition = 0;
    }
  } while(count != -1);

  if(count == -1 && ACE_OS::last_error () == EWOULDBLOCK) {
    this->reactor()->schedule_wakeup(this, ACE_Event_Handler::WRITE_MASK);
  } else {
    LOG_ERROR("Socket error occurred. (" << ACE_OS::last_error() << ")");
    return -1;
  }

  return 0;
}

int AndroidServiceHandler::processData(char *data, unsigned int messageSize, unsigned int messageChecksum) {
  //Validate checksum
  unsigned int calculatedChecksum = ACE::crc32(data, messageSize);
  if(calculatedChecksum != messageChecksum) {
    LOG_ERROR("Mismatched checksum " << std::hex << calculatedChecksum << " : " << messageChecksum);
    LOG_ERROR("size " << std::dec << messageSize ); // << " payload: " < );
    return -1;
  }

  //checksum is valid; parse the data
  ammo::protocol::MessageWrapper *msg = new ammo::protocol::MessageWrapper();
  bool result = msg->ParseFromArray(data, messageSize);
  if(result == false) {
    LOG_ERROR("MessageWrapper could not be deserialized.");
    LOG_ERROR("Client must have sent something that isn't a protocol buffer (or the wrong type).");
    delete msg;
    return -1;
  }
  addReceivedMessage(msg);
  messageProcessor->signalNewMessageAvailable();

  return 0;
}

void AndroidServiceHandler::sendMessage(ammo::protocol::MessageWrapper *msg) {
  sendQueueMutex.acquire();
  if(!connectionClosing) {
    sendQueue.push(msg);
    this->reactor()->schedule_wakeup(this, ACE_Event_Handler::WRITE_MASK);
    LOG_TRACE("Queued a message to send.  " << sendQueue.size() << " messages in queue.");
  }
  sendQueueMutex.release();
}

ammo::protocol::MessageWrapper *AndroidServiceHandler::getNextMessageToSend() {
  ammo::protocol::MessageWrapper *msg = NULL;
  sendQueueMutex.acquire();
  if(!sendQueue.empty()) {
    msg = sendQueue.front();
    sendQueue.pop();
  }
  sendQueueMutex.release();
  LOG_TRACE("Dequeued a message to send.  " << sendQueue.size() << " messages remain in queue.");
  return msg;
}

ammo::protocol::MessageWrapper *AndroidServiceHandler::getNextReceivedMessage() {
  ammo::protocol::MessageWrapper *msg = NULL;
  receiveQueueMutex.acquire();
  if(!receiveQueue.empty()) {
    msg = receiveQueue.front();
    receiveQueue.pop();
  }
  receiveQueueMutex.release();

  return msg;
}

void AndroidServiceHandler::addReceivedMessage(ammo::protocol::MessageWrapper *msg) {
  receiveQueueMutex.acquire();
  receiveQueue.push(msg);
  receiveQueueMutex.release();
}

AndroidServiceHandler::~AndroidServiceHandler() {
  LOG_TRACE("In ~AndroidServiceHandler");
  delete messageProcessor;
}
<commit_msg>Fix possible deadlock if we're really unlucky and something tries to send and receive at exactly the same time<commit_after>#include "AndroidServiceHandler.h"
#include "protocol/AmmoMessages.pb.h"
#include "AndroidMessageProcessor.h"

#include <iostream>

#include "ace/OS_NS_errno.h"

#include "log.h"

using namespace std;

extern std::string gatewayAddress;
extern int gatewayPort;

AndroidServiceHandler::AndroidServiceHandler() :
messageProcessor(NULL),
sendQueueMutex(),
receiveQueueMutex()
{

}

int AndroidServiceHandler::open(void *ptr) {
  if(super::open(ptr) == -1) {
    return -1;

  }
  state = READING_SIZE;
  dataSize = 0;
  checksum = 0;
  collectedData = NULL;
  position = 0;

  dataToSend = NULL;
  position = 0;

  connectionClosing = false;

  messageProcessor = new AndroidMessageProcessor(this);
  messageProcessor->activate();

  return 0;
}

int AndroidServiceHandler::handle_close(ACE_HANDLE fd, ACE_Reactor_Mask m) {
  connectionClosing = true;
  LOG_TRACE("Closing Message Processor");
  messageProcessor->close(0);
  LOG_TRACE("Waiting for message processor thread to finish...");
  messageProcessor->wait();
  LOG_TRACE("Message processor finished.");
  super::handle_close(fd, m);

  return 0;
}

int AndroidServiceHandler::handle_input(ACE_HANDLE fd) {
  LOG_TRACE("In handle_input");
  int count = 0;

  if(state == READING_SIZE) {
    count = this->peer().recv_n(&dataSize, sizeof(dataSize));
    LOG_TRACE("SIZE Read " << count << " bytes");
  } else if(state == READING_CHECKSUM) {
    count = this->peer().recv_n(&checksum, sizeof(checksum));
    LOG_TRACE("SUM Read " << count << " bytes");
  } else if(state == READING_DATA) {
    count = this->peer().recv(collectedData + position, dataSize - position);
    LOG_TRACE("DATA Read " << count << " bytes");
  } else {
    LOG_ERROR("Invalid state!");
  }

  if(count > 0) {
    if(state == READING_SIZE) {
      collectedData = new char[dataSize];
      position = 0;
      LOG_TRACE("Got data size (" << dataSize << ")");
      state = READING_CHECKSUM;
    } else if(state == READING_CHECKSUM) {
      LOG_TRACE("Got data checksum (" << checksum << ")");
      state = READING_DATA;
    } else if(state == READING_DATA) {
      LOG_TRACE("Got some data...");
      position += count;
      if(position == dataSize) {
        LOG_TRACE("Got all the data... processing");
        processData(collectedData, dataSize, checksum);
        LOG_TRACE("Processsing complete.  Deleting buffer.");
        delete[] collectedData;
        collectedData = NULL;
        dataSize = 0;
        position = 0;
        state = READING_SIZE;
      }
    }
  } else if(count == 0) {
    LOG_INFO("Connection closed.");
    return -1;
  } else if(count == -1 && ACE_OS::last_error () != EWOULDBLOCK) {
    LOG_ERROR("Socket error occurred. (" << ACE_OS::last_error() << ")");
    return -1;
  }
  LOG_TRACE("Leaving handle_input()");
  return 0;
}

int AndroidServiceHandler::handle_output(ACE_HANDLE fd) {
  int count = 0;

  do {
    if(dataToSend == NULL) {
      ammo::protocol::MessageWrapper *msg = getNextMessageToSend();
      if(msg != NULL) {
        if(!msg->IsInitialized()) {
          LOG_WARN("Protocol Buffers message is missing a required element.");
        }
        unsigned int messageSize = msg->ByteSize();
        sendBufferSize = messageSize + 2*sizeof(unsigned int);
        dataToSend = new char[sendBufferSize];
        unsigned int *size = (unsigned int *) dataToSend;
        unsigned int *messageChecksum = (unsigned int *) (dataToSend + sizeof(unsigned int));
        char *protobufSerializedMessage = dataToSend + 2*sizeof(unsigned int);

        *size = messageSize;
        msg->SerializeToArray(protobufSerializedMessage, messageSize);
        *messageChecksum = ACE::crc32(protobufSerializedMessage, messageSize);

        sendPosition = 0;

        delete msg;
      } else {
        //don't wake up the reactor when there's no data that needs to be sent
        //(wake-up will be rescheduled when data becomes available in sendMessage
        //below)
        this->reactor()->cancel_wakeup(this, ACE_Event_Handler::WRITE_MASK);
        return 0;
      }
    }

    count = this->peer().send(dataToSend, sendBufferSize - sendPosition);
    if(count >= 0) {
      sendPosition += count;
    }

    if(sendPosition >= (sendBufferSize - 1)) {
      delete[] dataToSend;
      dataToSend = NULL;
      sendBufferSize = 0;
      sendPosition = 0;
    }
  } while(count != -1);

  if(count == -1 && ACE_OS::last_error () == EWOULDBLOCK) {
    this->reactor()->schedule_wakeup(this, ACE_Event_Handler::WRITE_MASK);
  } else {
    LOG_ERROR("Socket error occurred. (" << ACE_OS::last_error() << ")");
    return -1;
  }

  return 0;
}

int AndroidServiceHandler::processData(char *data, unsigned int messageSize, unsigned int messageChecksum) {
  //Validate checksum
  unsigned int calculatedChecksum = ACE::crc32(data, messageSize);
  if(calculatedChecksum != messageChecksum) {
    LOG_ERROR("Mismatched checksum " << std::hex << calculatedChecksum << " : " << messageChecksum);
    LOG_ERROR("size " << std::dec << messageSize ); // << " payload: " < );
    return -1;
  }

  //checksum is valid; parse the data
  ammo::protocol::MessageWrapper *msg = new ammo::protocol::MessageWrapper();
  bool result = msg->ParseFromArray(data, messageSize);
  if(result == false) {
    LOG_ERROR("MessageWrapper could not be deserialized.");
    LOG_ERROR("Client must have sent something that isn't a protocol buffer (or the wrong type).");
    delete msg;
    return -1;
  }
  addReceivedMessage(msg);
  messageProcessor->signalNewMessageAvailable();

  return 0;
}

void AndroidServiceHandler::sendMessage(ammo::protocol::MessageWrapper *msg) {
  sendQueueMutex.acquire();
  if(!connectionClosing) {
    sendQueue.push(msg);
    LOG_TRACE("Queued a message to send.  " << sendQueue.size() << " messages in queue.");
  }
  sendQueueMutex.release();
  this->reactor()->schedule_wakeup(this, ACE_Event_Handler::WRITE_MASK);
}

ammo::protocol::MessageWrapper *AndroidServiceHandler::getNextMessageToSend() {
  ammo::protocol::MessageWrapper *msg = NULL;
  sendQueueMutex.acquire();
  if(!sendQueue.empty()) {
    msg = sendQueue.front();
    sendQueue.pop();
  }
  sendQueueMutex.release();
  LOG_TRACE("Dequeued a message to send.  " << sendQueue.size() << " messages remain in queue.");
  return msg;
}

ammo::protocol::MessageWrapper *AndroidServiceHandler::getNextReceivedMessage() {
  ammo::protocol::MessageWrapper *msg = NULL;
  receiveQueueMutex.acquire();
  if(!receiveQueue.empty()) {
    msg = receiveQueue.front();
    receiveQueue.pop();
  }
  receiveQueueMutex.release();

  return msg;
}

void AndroidServiceHandler::addReceivedMessage(ammo::protocol::MessageWrapper *msg) {
  receiveQueueMutex.acquire();
  receiveQueue.push(msg);
  receiveQueueMutex.release();
}

AndroidServiceHandler::~AndroidServiceHandler() {
  LOG_TRACE("In ~AndroidServiceHandler");
  delete messageProcessor;
}
<|endoftext|>


<commit_before>#ifndef MJOLNIR_FORCEFIELD_PDNS_PROTEIN_DNA_NON_SPECIFIC_POTENTIAL_HPP
#define MJOLNIR_FORCEFIELD_PDNS_PROTEIN_DNA_NON_SPECIFIC_POTENTIAL_HPP
#include <mjolnir/math/math.hpp>
#include <cstdint>

namespace mjolnir
{

// Protein-DNA Non-Specific interaction that represents hydrogen bond between
// side chain atoms in proteins and the phosphate residues in DNA.
// This is an implementation of the potential developed in the following paper.
// - T.Niina, G.B.Brandani, C.Tan, and S.Takada (2017) PLoS. Comput. Biol.

// ```toml
// [[forcefields.global]]
// interaction = "PDNS"
// potential   = "PDNS"
// spatial_partition.type   = "CellList"
// spatial_partition.margin = 1.0
// sigma = 1.0
// delta = 0.17453
// parameters  = [
// {index =    2, S = 1, kind = "DNA"},
// {index =    5, S = 4, kind = "DNA"},
// # ...
// {index = 1000, kind = "Protein", PN =  999, PC = 1001, k = 1.2, r0 = 5.0, theta0 = 100.0, phi0 = 130.0},
// {index = 1023, kind = "Protein", PN = 1022, PC = 1024, k = 1.2, r0 = 6.0, theta0 = 110.0, phi0 = 120.0},
// # ...
// ]
// ```
namespace parameter_PDNS
{
enum bead_kind : std::uint8_t
{
    Protein,
    DNA,
    invalid
};

template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const bead_kind bk)
{
    switch(bk)
    {
        case bead_kind::Protein: {os << "PRO"; return os;}
        case bead_kind::DNA:     {os << "DNA"; return os;}
        case bead_kind::invalid: {os << "INV"; return os;}
        default:                 {os << "UNK"; return os;}
    }
}
} // pdns

template<typename realT>
class ProteinDNANonSpecificPotential
{
  public:
    using real_type = realT;
    using self_type = ProteinDNANonSpecificPotential<real_type>;
    using bead_kind = parameter_PDNS::bead_kind;

    struct parameter_type
    {
        bead_kind     kind;
        std::uint32_t S_idx;        // for DNA
        std::uint32_t N_idx, C_idx; // for PRO
        real_type k, r0, theta0, phi0;
    };
    struct pair_parameter_type
    {
        std::uint32_t S3, PN, PC;
        real_type k, r0, theta0, phi0;
    };
    using container_type = std::vector<parameter_type>;

    // topology stuff
    using topology_type        = Topology;
    using molecule_id_type     = typename topology_type::molecule_id_type;
    using group_id_type        = typename topology_type::group_id_type;
    using connection_kind_type = typename topology_type::connection_kind_type;
    using ignore_molecule_type = IgnoreMolecule<molecule_id_type>;
    using ignore_group_type    = IgnoreGroup   <group_id_type>;
    using exclusion_list_type  = ExclusionList;

    static constexpr std::size_t invalid() noexcept
    {
        return std::numeric_limits<std::size_t>::max();
    }
    static constexpr parameter_type default_parameter() noexcept
    {
        return parameter_type{
            bead_kind::invalid, invalid(), invalid(), invalid(), 0, 0, 0, 0
        };
    }
    static constexpr real_type default_cutoff() noexcept {return 5.0;}

  public:

    ProteinDNANonSpecificPotential(const real_type sigma, const real_type delta,
        const real_type cutoff_ratio,
        const std::vector<std::pair<std::size_t, parameter_type>>& parameters,
        const std::map<connection_kind_type, std::size_t>&         exclusions,
        ignore_molecule_type ignore_mol, ignore_group_type ignore_grp)
        : sigma_(sigma), delta_(delta), delta2_(delta * 2),
          one_over_2delta_(0.5 / delta), cutoff_ratio_(cutoff_ratio),
          exclusion_list_(exclusions, std::move(ignore_mol), std::move(ignore_grp))
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        this->parameters_  .reserve(parameters.size());
        this->participants_.reserve(parameters.size());
        for(const auto& idxp : parameters)
        {
            const auto idx = idxp.first;

            this->participants_.push_back(idx);
            if(idxp.second.kind == bead_kind::Protein)
            {
                this->proteins_.push_back(idx);
            }

            if(idx >= this->parameters_.size())
            {
                this->parameters_.resize(idx+1, self_type::default_parameter());
            }
            this->parameters_.at(idx) = idxp.second;
        }
    }
    ~ProteinDNANonSpecificPotential() = default;

    std::pair<real_type, real_type>
    f_df(const real_type r0, const real_type r) noexcept
    {
        const real_type rsigma   = real_type(1) / this->sigma_;
        const real_type dr_sigma = (r - r0) * rsigma;
        const real_type term     = std::exp(-dr_sigma * dr_sigma);

        return std::make_pair(term, -2 * dr_sigma * rsigma * term);
    }
    std::pair<real_type, real_type>
    g_dg(const real_type theta0, const real_type theta) noexcept
    {
        constexpr auto  pi         = math::constants<real_type>::pi();
        const real_type dtheta     = theta - theta0;
        const real_type abs_dtheta = std::abs(dtheta);
        if(abs_dtheta < this->delta_)
        {
            return std::pair<real_type, real_type>(1, 0);
        }
        else if(abs_dtheta < this->delta2_)
        {
            const real_type c = std::cos(pi * dtheta * one_over_2delta_);
            const real_type s = std::sin(pi * dtheta * one_over_2delta_);
            return std::make_pair(1 - c * c, 2 * s * c * pi * one_over_2delta_);
        }
        else
        {
            return std::pair<real_type, real_type>(0, 0);
        }
    }

    real_type f(const real_type r0, const real_type r) noexcept
    {
        const real_type dr_sigma = (r - r0) / this->sigma_;
        return std::exp(-dr_sigma * dr_sigma);
    }
    real_type g(const real_type theta0, const real_type theta) noexcept
    {
        constexpr auto pi = math::constants<real_type>::pi();
        const real_type dtheta     = theta - theta0;
        const real_type abs_dtheta = std::abs(dtheta);
        if(abs_dtheta < this->delta_)
        {
            return 1;
        }
        else if(abs_dtheta < this->delta2_)
        {
            const real_type term = std::cos(pi * dtheta * one_over_2delta_);
            return real_type(1) - term * term;
        }
        else
        {
            return 0;
        }
    }

    real_type cutoff_ratio()      const noexcept {return cutoff_ratio_;}
    real_type gaussian_cutoff()   const noexcept {return sigma_ * cutoff_ratio_;}
    real_type max_cutoff_length() const noexcept
    {
        real_type max_r0 = 0.0;
        for(const auto pro : this->proteins_)
        {
            const auto& para = this->parameters_.at(pro);
            max_r0 = std::max(max_r0, para.r0);
        }
        return max_r0 + this->sigma_ * this->cutoff_ratio_;
    }

    template<typename traitsT>
    void initialize(const System<traitsT>& sys) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        this->update(sys);
        return;
    }

    template<typename traitsT>
    void update(const System<traitsT>& sys) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        // update exclusion list based on sys.topology()
        exclusion_list_.make(sys);
        return;
    }

    bool has_interaction(const std::size_t i, const std::size_t j) const noexcept
    {
        // if not excluded, the pair has interaction.
        if(exclusion_list_.is_excluded(i, j))
        {
            return false;
        }
        const auto i_kind = this->parameters_[i].kind;
        const auto j_kind = this->parameters_[j].kind;
        if(i_kind == bead_kind::Protein && j_kind == bead_kind::DNA)
        {
            return true; // Protein-DNA
        }
        else if(i_kind == bead_kind::DNA && j_kind == bead_kind::Protein)
        {
            return true; // DNA-Protein
        }
        return false; // other pair
    }

    // for testing
    exclusion_list_type const& exclusion_list() const noexcept
    {
        return exclusion_list_;
    }

    // ------------------------------------------------------------------------
    // used by Observer.
    static const char* name() noexcept {return "LennardJones";}

    // ------------------------------------------------------------------------
    // the following accessers would be used in tests.

    // access to the parameters...
    std::vector<parameter_type>&       parameters()       noexcept {return parameters_;}
    std::vector<parameter_type> const& parameters() const noexcept {return parameters_;}

    std::vector<std::size_t> const& participants() const noexcept {return participants_;}
    std::vector<std::size_t> const& proteins()     const noexcept {return proteins_;}

  private:

    real_type sigma, delta, delta2_, one_over_2delta_, cutoff_ratio_;
    container_type           parameters_;     // indices
    std::vector<std::size_t> participants_;   // PRO + DNA beads
    std::vector<std::size_t> proteins_;       // PRO only; to reduce loop size
    exclusion_list_type      exclusion_list_;
};

} // mjolnir
#endif// MJOLNIR_FORCEFIELD_PDNS_PROTEIN_DNA_NON_SPECIFIC_INTERACTION_HPP
<commit_msg>fix: fix typos and function specifiers<commit_after>#ifndef MJOLNIR_FORCEFIELD_PDNS_PROTEIN_DNA_NON_SPECIFIC_POTENTIAL_HPP
#define MJOLNIR_FORCEFIELD_PDNS_PROTEIN_DNA_NON_SPECIFIC_POTENTIAL_HPP
#include <mjolnir/math/math.hpp>
#include <cstdint>

namespace mjolnir
{

// Protein-DNA Non-Specific interaction that represents hydrogen bond between
// side chain atoms in proteins and the phosphate residues in DNA.
// This is an implementation of the potential developed in the following paper.
// - T.Niina, G.B.Brandani, C.Tan, and S.Takada (2017) PLoS. Comput. Biol.

// ```toml
// [[forcefields.global]]
// interaction = "PDNS"
// potential   = "PDNS"
// spatial_partition.type   = "CellList"
// spatial_partition.margin = 1.0
// sigma = 1.0
// delta = 0.17453
// parameters  = [
// {index =    2, S = 1, kind = "DNA"},
// {index =    5, S = 4, kind = "DNA"},
// # ...
// {index = 1000, kind = "Protein", PN =  999, PC = 1001, k = 1.2, r0 = 5.0, theta0 = 100.0, phi0 = 130.0},
// {index = 1023, kind = "Protein", PN = 1022, PC = 1024, k = 1.2, r0 = 6.0, theta0 = 110.0, phi0 = 120.0},
// # ...
// ]
// ```
namespace parameter_PDNS
{
enum bead_kind : std::uint8_t
{
    Protein,
    DNA,
    invalid
};

template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const bead_kind bk)
{
    switch(bk)
    {
        case bead_kind::Protein: {os << "PRO"; return os;}
        case bead_kind::DNA:     {os << "DNA"; return os;}
        case bead_kind::invalid: {os << "INV"; return os;}
        default:                 {os << "UNK"; return os;}
    }
}
} // pdns

template<typename realT>
class ProteinDNANonSpecificPotential
{
  public:
    using real_type = realT;
    using self_type = ProteinDNANonSpecificPotential<real_type>;
    using bead_kind = parameter_PDNS::bead_kind;

    struct parameter_type
    {
        bead_kind     kind;
        std::uint32_t S_idx;        // for DNA
        std::uint32_t N_idx, C_idx; // for PRO
        real_type k, r0, theta0, phi0;
    };
    struct pair_parameter_type
    {
        std::uint32_t S3, PN, PC;
        real_type k, r0, theta0, phi0;
    };
    using container_type = std::vector<parameter_type>;

    // topology stuff
    using topology_type        = Topology;
    using molecule_id_type     = typename topology_type::molecule_id_type;
    using group_id_type        = typename topology_type::group_id_type;
    using connection_kind_type = typename topology_type::connection_kind_type;
    using ignore_molecule_type = IgnoreMolecule<molecule_id_type>;
    using ignore_group_type    = IgnoreGroup   <group_id_type>;
    using exclusion_list_type  = ExclusionList;

    static constexpr std::uint32_t invalid() noexcept
    {
        return std::numeric_limits<std::uint32_t>::max();
    }
    static constexpr parameter_type default_parameter() noexcept
    {
        return parameter_type{
            bead_kind::invalid, invalid(), invalid(), invalid(), 0, 0, 0, 0
        };
    }
    static constexpr real_type default_cutoff() noexcept {return 5.0;}

  public:

    ProteinDNANonSpecificPotential(const real_type sigma, const real_type delta,
        const real_type cutoff_ratio,
        const std::vector<std::pair<std::size_t, parameter_type>>& parameters,
        const std::map<connection_kind_type, std::size_t>&         exclusions,
        ignore_molecule_type ignore_mol, ignore_group_type ignore_grp)
        : sigma_(sigma), delta_(delta), delta2_(delta * 2),
          one_over_2delta_(0.5 / delta), cutoff_ratio_(cutoff_ratio),
          exclusion_list_(exclusions, std::move(ignore_mol), std::move(ignore_grp))
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        this->parameters_  .reserve(parameters.size());
        this->participants_.reserve(parameters.size());
        for(const auto& idxp : parameters)
        {
            const auto idx = idxp.first;

            this->participants_.push_back(idx);
            if(idxp.second.kind == bead_kind::Protein)
            {
                this->proteins_.push_back(idx);
            }

            if(idx >= this->parameters_.size())
            {
                this->parameters_.resize(idx+1, self_type::default_parameter());
            }
            this->parameters_.at(idx) = idxp.second;
        }
    }
    ~ProteinDNANonSpecificPotential() = default;

    std::pair<real_type, real_type>
    f_df(const real_type r0, const real_type r) const noexcept
    {
        const real_type rsigma   = real_type(1) / this->sigma_;
        const real_type dr_sigma = (r - r0) * rsigma;
        const real_type term     = std::exp(-dr_sigma * dr_sigma);

        return std::make_pair(term, -2 * dr_sigma * rsigma * term);
    }
    std::pair<real_type, real_type>
    g_dg(const real_type theta0, const real_type theta) const noexcept
    {
        constexpr auto  pi         = math::constants<real_type>::pi();
        const real_type dtheta     = theta - theta0;
        const real_type abs_dtheta = std::abs(dtheta);
        if(abs_dtheta < this->delta_)
        {
            return std::pair<real_type, real_type>(1, 0);
        }
        else if(abs_dtheta < this->delta2_)
        {
            const real_type c = std::cos(pi * dtheta * one_over_2delta_);
            const real_type s = std::sin(pi * dtheta * one_over_2delta_);
            return std::make_pair(1 - c * c, 2 * s * c * pi * one_over_2delta_);
        }
        else
        {
            return std::pair<real_type, real_type>(0, 0);
        }
    }

    real_type f(const real_type r0, const real_type r) const noexcept
    {
        const real_type dr_sigma = (r - r0) / this->sigma_;
        return std::exp(-dr_sigma * dr_sigma);
    }
    real_type g(const real_type theta0, const real_type theta) const noexcept
    {
        constexpr auto pi = math::constants<real_type>::pi();
        const real_type dtheta     = theta - theta0;
        const real_type abs_dtheta = std::abs(dtheta);
        if(abs_dtheta < this->delta_)
        {
            return 1;
        }
        else if(abs_dtheta < this->delta2_)
        {
            const real_type term = std::cos(pi * dtheta * one_over_2delta_);
            return real_type(1) - term * term;
        }
        else
        {
            return 0;
        }
    }

    real_type cutoff_ratio()      const noexcept {return cutoff_ratio_;}
    real_type gaussian_cutoff()   const noexcept {return sigma_ * cutoff_ratio_;}
    real_type max_cutoff_length() const noexcept
    {
        real_type max_r0 = 0.0;
        for(const auto pro : this->proteins_)
        {
            const auto& para = this->parameters_.at(pro);
            max_r0 = std::max(max_r0, para.r0);
        }
        return max_r0 + this->sigma_ * this->cutoff_ratio_;
    }

    template<typename traitsT>
    void initialize(const System<traitsT>& sys) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        this->update(sys);
        return;
    }

    template<typename traitsT>
    void update(const System<traitsT>& sys) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        // update exclusion list based on sys.topology()
        exclusion_list_.make(sys);
        return;
    }

    bool has_interaction(const std::size_t i, const std::size_t j) const noexcept
    {
        // if not excluded, the pair has interaction.
        if(exclusion_list_.is_excluded(i, j))
        {
            return false;
        }
        const auto i_kind = this->parameters_[i].kind;
        const auto j_kind = this->parameters_[j].kind;
        if(i_kind == bead_kind::Protein && j_kind == bead_kind::DNA)
        {
            return true; // Protein-DNA
        }
        else if(i_kind == bead_kind::DNA && j_kind == bead_kind::Protein)
        {
            return true; // DNA-Protein
        }
        return false; // other pair
    }

    // for testing
    exclusion_list_type const& exclusion_list() const noexcept
    {
        return exclusion_list_;
    }

    // ------------------------------------------------------------------------
    // used by Observer.
    static const char* name() noexcept {return "PDNS";}

    // ------------------------------------------------------------------------
    // the following accessers would be used in tests.

    // access to the parameters...
    std::vector<parameter_type>&       parameters()       noexcept {return parameters_;}
    std::vector<parameter_type> const& parameters() const noexcept {return parameters_;}

    std::vector<std::size_t> const& participants() const noexcept {return participants_;}
    std::vector<std::size_t> const& proteins()     const noexcept {return proteins_;}

  private:

    real_type sigma_, delta_, delta2_, one_over_2delta_, cutoff_ratio_;
    container_type           parameters_;     // indices
    std::vector<std::size_t> participants_;   // PRO + DNA beads
    std::vector<std::size_t> proteins_;       // PRO only; to reduce loop size
    exclusion_list_type      exclusion_list_;
};

} // mjolnir
#endif// MJOLNIR_FORCEFIELD_PDNS_PROTEIN_DNA_NON_SPECIFIC_INTERACTION_HPP
<|endoftext|>


<commit_before>//===- LiveValues.cpp - Liveness information for LLVM IR Values. ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the implementation for the LLVM IR Value liveness
// analysis pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/LiveValues.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
using namespace llvm;

FunctionPass *llvm::createLiveValuesPass() { return new LiveValues(); }

char LiveValues::ID = 0;
static RegisterPass<LiveValues>
X("live-values", "Value Liveness Analysis", false, true);

LiveValues::LiveValues() : FunctionPass(&ID) {}

void LiveValues::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<DominatorTree>();
  AU.addRequired<LoopInfo>();
  AU.setPreservesAll();
}

bool LiveValues::runOnFunction(Function &F) {
  DT = &getAnalysis<DominatorTree>();
  LI = &getAnalysis<LoopInfo>();

  // This pass' values are computed lazily, so there's nothing to do here.

  return false;
}

void LiveValues::releaseMemory() {
  Memos.clear();
}

/// isUsedInBlock - Test if the given value is used in the given block.
///
bool LiveValues::isUsedInBlock(const Value *V, const BasicBlock *BB) {
  Memo &M = getMemo(V);
  return M.Used.count(BB);
}

/// isLiveThroughBlock - Test if the given value is known to be
/// live-through the given block, meaning that the block is properly
/// dominated by the value's definition, and there exists a block
/// reachable from it that contains a use. This uses a conservative
/// approximation that errs on the side of returning false.
///
bool LiveValues::isLiveThroughBlock(const Value *V,
                                    const BasicBlock *BB) {
  Memo &M = getMemo(V);
  return M.LiveThrough.count(BB);
}

/// isKilledInBlock - Test if the given value is known to be killed in
/// the given block, meaning that the block contains a use of the value,
/// and no blocks reachable from the block contain a use. This uses a
/// conservative approximation that errs on the side of returning false.
///
bool LiveValues::isKilledInBlock(const Value *V, const BasicBlock *BB) {
  Memo &M = getMemo(V);
  return M.Killed.count(BB);
}

/// getMemo - Retrieve an existing Memo for the given value if one
/// is available, otherwise compute a new one.
///
LiveValues::Memo &LiveValues::getMemo(const Value *V) {
  DenseMap<const Value *, Memo>::iterator I = Memos.find(V);
  if (I != Memos.end())
    return I->second;
  return compute(V);
}

/// getImmediateDominator - A handy utility for the specific DominatorTree
/// query that we need here.
///
static const BasicBlock *getImmediateDominator(const BasicBlock *BB,
                                               const DominatorTree *DT) {
  DomTreeNode *Node = DT->getNode(const_cast<BasicBlock *>(BB))->getIDom();
  return Node ? Node->getBlock() : 0;
}

/// compute - Compute a new Memo for the given value.
///
LiveValues::Memo &LiveValues::compute(const Value *V) {
  Memo &M = Memos[V];

  // Determine the block containing the definition.
  const BasicBlock *DefBB;
  // Instructions define values with meaningful live ranges.
  if (const Instruction *I = dyn_cast<Instruction>(V))
    DefBB = I->getParent();
  // Arguments can be analyzed as values defined in the entry block.
  else if (const Argument *A = dyn_cast<Argument>(V))
    DefBB = &A->getParent()->getEntryBlock();
  // Constants and other things aren't meaningful here, so just
  // return having computed an empty Memo so that we don't come
  // here again. The assumption here is that client code won't
  // be asking about such values very often.
  else
    return M;

  // Determine if the value is defined inside a loop. This is used
  // to track whether the value is ever used outside the loop, so
  // it'll be set to null if the value is either not defined in a
  // loop or used outside the loop in which it is defined.
  const Loop *L = LI->getLoopFor(DefBB);

  // Track whether the value is used anywhere outside of the block
  // in which it is defined.
  bool LiveOutOfDefBB = false;

  // Examine each use of the value.
  for (Value::use_const_iterator I = V->use_begin(), E = V->use_end();
       I != E; ++I) {
    const User *U = *I;
    const BasicBlock *UseBB = cast<Instruction>(U)->getParent();

    // Note the block in which this use occurs.
    M.Used.insert(UseBB);

    // If the use block doesn't have successors, the value can be
    // considered killed.
    if (succ_begin(UseBB) == succ_end(UseBB))
      M.Killed.insert(UseBB);

    // Observe whether the value is used outside of the loop in which
    // it is defined. Switch to an enclosing loop if necessary.
    for (; L; L = L->getParentLoop())
      if (L->contains(UseBB))
        break;

    if (isa<PHINode>(U)) {
      // The value is used by a PHI, so it is live-out of the defining block.
      LiveOutOfDefBB = true;
    } else if (UseBB != DefBB) {
      // A use outside the defining block has been found.
      LiveOutOfDefBB = true;

      // Climb the immediate dominator tree from the use to the definition
      // and mark all intermediate blocks as live-through. Don't do this if
      // the user is a PHI because such users may not be dominated by the
      // definition.
      for (const BasicBlock *BB = getImmediateDominator(UseBB, DT);
           BB != DefBB; BB = getImmediateDominator(BB, DT))
        if (!M.LiveThrough.insert(BB))
          break;
    }
  }

  // If the value is defined inside a loop and is not live outside
  // the loop, then each exit block of the loop in which the value
  // is used is a kill block.
  if (L) {
    SmallVector<BasicBlock *, 4> ExitingBlocks;
    L->getExitingBlocks(ExitingBlocks);
    for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
      const BasicBlock *ExitingBlock = ExitingBlocks[i];
      if (M.Used.count(ExitingBlock))
        M.Killed.insert(ExitingBlock);
    }
  }

  // If the value was never used outside the the block in which it was
  // defined, it's killed in that block.
  if (!LiveOutOfDefBB)
    M.Killed.insert(DefBB);

  return M;
}
<commit_msg>Enhance LiveValues to work on PHI operands.<commit_after>//===- LiveValues.cpp - Liveness information for LLVM IR Values. ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the implementation for the LLVM IR Value liveness
// analysis pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/LiveValues.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
using namespace llvm;

FunctionPass *llvm::createLiveValuesPass() { return new LiveValues(); }

char LiveValues::ID = 0;
static RegisterPass<LiveValues>
X("live-values", "Value Liveness Analysis", false, true);

LiveValues::LiveValues() : FunctionPass(&ID) {}

void LiveValues::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<DominatorTree>();
  AU.addRequired<LoopInfo>();
  AU.setPreservesAll();
}

bool LiveValues::runOnFunction(Function &F) {
  DT = &getAnalysis<DominatorTree>();
  LI = &getAnalysis<LoopInfo>();

  // This pass' values are computed lazily, so there's nothing to do here.

  return false;
}

void LiveValues::releaseMemory() {
  Memos.clear();
}

/// isUsedInBlock - Test if the given value is used in the given block.
///
bool LiveValues::isUsedInBlock(const Value *V, const BasicBlock *BB) {
  Memo &M = getMemo(V);
  return M.Used.count(BB);
}

/// isLiveThroughBlock - Test if the given value is known to be
/// live-through the given block, meaning that the block is properly
/// dominated by the value's definition, and there exists a block
/// reachable from it that contains a use. This uses a conservative
/// approximation that errs on the side of returning false.
///
bool LiveValues::isLiveThroughBlock(const Value *V,
                                    const BasicBlock *BB) {
  Memo &M = getMemo(V);
  return M.LiveThrough.count(BB);
}

/// isKilledInBlock - Test if the given value is known to be killed in
/// the given block, meaning that the block contains a use of the value,
/// and no blocks reachable from the block contain a use. This uses a
/// conservative approximation that errs on the side of returning false.
///
bool LiveValues::isKilledInBlock(const Value *V, const BasicBlock *BB) {
  Memo &M = getMemo(V);
  return M.Killed.count(BB);
}

/// getMemo - Retrieve an existing Memo for the given value if one
/// is available, otherwise compute a new one.
///
LiveValues::Memo &LiveValues::getMemo(const Value *V) {
  DenseMap<const Value *, Memo>::iterator I = Memos.find(V);
  if (I != Memos.end())
    return I->second;
  return compute(V);
}

/// getImmediateDominator - A handy utility for the specific DominatorTree
/// query that we need here.
///
static const BasicBlock *getImmediateDominator(const BasicBlock *BB,
                                               const DominatorTree *DT) {
  DomTreeNode *Node = DT->getNode(const_cast<BasicBlock *>(BB))->getIDom();
  return Node ? Node->getBlock() : 0;
}

/// compute - Compute a new Memo for the given value.
///
LiveValues::Memo &LiveValues::compute(const Value *V) {
  Memo &M = Memos[V];

  // Determine the block containing the definition.
  const BasicBlock *DefBB;
  // Instructions define values with meaningful live ranges.
  if (const Instruction *I = dyn_cast<Instruction>(V))
    DefBB = I->getParent();
  // Arguments can be analyzed as values defined in the entry block.
  else if (const Argument *A = dyn_cast<Argument>(V))
    DefBB = &A->getParent()->getEntryBlock();
  // Constants and other things aren't meaningful here, so just
  // return having computed an empty Memo so that we don't come
  // here again. The assumption here is that client code won't
  // be asking about such values very often.
  else
    return M;

  // Determine if the value is defined inside a loop. This is used
  // to track whether the value is ever used outside the loop, so
  // it'll be set to null if the value is either not defined in a
  // loop or used outside the loop in which it is defined.
  const Loop *L = LI->getLoopFor(DefBB);

  // Track whether the value is used anywhere outside of the block
  // in which it is defined.
  bool LiveOutOfDefBB = false;

  // Examine each use of the value.
  for (Value::use_const_iterator I = V->use_begin(), E = V->use_end();
       I != E; ++I) {
    const User *U = *I;
    const BasicBlock *UseBB = cast<Instruction>(U)->getParent();

    // Note the block in which this use occurs.
    M.Used.insert(UseBB);

    // If the use block doesn't have successors, the value can be
    // considered killed.
    if (succ_begin(UseBB) == succ_end(UseBB))
      M.Killed.insert(UseBB);

    // Observe whether the value is used outside of the loop in which
    // it is defined. Switch to an enclosing loop if necessary.
    for (; L; L = L->getParentLoop())
      if (L->contains(UseBB))
        break;

    // Search for live-through blocks.
    const BasicBlock *BB;
    if (const PHINode *PHI = dyn_cast<PHINode>(U)) {
      // For PHI nodes, start the search at the incoming block paired with the
      // incoming value, which must be dominated by the definition.
      unsigned Num = PHI->getIncomingValueNumForOperand(I.getOperandNo());
      BB = PHI->getIncomingBlock(Num);

      // A PHI-node use means the value is live-out of it's defining block
      // even if that block also contains the only use.
      LiveOutOfDefBB = true;
    } else {
      // Otherwise just start the search at the use.
      BB = UseBB;

      // Note if the use is outside the defining block.
      LiveOutOfDefBB |= UseBB != DefBB;
    }

    // Climb the immediate dominator tree from the use to the definition
    // and mark all intermediate blocks as live-through. Don't do this if
    // the user is a PHI because such users may not be dominated by the
    // definition.
    for (; BB != DefBB; BB = getImmediateDominator(BB, DT)) {
      if (BB != UseBB && !M.LiveThrough.insert(BB))
        break;
    }
  }

  // If the value is defined inside a loop and is not live outside
  // the loop, then each exit block of the loop in which the value
  // is used is a kill block.
  if (L) {
    SmallVector<BasicBlock *, 4> ExitingBlocks;
    L->getExitingBlocks(ExitingBlocks);
    for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
      const BasicBlock *ExitingBlock = ExitingBlocks[i];
      if (M.Used.count(ExitingBlock))
        M.Killed.insert(ExitingBlock);
    }
  }

  // If the value was never used outside the the block in which it was
  // defined, it's killed in that block.
  if (!LiveOutOfDefBB)
    M.Killed.insert(DefBB);

  return M;
}
<|endoftext|>


<commit_before>class RegisterClassDetails
{
public:
private:
    BitSet _members;
};

class RegisterClass
{
public:
private:
    int _index;
};

class ConstantClassDetails
{
public:
    bool matches(int c)
    {
        if (c < _minimum || c > _maximum)
            return false;
        return (c - _minimum) % _step == 0;
    }
private:
    int _minimum;
    int _maximum;
    int _step;
};

class ConstantClass
{
public:
private:
    int _index;
};

class Register
{
public:
private:
    int _index;
};

class BinaryMatcher
{
public:
    virtual bool matches(Byte** data) = 0;
private:
};

class ConstantMatcher : public BinaryMatcher
{
public:
    bool matches(Byte** data)
    {
        if ((*reinterpret_cast<DWord*>(*data) & _mask) >> _shift != _match)
            return false;
        *data += _increment;
        return true;
    }
private:
    DWord _match;
    int _mask;
    int _shift;
    int _increment;
};

class Instruction
{
public:
private:
    InstructionPattern* _pattern;
    Array<Register> _registers;
    Array<int> _constants;
};

class InstructionPattern
{
public:
    bool matches(Byte* data)
    {

    }
private:
    Array<BinaryMatcher> _matchers;
    Array<RegisterClass> _registerHoles;
    Array<ConstantClass> _constantHoles;
};

class Instruction
{
public:
private:
    InstructionPattern* _patter;
    Array<Register> _registers;
    Array<int> _constants;
};

class MachineDescription
{
public:
    Array<InstructionPattern> _patterns;
    Array<RegisterClassDetails> _registerClassDetails;
    Array<ConstantClassDetails> _constantClassDetails;
};
<commit_msg>More machine description<commit_after>class RegisterClassDetails
{
public:
private:
    BitSet _members;
};

class RegisterClass
{
public:
private:
    int _index;
};

class ConstantClassDetails
{
public:
    bool matches(int c)
    {
        if (c < _minimum || c > _maximum)
            return false;
        return (c - _minimum) % _step == 0;
    }
private:
    int _minimum;
    int _maximum;
    int _step;
};

class ConstantClass
{
public:
private:
    int _index;
};

class Register
{
public:
private:
    int _index;
};

class BinaryMatcher
{
public:
    virtual bool matches(Byte** data) = 0;
private:
};

class LiteralMatcher : public BinaryMatcher
{
public:
    bool matches(Byte** data)
    {
        if ((*reinterpret_cast<DWord*>(*data) & _mask) >> _shift != _match)
            return false;
        *data += _increment;
        return true;
    }
private:
    DWord _match;
    int _mask;
    int _shift;
    int _increment;
};

class ConstantMatcher : public BinaryMatcher
{
public:
    bool matches(Byte** data, int* d)
    {
        if ((*reinterpret_cast<DWord*>(*data) & _mask) >> _shift != _match)
            return false;
        *data += _increment;
        return true;
    }
private:
    DWord _match;
    int _mask;
    int _shift;
    int _increment;
};

class Instruction
{
public:
private:
    InstructionPattern* _pattern;
    Array<Register> _registers;
    Array<int> _constants;
};

class InstructionPattern
{
public:
    bool matches(Byte* data)
    {

    }
private:
    Array<BinaryMatcher> _matchers;
    Array<RegisterClass> _registerHoles;
    Array<ConstantClass> _constantHoles;
};

class Instruction
{
public:
private:
    InstructionPattern* _patter;
    Array<Register> _registers;
    Array<int> _constants;
};

class MachineDescription
{
public:
    Array<InstructionPattern> _patterns;
    Array<RegisterClassDetails> _registerClassDetails;
    Array<ConstantClassDetails> _constantClassDetails;
};
<|endoftext|>


<commit_before>#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include "tern/user.h"

#define N 8
#define M 10000

int nwait = 0;
int nexit = 0;
long long sum;
long loops = 6e3;
pthread_mutex_t mutex;
pthread_cond_t cond;

void set_affinity(int core_id) {
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
  CPU_SET(core_id, &cpuset);
  assert(pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) == 0);
}

void* thread_func(void *arg) {
  set_affinity((int)(long)arg);
  for (int j = 0; j < M; j++) {
    pthread_mutex_lock(&mutex);
    nwait++;
    for (long i = 0; i < loops; i++) // This is the key of speedup for parrot: the mutex needs to be a little bit congested.
      sum += i;
    pthread_cond_wait(&cond, &mutex);
    pthread_mutex_unlock(&mutex);
    soba_wait(0);
    for (long i = 0; i < loops; i++)
      sum += i*i*i*i*i*i;
    //fprintf(stderr, "compute thread %u %d\n", (unsigned)thread, sched_getcpu());
  }
}

int main(int argc, char *argv[]) {
  set_affinity(23);
  soba_init(0, N, 20);
  pthread_t th[N];
  int ret;
  pthread_cond_init(&cond, NULL);

  for(unsigned i=0; i<N; ++i) {
    ret  = pthread_create(&th[i], NULL, thread_func, (void*)i);
    assert(!ret && "pthread_create() failed!");
  }

  for (int j = 0; j < M; j++) {
    while (nwait < N) {
      sched_yield();
    }
    pthread_mutex_lock(&mutex);
    nwait = 0;
    //fprintf(stderr, "broadcast %u %d\n", (unsigned)pthread_self(), sched_getcpu());
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex);
  }

  for(unsigned i=0; i<N; ++i)
    pthread_join(th[i], NULL);

  exit(0);
}
<commit_msg>Added a mencoder-like speedup toy program.<commit_after>#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include "tern/user.h"

#define N 8
#define M 10000

int nwait = 0;
int nexit = 0;
volatile long long sum;
long loops = 6e3;
pthread_mutex_t mutex;
pthread_cond_t cond;

void set_affinity(int core_id) {
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
  CPU_SET(core_id, &cpuset);
  assert(pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) == 0);
}

void* thread_func(void *arg) {
  set_affinity((int)(long)arg);
  for (int j = 0; j < M; j++) {
    pthread_mutex_lock(&mutex);
    nwait++;
    for (long i = 0; i < loops; i++) // This is the key of speedup for parrot: the mutex needs to be a little bit congested.
      sum += i;
    pthread_cond_wait(&cond, &mutex);
    pthread_mutex_unlock(&mutex);
    soba_wait(0);
    for (long i = 0; i < loops; i++)
      sum += i*i*i*i*i*i;
    //fprintf(stderr, "compute thread %u %d\n", (unsigned)thread, sched_getcpu());
  }
}

int main(int argc, char *argv[]) {
  set_affinity(23);
  soba_init(0, N, 20);
  pthread_t th[N];
  int ret;
  pthread_cond_init(&cond, NULL);

  for(unsigned i=0; i<N; ++i) {
    ret  = pthread_create(&th[i], NULL, thread_func, (void*)i);
    assert(!ret && "pthread_create() failed!");
  }

  for (int j = 0; j < M; j++) {
    while (nwait < N) {
      sched_yield();
    }
    pthread_mutex_lock(&mutex);
    nwait = 0;
    //fprintf(stderr, "broadcast %u %d\n", (unsigned)pthread_self(), sched_getcpu());
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex);
  }

  for(unsigned i=0; i<N; ++i)
    pthread_join(th[i], NULL);

  exit(0);
}
<|endoftext|>


<commit_before>//===--- GenReflection.cpp - IR generation for nominal type reflection ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR generation of type metadata for struct/class
//  stored properties and enum cases for use with reflection.
//===----------------------------------------------------------------------===//

#include "swift/AST/ArchetypeBuilder.h"
#include "swift/AST/Decl.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/Reflection/Records.h"

#include "ConstantBuilder.h"
#include "IRGenModule.h"

using namespace swift;
using namespace irgen;

class ReflectionMetadataBuilder : public ConstantBuilder<> {
protected:
  void addTypeRef(Module *ModuleContext, CanType type) {
    Mangle::Mangler mangler;
    mangler.setModuleContext(ModuleContext);
    mangler.mangleType(type, 0);
    auto mangledName = IGM.getAddrOfStringForTypeRef(mangler.finalize());
    addRelativeAddress(mangledName);
  }

public:
  ReflectionMetadataBuilder(IRGenModule &IGM) : ConstantBuilder(IGM) {}
};

class AssociatedTypeMetadataBuilder : public ReflectionMetadataBuilder {
  static const uint32_t AssociatedTypeRecordSize = 8;
  ArrayRef<const NominalTypeDecl *> NominalTypeDecls;

  void addDecl(const NominalTypeDecl *Decl) {
    for (auto Conformance : Decl->getAllConformances()) {
      SmallVector<std::pair<StringRef, CanType>, 2> AssociatedTypes;

      auto collectTypeWitness = [&](const AssociatedTypeDecl *AssocTy,
                                    const Substitution &Sub,
                                    const TypeDecl *TD) -> bool {

        Type Subst = Sub.getReplacement();
        if (auto InterfaceTy = ArchetypeBuilder::mapTypeOutOfContext(
            Conformance->getDeclContext(), Subst)) {
          Subst = InterfaceTy;
        }

        AssociatedTypes.push_back({
          AssocTy->getNameStr(),
          Subst->getCanonicalType()
        });
        return false;
      };

      auto ModuleContext = Decl->getModuleContext();

      auto ConformingTy = Conformance->getInterfaceType();
      addTypeRef(ModuleContext, ConformingTy->getCanonicalType());

      auto ProtoTy = Conformance->getProtocol()->getInterfaceType();
      addTypeRef(ModuleContext, ProtoTy->getCanonicalType());

      Conformance->forEachTypeWitness(/*resolver*/ nullptr, collectTypeWitness);

      addConstantInt32(AssociatedTypes.size());
      addConstantInt32(AssociatedTypeRecordSize);

      for (auto AssocTy : AssociatedTypes) {
        auto NameGlobal = IGM.getAddrOfStringForTypeRef(AssocTy.first);
        addRelativeAddress(NameGlobal);
        addTypeRef(ModuleContext, AssocTy.second);
      }
    }
  }

public:
  AssociatedTypeMetadataBuilder(IRGenModule &IGM,
      ArrayRef<const NominalTypeDecl *> NominalTypeDecls)
    : ReflectionMetadataBuilder(IGM), NominalTypeDecls(NominalTypeDecls) {}

  void layout() {
    for (auto decl : NominalTypeDecls)
      addDecl(decl);
  }

  llvm::GlobalVariable *emit() {
    auto tempBase = std::unique_ptr<llvm::GlobalVariable>(
        new llvm::GlobalVariable(IGM.Int8Ty, /*isConstant*/ true,
        llvm::GlobalValue::PrivateLinkage));
    setRelativeAddressBase(tempBase.get());

    layout();
    auto init = getInit();
    auto var = new llvm::GlobalVariable(*IGM.getModule(), init->getType(),
                                        /*isConstant*/ true,
                                        llvm::GlobalValue::PrivateLinkage,
                                        init,
                                        "\x01l__swift3_assocty_metadata");
    var->setSection(IGM.getAssociatedTypeMetadataSectionName());
    var->setAlignment(IGM.getPointerAlignment().getValue());

    auto replacer = llvm::ConstantExpr::getBitCast(var, IGM.Int8PtrTy);
    tempBase->replaceAllUsesWith(replacer);

    return var;
  }
};

class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {

  const uint32_t fieldRecordSize = 12;
  ArrayRef<const NominalTypeDecl *> NominalTypeDecls;

  void addFieldDecl(const ValueDecl *value) {
    swift::reflection::FieldRecordFlags Flags;
    Flags.setIsObjC(value->isObjC());

    addConstantInt32(Flags.getRawValue());

    auto type = value->getInterfaceType()->getCanonicalType();
    addTypeRef(value->getModuleContext(), type);

    if (IGM.Opts.StripReflectionNames) {
      addConstantInt32(0);
    } else {
      auto fieldName = IGM.getAddrOfFieldName(value->getNameStr());
      addRelativeAddress(fieldName);
    }
  }

  void addDecl(const NominalTypeDecl *decl) {
    auto type = decl->getDeclaredInterfaceType()->getCanonicalType();
    addTypeRef(decl->getModuleContext(), type);

    switch (decl->getKind()) {
    case DeclKind::Class:
    case DeclKind::Struct: {
      auto properties = decl->getStoredProperties();
      addConstantInt32(std::distance(properties.begin(), properties.end()));
      addConstantInt32(fieldRecordSize);
      for (auto property : properties)
        addFieldDecl(property);
      break;
    }
    case DeclKind::Enum: {
      auto enumDecl = cast<EnumDecl>(decl);
      auto cases = enumDecl->getAllElements();
      addConstantInt32(std::distance(cases.begin(), cases.end()));
      addConstantInt32(fieldRecordSize);
      for (auto enumCase : cases)
        addFieldDecl(enumCase);
      break;
    }
    default:
      llvm_unreachable("Not a nominal type");
      break;
    }
  }

public:
  FieldTypeMetadataBuilder(IRGenModule &IGM,
      ArrayRef<const NominalTypeDecl *> NominalTypeDecls)
    : ReflectionMetadataBuilder(IGM), NominalTypeDecls(NominalTypeDecls) {}
  void layout() {
    for (auto decl : NominalTypeDecls) {
      addDecl(decl);
    }
  }

  llvm::GlobalVariable *emit() {
    auto tempBase = std::unique_ptr<llvm::GlobalVariable>(
        new llvm::GlobalVariable(IGM.Int8Ty, /*isConstant*/ true,
                                 llvm::GlobalValue::PrivateLinkage));
    setRelativeAddressBase(tempBase.get());

    layout();
    auto init = getInit();
    auto var = new llvm::GlobalVariable(*IGM.getModule(), init->getType(),
                                        /*isConstant*/ true,
                                        llvm::GlobalValue::PrivateLinkage,
                                        init,
                                        "\x01l__swift3_reflection_metadata");
    var->setSection(IGM.getFieldTypeMetadataSectionName());
    var->setAlignment(IGM.getPointerAlignment().getValue());

    auto replacer = llvm::ConstantExpr::getBitCast(var, IGM.Int8PtrTy);
    tempBase->replaceAllUsesWith(replacer);

    return var;
  }
};

static std::string getReflectionSectionName(IRGenModule &IGM,
                                            std::string Base) {
  assert(Base.size() <= 7
         && "Mach-O section name length must be <= 16 characters");
  SmallString<50> SectionName;
  llvm::raw_svector_ostream OS(SectionName);
  switch (IGM.TargetInfo.OutputObjectFormat) {
    case llvm::Triple::MachO:
      OS << "__DATA, __swift3_" << Base << ", regular, no_dead_strip";
      break;
    case llvm::Triple::ELF:
      OS << ".swift3_" << Base;
      break;
    default:
      llvm_unreachable("Don't know how to emit field name table for "
                       "the selected object format.");
  }
  return OS.str();
}

std::string IRGenModule::getFieldTypeMetadataSectionName() {
  return getReflectionSectionName(*this, "fieldmd");
}

std::string IRGenModule::getAssociatedTypeMetadataSectionName() {
  return getReflectionSectionName(*this, "assocty");
}

std::string IRGenModule::getReflectionStringsSectionName() {
  return getReflectionSectionName(*this, "reflstr");
}

std::string IRGenModule::getReflectionTypeRefSectionName() {
  return getReflectionSectionName(*this, "typeref");
}

llvm::Constant *IRGenModule::getAddrOfFieldName(StringRef Name) {
  auto &entry = FieldNames[Name];
  if (entry.second)
    return entry.second;

  entry = createStringConstant(Name, /*willBeRelativelyAddressed*/ true,
                               getReflectionStringsSectionName());
  return entry.second;
}

llvm::Constant *IRGenModule::getAddrOfStringForTypeRef(StringRef Str) {
  auto &entry = StringsForTypeRef[Str];
  if (entry.second)
    return entry.second;

  entry = createStringConstant(Str, /*willBeRelativelyAddressed*/ true,
                               getReflectionTypeRefSectionName());
  return entry.second;
}

llvm::Constant *IRGenModule::emitFieldTypeMetadataRecords() {
  if (Opts.StripReflectionMetadata)
    return nullptr;

  if (NominalTypeDecls.empty())
    return nullptr;

  FieldTypeMetadataBuilder builder(*this, NominalTypeDecls);
  auto var = builder.emit();
  addUsedGlobal(var);
  return var;
}

llvm::Constant *IRGenModule::emitAssociatedTypeMetadataRecords() {
  if (Opts.StripReflectionMetadata)
    return nullptr;

  if (NominalTypeDecls.empty())
    return nullptr;

  AssociatedTypeMetadataBuilder builder(*this, NominalTypeDecls);
  auto var = builder.emit();
  addUsedGlobal(var);
  return var;
}
<commit_msg>Remove unnecessary if auto check - NFC<commit_after>//===--- GenReflection.cpp - IR generation for nominal type reflection ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR generation of type metadata for struct/class
//  stored properties and enum cases for use with reflection.
//===----------------------------------------------------------------------===//

#include "swift/AST/ArchetypeBuilder.h"
#include "swift/AST/Decl.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/Reflection/Records.h"

#include "ConstantBuilder.h"
#include "IRGenModule.h"

using namespace swift;
using namespace irgen;

class ReflectionMetadataBuilder : public ConstantBuilder<> {
protected:
  void addTypeRef(Module *ModuleContext, CanType type) {
    Mangle::Mangler mangler;
    mangler.setModuleContext(ModuleContext);
    mangler.mangleType(type, 0);
    auto mangledName = IGM.getAddrOfStringForTypeRef(mangler.finalize());
    addRelativeAddress(mangledName);
  }

public:
  ReflectionMetadataBuilder(IRGenModule &IGM) : ConstantBuilder(IGM) {}
};

class AssociatedTypeMetadataBuilder : public ReflectionMetadataBuilder {
  static const uint32_t AssociatedTypeRecordSize = 8;
  ArrayRef<const NominalTypeDecl *> NominalTypeDecls;

  void addDecl(const NominalTypeDecl *Decl) {
    for (auto Conformance : Decl->getAllConformances()) {
      SmallVector<std::pair<StringRef, CanType>, 2> AssociatedTypes;

      auto collectTypeWitness = [&](const AssociatedTypeDecl *AssocTy,
                                    const Substitution &Sub,
                                    const TypeDecl *TD) -> bool {

        auto Subst = ArchetypeBuilder::mapTypeOutOfContext(
            Conformance->getDeclContext(), Sub.getReplacement());

        AssociatedTypes.push_back({
          AssocTy->getNameStr(),
          Subst->getCanonicalType()
        });
        return false;
      };

      auto ModuleContext = Decl->getModuleContext();

      auto ConformingTy = Conformance->getInterfaceType();
      addTypeRef(ModuleContext, ConformingTy->getCanonicalType());

      auto ProtoTy = Conformance->getProtocol()->getInterfaceType();
      addTypeRef(ModuleContext, ProtoTy->getCanonicalType());

      Conformance->forEachTypeWitness(/*resolver*/ nullptr, collectTypeWitness);

      addConstantInt32(AssociatedTypes.size());
      addConstantInt32(AssociatedTypeRecordSize);

      for (auto AssocTy : AssociatedTypes) {
        auto NameGlobal = IGM.getAddrOfStringForTypeRef(AssocTy.first);
        addRelativeAddress(NameGlobal);
        addTypeRef(ModuleContext, AssocTy.second);
      }
    }
  }

public:
  AssociatedTypeMetadataBuilder(IRGenModule &IGM,
      ArrayRef<const NominalTypeDecl *> NominalTypeDecls)
    : ReflectionMetadataBuilder(IGM), NominalTypeDecls(NominalTypeDecls) {}

  void layout() {
    for (auto decl : NominalTypeDecls)
      addDecl(decl);
  }

  llvm::GlobalVariable *emit() {
    auto tempBase = std::unique_ptr<llvm::GlobalVariable>(
        new llvm::GlobalVariable(IGM.Int8Ty, /*isConstant*/ true,
        llvm::GlobalValue::PrivateLinkage));
    setRelativeAddressBase(tempBase.get());

    layout();
    auto init = getInit();
    auto var = new llvm::GlobalVariable(*IGM.getModule(), init->getType(),
                                        /*isConstant*/ true,
                                        llvm::GlobalValue::PrivateLinkage,
                                        init,
                                        "\x01l__swift3_assocty_metadata");
    var->setSection(IGM.getAssociatedTypeMetadataSectionName());
    var->setAlignment(IGM.getPointerAlignment().getValue());

    auto replacer = llvm::ConstantExpr::getBitCast(var, IGM.Int8PtrTy);
    tempBase->replaceAllUsesWith(replacer);

    return var;
  }
};

class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {

  const uint32_t fieldRecordSize = 12;
  ArrayRef<const NominalTypeDecl *> NominalTypeDecls;

  void addFieldDecl(const ValueDecl *value) {
    swift::reflection::FieldRecordFlags Flags;
    Flags.setIsObjC(value->isObjC());

    addConstantInt32(Flags.getRawValue());

    auto type = value->getInterfaceType()->getCanonicalType();
    addTypeRef(value->getModuleContext(), type);

    if (IGM.Opts.StripReflectionNames) {
      addConstantInt32(0);
    } else {
      auto fieldName = IGM.getAddrOfFieldName(value->getNameStr());
      addRelativeAddress(fieldName);
    }
  }

  void addDecl(const NominalTypeDecl *decl) {
    auto type = decl->getDeclaredInterfaceType()->getCanonicalType();
    addTypeRef(decl->getModuleContext(), type);

    switch (decl->getKind()) {
    case DeclKind::Class:
    case DeclKind::Struct: {
      auto properties = decl->getStoredProperties();
      addConstantInt32(std::distance(properties.begin(), properties.end()));
      addConstantInt32(fieldRecordSize);
      for (auto property : properties)
        addFieldDecl(property);
      break;
    }
    case DeclKind::Enum: {
      auto enumDecl = cast<EnumDecl>(decl);
      auto cases = enumDecl->getAllElements();
      addConstantInt32(std::distance(cases.begin(), cases.end()));
      addConstantInt32(fieldRecordSize);
      for (auto enumCase : cases)
        addFieldDecl(enumCase);
      break;
    }
    default:
      llvm_unreachable("Not a nominal type");
      break;
    }
  }

public:
  FieldTypeMetadataBuilder(IRGenModule &IGM,
      ArrayRef<const NominalTypeDecl *> NominalTypeDecls)
    : ReflectionMetadataBuilder(IGM), NominalTypeDecls(NominalTypeDecls) {}
  void layout() {
    for (auto decl : NominalTypeDecls) {
      addDecl(decl);
    }
  }

  llvm::GlobalVariable *emit() {
    auto tempBase = std::unique_ptr<llvm::GlobalVariable>(
        new llvm::GlobalVariable(IGM.Int8Ty, /*isConstant*/ true,
                                 llvm::GlobalValue::PrivateLinkage));
    setRelativeAddressBase(tempBase.get());

    layout();
    auto init = getInit();
    auto var = new llvm::GlobalVariable(*IGM.getModule(), init->getType(),
                                        /*isConstant*/ true,
                                        llvm::GlobalValue::PrivateLinkage,
                                        init,
                                        "\x01l__swift3_reflection_metadata");
    var->setSection(IGM.getFieldTypeMetadataSectionName());
    var->setAlignment(IGM.getPointerAlignment().getValue());

    auto replacer = llvm::ConstantExpr::getBitCast(var, IGM.Int8PtrTy);
    tempBase->replaceAllUsesWith(replacer);

    return var;
  }
};

static std::string getReflectionSectionName(IRGenModule &IGM,
                                            std::string Base) {
  assert(Base.size() <= 7
         && "Mach-O section name length must be <= 16 characters");
  SmallString<50> SectionName;
  llvm::raw_svector_ostream OS(SectionName);
  switch (IGM.TargetInfo.OutputObjectFormat) {
    case llvm::Triple::MachO:
      OS << "__DATA, __swift3_" << Base << ", regular, no_dead_strip";
      break;
    case llvm::Triple::ELF:
      OS << ".swift3_" << Base;
      break;
    default:
      llvm_unreachable("Don't know how to emit field name table for "
                       "the selected object format.");
  }
  return OS.str();
}

std::string IRGenModule::getFieldTypeMetadataSectionName() {
  return getReflectionSectionName(*this, "fieldmd");
}

std::string IRGenModule::getAssociatedTypeMetadataSectionName() {
  return getReflectionSectionName(*this, "assocty");
}

std::string IRGenModule::getReflectionStringsSectionName() {
  return getReflectionSectionName(*this, "reflstr");
}

std::string IRGenModule::getReflectionTypeRefSectionName() {
  return getReflectionSectionName(*this, "typeref");
}

llvm::Constant *IRGenModule::getAddrOfFieldName(StringRef Name) {
  auto &entry = FieldNames[Name];
  if (entry.second)
    return entry.second;

  entry = createStringConstant(Name, /*willBeRelativelyAddressed*/ true,
                               getReflectionStringsSectionName());
  return entry.second;
}

llvm::Constant *IRGenModule::getAddrOfStringForTypeRef(StringRef Str) {
  auto &entry = StringsForTypeRef[Str];
  if (entry.second)
    return entry.second;

  entry = createStringConstant(Str, /*willBeRelativelyAddressed*/ true,
                               getReflectionTypeRefSectionName());
  return entry.second;
}

llvm::Constant *IRGenModule::emitFieldTypeMetadataRecords() {
  if (Opts.StripReflectionMetadata)
    return nullptr;

  if (NominalTypeDecls.empty())
    return nullptr;

  FieldTypeMetadataBuilder builder(*this, NominalTypeDecls);
  auto var = builder.emit();
  addUsedGlobal(var);
  return var;
}

llvm::Constant *IRGenModule::emitAssociatedTypeMetadataRecords() {
  if (Opts.StripReflectionMetadata)
    return nullptr;

  if (NominalTypeDecls.empty())
    return nullptr;

  AssociatedTypeMetadataBuilder builder(*this, NominalTypeDecls);
  auto var = builder.emit();
  addUsedGlobal(var);
  return var;
}
<|endoftext|>


<commit_before>#include "MountEvent.h"

#if defined(__linux__)
#include <linux/version.h>
#elif !defined(KERNEL_VERSION)
#define LINUX_VERSION_CODE 0
#define KERNEL_VERSION(a, b, c) 0
#endif

#if defined(__linux__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) /* Linux 2.6.30+ */
// Linux
# include <sys/epoll.h>
#elif defined(__unix__) || defined(__unix)      /* Generic UNIX */ || \
      (defined(__APPLE__) && defined(__MACH__)) /* Darwin       */
// PDTK
# include "TimerEvent.h"
#else
# error Unsupported platform! >:(
#endif

// POSIX++
#include <climits>
#include <cstring>

#ifndef MOUNT_TABLE_FILE
#define MOUNT_TABLE_FILE  "/etc/mtab"
#endif

MountEvent::MountEvent(void) noexcept
  : m_timer(nullptr)
{
    parse_table(m_table, MOUNT_TABLE_FILE);

    EventBackend::callback_t comparison_func =
        [this](posix::fd_t, native_flags_t) noexcept
        {
          std::set<struct fsentry_t> new_table;
          parse_table(new_table, MOUNT_TABLE_FILE);

          for(auto& entry : new_table)
            if(m_table.find(entry) == m_table.end())
              Object::enqueue_copy<std::string, std::string>(mounted, std::string(entry.device), std::string(entry.path));

          for(auto& entry : m_table)
            if(new_table.find(entry) == new_table.end())
              Object::enqueue_copy<std::string, std::string>(unmounted, std::string(entry.device), std::string(entry.path));

          m_table = new_table;
        };

#if defined(__linux__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) /* Linux 2.6.30+ */
    m_fd = posix::open(MOUNT_TABLE_FILE, O_RDONLY | O_NONBLOCK);
    EventBackend::add(m_fd, EPOLLERR | EPOLLPRI, comparison_func); // connect FD with flags to comparison_func
#elif defined(__unix__) || defined(__unix)      /* Generic UNIX */ || \
      (defined(__APPLE__) && defined(__MACH__)) /* Darwin       */
    m_timer = new TimerEvent();
    m_timer->start(10000000, 10000000); // once per 10 seconds
    Object::connect(m_timer->expired, fslot_t<void>([this](void) noexcept { comparison_func(0,0) }));
#endif
}

MountEvent::~MountEvent(void) noexcept
{
#if defined(__linux__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) /* Linux 2.6.30+ */
  EventBackend::remove(m_fd, EPOLLERR | EPOLLPRI); // disconnect FD with flags from signal
  posix::close(m_fd);
#elif defined(__unix__) || defined(__unix)      /* Generic UNIX */ || \
      (defined(__APPLE__) && defined(__MACH__)) /* Darwin       */
  if(m_timer != nullptr)
    delete m_timer;
  m_timer = nullptr;
#endif
}

<commit_msg>grow up, Darwin. -_-<commit_after>#include "MountEvent.h"

#if defined(__linux__)
#include <linux/version.h>
#elif !defined(KERNEL_VERSION)
#define LINUX_VERSION_CODE 0
#define KERNEL_VERSION(a, b, c) 0
#endif

#if defined(__linux__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) /* Linux 2.6.30+ */
// Linux
# include <sys/epoll.h>
#elif defined(__unix__) || defined(__unix)      /* Generic UNIX */ || \
      (defined(__APPLE__) && defined(__MACH__)) /* Darwin       */
// PDTK
# include "TimerEvent.h"
#else
# error Unsupported platform! >:(
#endif

// POSIX++
#include <climits>
#include <cstring>

#ifndef MOUNT_TABLE_FILE
#define MOUNT_TABLE_FILE  "/etc/mtab"
#endif

MountEvent::MountEvent(void) noexcept
  : m_timer(nullptr)
{
    parse_table(m_table, MOUNT_TABLE_FILE);

    EventBackend::callback_t comparison_func =
        [this](posix::fd_t, native_flags_t) noexcept
        {
          std::set<struct fsentry_t> new_table;
          parse_table(new_table, MOUNT_TABLE_FILE);

          for(auto& entry : new_table)
            if(m_table.find(entry) == m_table.end())
            {
              std::string device(entry.device);
              std::string path (entry.path);
              Object::enqueue(mounted, device, path);
            }

          for(auto& entry : m_table)
            if(new_table.find(entry) == new_table.end())
            {
              std::string device(entry.device);
              std::string path (entry.path);
              Object::enqueue(mounted, device, path);
            }

          m_table = new_table;
        };

#if defined(__linux__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) /* Linux 2.6.30+ */
    m_fd = posix::open(MOUNT_TABLE_FILE, O_RDONLY | O_NONBLOCK);
    EventBackend::add(m_fd, EPOLLERR | EPOLLPRI, comparison_func); // connect FD with flags to comparison_func
#elif defined(__unix__) || defined(__unix)      /* Generic UNIX */ || \
      (defined(__APPLE__) && defined(__MACH__)) /* Darwin       */
    m_timer = new TimerEvent();
    m_timer->start(10000000, 10000000); // once per 10 seconds
    Object::connect(m_timer->expired, fslot_t<void>([this](void) noexcept { comparison_func(0,0) }));
#endif
}

MountEvent::~MountEvent(void) noexcept
{
#if defined(__linux__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) /* Linux 2.6.30+ */
  EventBackend::remove(m_fd, EPOLLERR | EPOLLPRI); // disconnect FD with flags from signal
  posix::close(m_fd);
#elif defined(__unix__) || defined(__unix)      /* Generic UNIX */ || \
      (defined(__APPLE__) && defined(__MACH__)) /* Darwin       */
  if(m_timer != nullptr)
    delete m_timer;
  m_timer = nullptr;
#endif
}

<|endoftext|>