<commit_before>// Copyright 2020 Google LLC
//
// 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 "google/cloud/pubsub/internal/subscription_lease_management.h"
#include <chrono>

namespace google {
namespace cloud {
namespace pubsub_internal {
inline namespace GOOGLE_CLOUD_CPP_PUBSUB_NS {

std::chrono::seconds constexpr SubscriptionLeaseManagement::kMinimumAckDeadline;
std::chrono::seconds constexpr SubscriptionLeaseManagement::kAckDeadlineSlack;

void SubscriptionLeaseManagement::Start(BatchCallback cb) {
  auto weak = std::weak_ptr<SubscriptionLeaseManagement>(shared_from_this());
  child_->Start(
      [weak, cb](StatusOr<google::pubsub::v1::StreamingPullResponse> r) {
        if (auto self = weak.lock()) self->OnRead(r);
        cb(std::move(r));
      });
}

void SubscriptionLeaseManagement::Shutdown() {
  std::unique_lock<std::mutex> lk(mu_);
  // Cancel any existing timers.
  if (refresh_timer_.valid()) refresh_timer_.cancel();
  // Schedule a nack for each pending message, using the existing executor.
  NackAll(std::move(lk));
  child_->Shutdown();
}

void SubscriptionLeaseManagement::AckMessage(std::string const& ack_id) {
  std::unique_lock<std::mutex> lk(mu_);
  leases_.erase(ack_id);
  lk.unlock();
  child_->AckMessage(ack_id);
}

void SubscriptionLeaseManagement::NackMessage(std::string const& ack_id) {
  std::unique_lock<std::mutex> lk(mu_);
  leases_.erase(ack_id);
  lk.unlock();
  child_->NackMessage(ack_id);
}

void SubscriptionLeaseManagement::BulkNack(std::vector<std::string> ack_ids) {
  std::unique_lock<std::mutex> lk(mu_);
  for (auto const& id : ack_ids) leases_.erase(id);
  lk.unlock();
  child_->BulkNack(std::move(ack_ids));
}

// Users of this class should have no need to call ExtendLeases(); they create
// it to automate lease management after all. We could create a hierarchy of
// classes for "BatchSourceWithoutExtendLeases", but that seems like overkill.
void SubscriptionLeaseManagement::ExtendLeases(std::vector<std::string>,
                                               std::chrono::seconds) {}

void SubscriptionLeaseManagement::OnRead(
    StatusOr<google::pubsub::v1::StreamingPullResponse> const& response) {
  if (!response) {
    shutdown_manager_->MarkAsShutdown(__func__, response.status());
    std::unique_lock<std::mutex> lk(mu_);
    // Cancel any existing timers.
    if (refresh_timer_.valid()) refresh_timer_.cancel();
    return;
  }
  std::unique_lock<std::mutex> lk(mu_);
  auto const now = std::chrono::system_clock::now();
  auto const estimated_server_deadline = now + std::chrono::seconds(10);
  auto const handling_deadline = now + max_deadline_time_;
  for (auto const& rm : response->received_messages()) {
    leases_.emplace(rm.ack_id(),
                    LeaseStatus{estimated_server_deadline, handling_deadline});
  }
  // Setup a timer to refresh the message leases. We do not want to immediately
  // refresh them because there is a good chance they will be handled before
  // the minimum lease time, and it seems wasteful to refresh the lease just to
  // quickly turnaround and ack or nack the message.
  StartRefreshTimer(std::move(lk),
                    std::chrono::system_clock::now() + kMinimumAckDeadline);
}

void SubscriptionLeaseManagement::RefreshMessageLeases(
    std::unique_lock<std::mutex> lk) {
  using seconds = std::chrono::seconds;

  if (leases_.empty() || refreshing_leases_) return;

  std::vector<std::string> ack_ids;
  ack_ids.reserve(leases_.size());
  auto extension = max_deadline_extension_;
  auto const now = std::chrono::system_clock::now();
  for (auto const& kv : leases_) {
    // This message lease cannot be extended any further, and we do not want to
    // send an extension of 0 seconds because that is a nack.
    if (kv.second.handling_deadline < now + seconds(1)) continue;
    auto const message_extension =
        std::chrono::duration_cast<seconds>(kv.second.handling_deadline - now);
    extension = (std::min)(extension, message_extension);
    ack_ids.push_back(kv.first);
  }
  auto const new_deadline = now + extension;
  if (ack_ids.empty()) {
    StartRefreshTimer(std::move(lk), new_deadline);
    return;
  }
  lk.unlock();
  child_->ExtendLeases(ack_ids, extension);
  lk.lock();
  for (auto const& ack : ack_ids) {
    auto i = leases_.find(ack);
    if (i == leases_.end()) continue;
    i->second.estimated_server_deadline = new_deadline;
  }
  StartRefreshTimer(std::move(lk), new_deadline);
}

void SubscriptionLeaseManagement::StartRefreshTimer(
    std::unique_lock<std::mutex>,
    std::chrono::system_clock::time_point new_server_deadline) {
  std::weak_ptr<SubscriptionLeaseManagement> weak = shared_from_this();
  auto deadline = new_server_deadline - kAckDeadlineSlack;

  shutdown_manager_->StartOperation(__func__, "OnRefreshTimer", [&] {
    if (refresh_timer_.valid()) refresh_timer_.cancel();
    using TimerFuture = future<StatusOr<std::chrono::system_clock::time_point>>;
    cq_.MakeDeadlineTimer(deadline).then([weak](TimerFuture tp) {
      if (auto self = weak.lock()) self->OnRefreshTimer(!tp.get());
    });
  });
}

void SubscriptionLeaseManagement::OnRefreshTimer(bool cancelled) {
  if (shutdown_manager_->FinishedOperation(__func__)) return;
  if (cancelled) return;
  RefreshMessageLeases(std::unique_lock<std::mutex>(mu_));
}

void SubscriptionLeaseManagement::NackAll(std::unique_lock<std::mutex> lk) {
  if (leases_.empty()) return;
  std::vector<std::string> ack_ids;
  ack_ids.reserve(leases_.size());
  for (auto const& kv : leases_) {
    ack_ids.push_back(kv.first);
  }
  lk.unlock();
  BulkNack(std::move(ack_ids));
}

}  // namespace GOOGLE_CLOUD_CPP_PUBSUB_NS
}  // namespace pubsub_internal
}  // namespace cloud
}  // namespace google
<commit_msg>fix(pubsub): save refresh timer for cancellation (#6662)<commit_after>// Copyright 2020 Google LLC
//
// 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 "google/cloud/pubsub/internal/subscription_lease_management.h"
#include <chrono>

namespace google {
namespace cloud {
namespace pubsub_internal {
inline namespace GOOGLE_CLOUD_CPP_PUBSUB_NS {

std::chrono::seconds constexpr SubscriptionLeaseManagement::kMinimumAckDeadline;
std::chrono::seconds constexpr SubscriptionLeaseManagement::kAckDeadlineSlack;

void SubscriptionLeaseManagement::Start(BatchCallback cb) {
  auto weak = std::weak_ptr<SubscriptionLeaseManagement>(shared_from_this());
  child_->Start(
      [weak, cb](StatusOr<google::pubsub::v1::StreamingPullResponse> r) {
        if (auto self = weak.lock()) self->OnRead(r);
        cb(std::move(r));
      });
}

void SubscriptionLeaseManagement::Shutdown() {
  std::unique_lock<std::mutex> lk(mu_);
  // Cancel any existing timers.
  if (refresh_timer_.valid()) refresh_timer_.cancel();
  // Schedule a nack for each pending message, using the existing executor.
  NackAll(std::move(lk));
  child_->Shutdown();
}

void SubscriptionLeaseManagement::AckMessage(std::string const& ack_id) {
  std::unique_lock<std::mutex> lk(mu_);
  leases_.erase(ack_id);
  lk.unlock();
  child_->AckMessage(ack_id);
}

void SubscriptionLeaseManagement::NackMessage(std::string const& ack_id) {
  std::unique_lock<std::mutex> lk(mu_);
  leases_.erase(ack_id);
  lk.unlock();
  child_->NackMessage(ack_id);
}

void SubscriptionLeaseManagement::BulkNack(std::vector<std::string> ack_ids) {
  std::unique_lock<std::mutex> lk(mu_);
  for (auto const& id : ack_ids) leases_.erase(id);
  lk.unlock();
  child_->BulkNack(std::move(ack_ids));
}

// Users of this class should have no need to call ExtendLeases(); they create
// it to automate lease management after all. We could create a hierarchy of
// classes for "BatchSourceWithoutExtendLeases", but that seems like overkill.
void SubscriptionLeaseManagement::ExtendLeases(std::vector<std::string>,
                                               std::chrono::seconds) {}

void SubscriptionLeaseManagement::OnRead(
    StatusOr<google::pubsub::v1::StreamingPullResponse> const& response) {
  if (!response) {
    shutdown_manager_->MarkAsShutdown(__func__, response.status());
    std::unique_lock<std::mutex> lk(mu_);
    // Cancel any existing timers.
    if (refresh_timer_.valid()) refresh_timer_.cancel();
    return;
  }
  std::unique_lock<std::mutex> lk(mu_);
  auto const now = std::chrono::system_clock::now();
  auto const estimated_server_deadline = now + std::chrono::seconds(10);
  auto const handling_deadline = now + max_deadline_time_;
  for (auto const& rm : response->received_messages()) {
    leases_.emplace(rm.ack_id(),
                    LeaseStatus{estimated_server_deadline, handling_deadline});
  }
  // Setup a timer to refresh the message leases. We do not want to immediately
  // refresh them because there is a good chance they will be handled before
  // the minimum lease time, and it seems wasteful to refresh the lease just to
  // quickly turnaround and ack or nack the message.
  StartRefreshTimer(std::move(lk),
                    std::chrono::system_clock::now() + kMinimumAckDeadline);
}

void SubscriptionLeaseManagement::RefreshMessageLeases(
    std::unique_lock<std::mutex> lk) {
  using seconds = std::chrono::seconds;

  if (leases_.empty() || refreshing_leases_) return;

  std::vector<std::string> ack_ids;
  ack_ids.reserve(leases_.size());
  auto extension = max_deadline_extension_;
  auto const now = std::chrono::system_clock::now();
  for (auto const& kv : leases_) {
    // This message lease cannot be extended any further, and we do not want to
    // send an extension of 0 seconds because that is a nack.
    if (kv.second.handling_deadline < now + seconds(1)) continue;
    auto const message_extension =
        std::chrono::duration_cast<seconds>(kv.second.handling_deadline - now);
    extension = (std::min)(extension, message_extension);
    ack_ids.push_back(kv.first);
  }
  auto const new_deadline = now + extension;
  if (ack_ids.empty()) {
    StartRefreshTimer(std::move(lk), new_deadline);
    return;
  }
  lk.unlock();
  child_->ExtendLeases(ack_ids, extension);
  lk.lock();
  for (auto const& ack : ack_ids) {
    auto i = leases_.find(ack);
    if (i == leases_.end()) continue;
    i->second.estimated_server_deadline = new_deadline;
  }
  StartRefreshTimer(std::move(lk), new_deadline);
}

void SubscriptionLeaseManagement::StartRefreshTimer(
    std::unique_lock<std::mutex>,
    std::chrono::system_clock::time_point new_server_deadline) {
  std::weak_ptr<SubscriptionLeaseManagement> weak = shared_from_this();
  auto deadline = new_server_deadline - kAckDeadlineSlack;

  shutdown_manager_->StartOperation(__func__, "OnRefreshTimer", [&] {
    using TimerFuture = future<StatusOr<std::chrono::system_clock::time_point>>;
    if (refresh_timer_.valid()) refresh_timer_.cancel();
    refresh_timer_ =
        cq_.MakeDeadlineTimer(deadline).then([weak](TimerFuture tp) {
          if (auto self = weak.lock()) self->OnRefreshTimer(!tp.get());
        });
  });
}

void SubscriptionLeaseManagement::OnRefreshTimer(bool cancelled) {
  if (shutdown_manager_->FinishedOperation(__func__)) return;
  if (cancelled) return;
  RefreshMessageLeases(std::unique_lock<std::mutex>(mu_));
}

void SubscriptionLeaseManagement::NackAll(std::unique_lock<std::mutex> lk) {
  if (leases_.empty()) return;
  std::vector<std::string> ack_ids;
  ack_ids.reserve(leases_.size());
  for (auto const& kv : leases_) {
    ack_ids.push_back(kv.first);
  }
  lk.unlock();
  BulkNack(std::move(ack_ids));
}

}  // namespace GOOGLE_CLOUD_CPP_PUBSUB_NS
}  // namespace pubsub_internal
}  // namespace cloud
}  // namespace google
<|endoftext|>


<commit_before>//   Copyright 2015 Patrick Putnam
//
//   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.
#ifndef CLOTHO_BATCH_CROSSOVER_MTWE_GENERATOR_HPP_
#define CLOTHO_BATCH_CROSSOVER_MTWE_GENERATOR_HPP_

#include "clotho/data_spaces/crossover/batch_crossover_tasks.hpp"
#include "clotho/recombination/sequence_bias_parameter.hpp"
#include "clotho/recombination/recombination_rate_parameter.hpp"
#include "clotho/data_spaces/task/thread_pool.hpp"

#include "clotho/data_spaces/generators/position_distribution_helper.hpp"
#include "clotho/data_spaces/generators/crossover_event_distribution_helper.hpp"

#include <boost/random/bernoulli_distribution.hpp>

namespace clotho {
namespace genetics {

template < class RNG, class SequenceSpaceType, class AlleleSpaceType >
class BatchCrossoverMTWE {
public:
    typedef SequenceSpaceType       sequence_space_type;
    typedef AlleleSpaceType         allele_space_type;

    typedef typename position_distribution_helper< typename allele_space_type::position_type >::type  position_distribution_type;
    typedef typename crossover_event_distribution_helper< double >::type                    event_distribution_type;

    BatchCrossoverMTWE( RNG * rng, boost::property_tree::ptree & config ) :
        m_rng( rng )
        , m_seq_bias(config)
        , m_recomb_rate(config)
    { }

    template < class SelectionType, class PoolType >
    void operator()( const SelectionType & parents, sequence_space_type * parental, sequence_space_type * offspring, allele_space_type * alleles, PoolType & pool ) {

        batch_generate( parents, parental, offspring, alleles, pool );
    }

    virtual ~BatchCrossoverMTWE() {}

protected:

    template < class SelectionType, class PoolType >
    void batch_generate( const SelectionType & parents, sequence_space_type * parental, sequence_space_type * offspring, allele_space_type * alleles, PoolType & pool ) {
#ifdef  DEBUGGING
        BOOST_LOG_TRIVIAL(debug) << "Launching crossover batch jobs";
#endif  // DEBUGGING
        typedef typename SelectionType::mate_pair_vector                            mate_pair_type;
        typedef batch_crossover_taskwe< mate_pair_type, SequenceSpaceType, AlleleSpaceType >     crossover_task_type;

        typedef typename crossover_task_type::event_pool_type                       event_pool_type;
        typedef typename crossover_task_type::event_lookup_type                     event_lookup_type;
        typedef typename crossover_task_type::bias_pool_type                        bias_pool_type;

        event_pool_type ep = crossover_task_type::make_event_pool();
        event_lookup_type el;

        fill_event_pool( ep, el, 2 * parents.size() );

        bias_pool_type bp;
        fill_bias_pool( bp, 2 * parents.size() );

        const size_t TC = pool.pool_size() + 1;   // + 1 for master thread

        const size_t  BATCH_SIZE = (parents.size() / TC) + ((parents.size() % TC > 0)? 1 : 0);

        unsigned int off_idx = 0;
        while( off_idx + BATCH_SIZE < parents.size() ) {
            unsigned int off_end = off_idx + BATCH_SIZE;

#ifdef DEBUGGING
            BOOST_LOG_TRIVIAL(info) << "Batch Crossover: [" << off_idx << ", " << off_end << ");";
#endif  // DEBUGGING

            crossover_task_type x( parental, offspring, alleles, ep, off_idx, parents.begin() + off_idx, parents.begin() + off_end, el.begin() + 2 * off_idx, el.begin() + 2 * off_end,  bp.begin() + 2 * off_idx, bp.begin() + 2 * off_end );
            pool.post( x );

            off_idx = off_end;
        }

        if( off_idx < parents.size() ){
#ifdef DEBUGGING
            BOOST_LOG_TRIVIAL(info) << "Batch Crossover: [" << off_idx << ", " << parents.size() << ");";
#endif  // DEBUGGING

            crossover_task_type t( parental, offspring, alleles, ep, off_idx, parents.begin() + off_idx, parents.end(), el.begin() + 2 * off_idx, el.end(), bp.begin() + 2 * off_idx, bp.end());
            t();
        }

        pool.sync();
#ifdef DEBUGGING
        BOOST_LOG_TRIVIAL(debug) << "Thread pool synced";
#endif // DEBUGGING
    }

    template < class EventPool, class EventLookup >
    void fill_event_pool( EventPool & events, EventLookup & lookup, unsigned int offspring_pop_size ) {
        event_distribution_type event_dist( m_recomb_rate.m_rho );
        position_distribution_type pos_dist;

        while( offspring_pop_size-- ) {
            lookup.push_back( events->size() );
            unsigned int N = event_dist( *m_rng );
            while( N-- ) {
                events->push_back( pos_dist( *m_rng ) );
            }
        }

        lookup.push_back( events->size() );

        BOOST_LOG_TRIVIAL( info ) << "Events Count: " << events->size() << "; Lookup size: " << lookup.size();
    }

    template < class BiasPool >
    void fill_bias_pool( BiasPool & bp, unsigned int offspring_pop_size ) {
        boost::random::bernoulli_distribution< double > bias_dist( m_seq_bias.m_bias );

        while( offspring_pop_size-- ) {
            bp.push_back( bias_dist( *m_rng ) );
        }
    }

    RNG * m_rng;
    sequence_bias_parameter< double > m_seq_bias;
    recombination_rate_parameter< double > m_recomb_rate;
};

}   // namespace genetics
}   // namespace clotho

#endif  // CLOTHO_BATCH_CROSSOVER_MTWE_GENERATOR_HPP_
<commit_msg>Adding comments<commit_after>//   Copyright 2015 Patrick Putnam
//
//   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.
#ifndef CLOTHO_BATCH_CROSSOVER_MTWE_GENERATOR_HPP_
#define CLOTHO_BATCH_CROSSOVER_MTWE_GENERATOR_HPP_

#include "clotho/data_spaces/crossover/batch_crossover_tasks.hpp"
#include "clotho/recombination/sequence_bias_parameter.hpp"
#include "clotho/recombination/recombination_rate_parameter.hpp"
#include "clotho/data_spaces/task/thread_pool.hpp"

#include "clotho/data_spaces/generators/position_distribution_helper.hpp"
#include "clotho/data_spaces/generators/crossover_event_distribution_helper.hpp"

#include <boost/random/bernoulli_distribution.hpp>

namespace clotho {
namespace genetics {

/**
 *
 * Single pool of crossover events (WE => with events)
 * Common event pool intended to make simulations more reproduceable
 *
 */
template < class RNG, class SequenceSpaceType, class AlleleSpaceType >
class BatchCrossoverMTWE {
public:
    typedef SequenceSpaceType       sequence_space_type;
    typedef AlleleSpaceType         allele_space_type;

    typedef typename position_distribution_helper< typename allele_space_type::position_type >::type  position_distribution_type;
    typedef typename crossover_event_distribution_helper< double >::type                    event_distribution_type;

    BatchCrossoverMTWE( RNG * rng, boost::property_tree::ptree & config ) :
        m_rng( rng )
        , m_seq_bias(config)
        , m_recomb_rate(config)
    { }

    template < class SelectionType, class PoolType >
    void operator()( const SelectionType & parents, sequence_space_type * parental, sequence_space_type * offspring, allele_space_type * alleles, PoolType & pool ) {

        batch_generate( parents, parental, offspring, alleles, pool );
    }

    virtual ~BatchCrossoverMTWE() {}

protected:

    template < class SelectionType, class PoolType >
    void batch_generate( const SelectionType & parents, sequence_space_type * parental, sequence_space_type * offspring, allele_space_type * alleles, PoolType & pool ) {
#ifdef  DEBUGGING
        BOOST_LOG_TRIVIAL(debug) << "Launching crossover batch jobs";
#endif  // DEBUGGING
        typedef typename SelectionType::mate_pair_vector                            mate_pair_type;
        typedef batch_crossover_taskwe< mate_pair_type, SequenceSpaceType, AlleleSpaceType >     crossover_task_type;

        typedef typename crossover_task_type::event_pool_type                       event_pool_type;
        typedef typename crossover_task_type::event_lookup_type                     event_lookup_type;
        typedef typename crossover_task_type::bias_pool_type                        bias_pool_type;

        // generate a new event pool for every generation
        event_pool_type ep = crossover_task_type::make_event_pool();
        event_lookup_type el;

        fill_event_pool( ep, el, 2 * parents.size() );

        bias_pool_type bp;
        fill_bias_pool( bp, 2 * parents.size() );

        const size_t TC = pool.pool_size() + 1;   // + 1 for master thread

        const size_t  BATCH_SIZE = (parents.size() / TC) + ((parents.size() % TC > 0)? 1 : 0);

        unsigned int off_idx = 0;
        while( off_idx + BATCH_SIZE < parents.size() ) {
            unsigned int off_end = off_idx + BATCH_SIZE;

#ifdef DEBUGGING
            BOOST_LOG_TRIVIAL(info) << "Batch Crossover: [" << off_idx << ", " << off_end << ");";
#endif  // DEBUGGING

            crossover_task_type x( parental, offspring, alleles, ep, off_idx, parents.begin() + off_idx, parents.begin() + off_end, el.begin() + 2 * off_idx, el.begin() + 2 * off_end,  bp.begin() + 2 * off_idx, bp.begin() + 2 * off_end );
            pool.post( x );

            off_idx = off_end;
        }

        if( off_idx < parents.size() ){
#ifdef DEBUGGING
            BOOST_LOG_TRIVIAL(info) << "Batch Crossover: [" << off_idx << ", " << parents.size() << ");";
#endif  // DEBUGGING

            crossover_task_type t( parental, offspring, alleles, ep, off_idx, parents.begin() + off_idx, parents.end(), el.begin() + 2 * off_idx, el.end(), bp.begin() + 2 * off_idx, bp.end());
            t();
        }

        pool.sync();
#ifdef DEBUGGING
        BOOST_LOG_TRIVIAL(debug) << "Thread pool synced";
#endif // DEBUGGING
    }

    template < class EventPool, class EventLookup >
    void fill_event_pool( EventPool & events, EventLookup & lookup, unsigned int offspring_pop_size ) {
        event_distribution_type event_dist( m_recomb_rate.m_rho );
        position_distribution_type pos_dist;

        lookup.reserve( offspring_pop_size + 1);
        events->reserve( offspring_pop_size );

        while( offspring_pop_size-- ) {
            lookup.push_back( events->size() );
            unsigned int N = event_dist( *m_rng );
            while( N-- ) {
                events->push_back( pos_dist( *m_rng ) );
            }
        }

        lookup.push_back( events->size() );

        BOOST_LOG_TRIVIAL( info ) << "Events Count: " << events->size() << "; Lookup size: " << lookup.size();
    }

    template < class BiasPool >
    void fill_bias_pool( BiasPool & bp, unsigned int offspring_pop_size ) {
        boost::random::bernoulli_distribution< double > bias_dist( m_seq_bias.m_bias );
        bp.reserve( offspring_pop_size );

        while( offspring_pop_size-- ) {
            bp.push_back( bias_dist( *m_rng ) );
        }
    }

    RNG * m_rng;
    sequence_bias_parameter< double > m_seq_bias;
    recombination_rate_parameter< double > m_recomb_rate;
};

}   // namespace genetics
}   // namespace clotho

#endif  // CLOTHO_BATCH_CROSSOVER_MTWE_GENERATOR_HPP_
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "AutoPacket.h"
#include "Autowired.h"
#include "AutoPacketFactory.h"
#include "AutoPacketProfiler.h"
#include "ContextEnumerator.h"
#include "SatCounter.h"
#include <list>

AutoPacket::AutoPacket(AutoPacketFactory& factory)
{
  // Traverse all contexts, adding their packet subscriber vectors one at a time:
  for(const auto& curContext : ContextEnumerator(factory.GetContext())) {
    AutowiredFast<AutoPacketFactory> curFactory(curContext);
    if(curFactory)
      // Only insert if this context actually has a packet factory
      curFactory->AppendAutoFiltersTo(m_satCounters);
  }

  // Prime the satisfaction graph for each element:
  for(auto& satCounter : m_satCounters) {
    for(
      auto pCur = satCounter.GetAutoFilterInput();
      *pCur;
      pCur++
    ) {
      DecorationDisposition& entry = m_decorations[*pCur->ti];

      // Decide what to do with this entry:
      switch(pCur->subscriberType) {
      case inTypeInvalid:
        // Should never happen--trivially ignore this entry
        break;
      case inTypeRequired:
        entry.m_subscribers.push_back(std::make_pair(&satCounter, true));
        break;
      case inTypeOptional:
        entry.m_subscribers.push_back(std::make_pair(&satCounter, false));
        break;
      case outTypeRef:
      case outTypeRefAutoReady:
        // We don't do anything with these types.
        // Optionally, we might want to register them as outputs, or do some kind
        // of runtime detection that a multi-satisfaction case exists--but for now,
        // we just trivially ignore them.
        break;
      }
    }
  }

  // Invoke any output-only AutoFilter routines
  Initialize();
}

AutoPacket::~AutoPacket() {
  // Last chance for AutoFilter call
  ResolveOptions();
}

ObjectPool<AutoPacket> AutoPacket::CreateObjectPool(AutoPacketFactory& factory) {
  return ObjectPool<AutoPacket>(
    ~0,
    ~0,
    [&factory] { return new AutoPacket(factory); },
    [] (AutoPacket& packet) {
      // Last chance for AutoFilter optional calls
      packet.ResolveOptions();

      // Reinitialize the whole packet:
      packet.Initialize();
    }
  );
}

void AutoPacket::ResolveOptions(void) {
  // Queue calls to ensure that calls to Decorate inside of AutoFilter methods
  // will NOT effect the resolution of optional arguments.
  std::list<SatCounter*> callQueue;
  {
    boost::lock_guard<boost::mutex> lk(m_lock);
    for(auto& decoration : m_decorations)
      for(auto& satCounter : decoration.second.m_subscribers)
        if(!satCounter.second)
          if(satCounter.first->Resolve())
            callQueue.push_back(satCounter.first);
  }
  for (SatCounter* call : callQueue)
    call->CallAutoFilter(*this);
}

void AutoPacket::MarkUnsatisfiable(const std::type_info& info) {
  DecorationDisposition* decoration;
  {
    boost::lock_guard<boost::mutex> lk(m_lock);
    auto dFind = m_decorations.find(info);
    if(dFind == m_decorations.end())
      // Trivial return, there's no subscriber to this decoration and so we have nothing to do
      return;
    decoration = &dFind->second;
  }

  // Update everything
  for(auto& satCounter : decoration->m_subscribers) {
    if(satCounter.second)
      // Entry is mandatory, leave it unsatisfaible
      continue;

    // Entry is optional, we will call if we're satisfied after decrementing this optional field
    if(satCounter.first->Decrement(false))
        satCounter.first->CallAutoFilter(*this);
  }
}

void AutoPacket::UpdateSatisfaction(const std::type_info& info) {
  DecorationDisposition* decoration;
  {
    boost::lock_guard<boost::mutex> lk(m_lock);
    auto dFind = m_decorations.find(info);
    if(dFind == m_decorations.end())
      // Trivial return, there's no subscriber to this decoration and so we have nothing to do
      return;
    decoration = &dFind->second;
  }

  // Update everything
  for(auto& satCounter : decoration->m_subscribers)
    if(satCounter.first->Decrement(satCounter.second))
        satCounter.first->CallAutoFilter(*this);
}

void AutoPacket::PulseSatisfaction(DecorationDisposition* pTypeSubs[], size_t nInfos) {
  // First pass, decrement what we can:
  for(size_t i = nInfos; i--;) {
    for(std::pair<SatCounter*, bool>& subscriber : pTypeSubs[i]->m_subscribers) {
      SatCounter* cur = subscriber.first;
      if(
        // We only care about mandatory inputs
        subscriber.second &&

        // We only care about sat counters that aren't deferred--skip everyone else
        // Deferred calls will be too late.
        !cur->IsDeferred() &&

        // Now do the decrementation, and only proceed if the decremented value is zero
        !--cur->remaining
      )
        // Finally, a call is safe to make on this type
        cur->CallAutoFilter(*this);
    }
  }

  // Reset all counters
  // since data in this call will not be available subsequently
  for(size_t i = nInfos; i--;) {
    for(auto& satCounter : pTypeSubs[i]->m_subscribers) {
      auto& cur = satCounter.first;
      if (satCounter.second) {
        ++cur->remaining;
      }
    }
  }
}

void AutoPacket::Initialize(void) {
  // Initialize all counters:
  {
    boost::lock_guard<boost::mutex> lk(m_lock);
    for(auto& satCounter : m_satCounters)
      satCounter.Reset();
    for(auto& decoration : m_decorations)
      decoration.second.Reset();
  }

  // Call all subscribers with no required or optional arguments:
  for (auto& satCounter : m_satCounters)
    if (satCounter)
      satCounter.CallAutoFilter(*this);

  // Initial satisfaction of the AutoPacket:
  UpdateSatisfaction(typeid(AutoPacket));
}

bool AutoPacket::HasSubscribers(const std::type_info& ti) const {
  return m_decorations.count(ti) != 0;
}
<commit_msg>Adding duplicate elimination after saturation counter generation<commit_after>#include "stdafx.h"
#include "AutoPacket.h"
#include "Autowired.h"
#include "AutoPacketFactory.h"
#include "AutoPacketProfiler.h"
#include "ContextEnumerator.h"
#include "SatCounter.h"
#include <list>

AutoPacket::AutoPacket(AutoPacketFactory& factory)
{
  // Traverse all contexts, adding their packet subscriber vectors one at a time:
  for(const auto& curContext : ContextEnumerator(factory.GetContext())) {
    AutowiredFast<AutoPacketFactory> curFactory(curContext);
    if(curFactory)
      // Only insert if this context actually has a packet factory
      curFactory->AppendAutoFiltersTo(m_satCounters);
  }

  // Sort, eliminate duplicates
  std::sort(m_satCounters.begin(), m_satCounters.end());
  m_satCounters.erase(std::unique(m_satCounters.begin(), m_satCounters.end()), m_satCounters.end());

  // Prime the satisfaction graph for each element:
  for(auto& satCounter : m_satCounters) {
    for(
      auto pCur = satCounter.GetAutoFilterInput();
      *pCur;
      pCur++
    ) {
      DecorationDisposition& entry = m_decorations[*pCur->ti];

      // Decide what to do with this entry:
      switch(pCur->subscriberType) {
      case inTypeInvalid:
        // Should never happen--trivially ignore this entry
        break;
      case inTypeRequired:
        entry.m_subscribers.push_back(std::make_pair(&satCounter, true));
        break;
      case inTypeOptional:
        entry.m_subscribers.push_back(std::make_pair(&satCounter, false));
        break;
      case outTypeRef:
      case outTypeRefAutoReady:
        // We don't do anything with these types.
        // Optionally, we might want to register them as outputs, or do some kind
        // of runtime detection that a multi-satisfaction case exists--but for now,
        // we just trivially ignore them.
        break;
      }
    }
  }

  // Invoke any output-only AutoFilter routines
  Initialize();
}

AutoPacket::~AutoPacket() {
  // Last chance for AutoFilter call
  ResolveOptions();
}

ObjectPool<AutoPacket> AutoPacket::CreateObjectPool(AutoPacketFactory& factory) {
  return ObjectPool<AutoPacket>(
    ~0,
    ~0,
    [&factory] { return new AutoPacket(factory); },
    [] (AutoPacket& packet) {
      // Last chance for AutoFilter optional calls
      packet.ResolveOptions();

      // Reinitialize the whole packet:
      packet.Initialize();
    }
  );
}

void AutoPacket::ResolveOptions(void) {
  // Queue calls to ensure that calls to Decorate inside of AutoFilter methods
  // will NOT effect the resolution of optional arguments.
  std::list<SatCounter*> callQueue;
  {
    boost::lock_guard<boost::mutex> lk(m_lock);
    for(auto& decoration : m_decorations)
      for(auto& satCounter : decoration.second.m_subscribers)
        if(!satCounter.second)
          if(satCounter.first->Resolve())
            callQueue.push_back(satCounter.first);
  }
  for (SatCounter* call : callQueue)
    call->CallAutoFilter(*this);
}

void AutoPacket::MarkUnsatisfiable(const std::type_info& info) {
  DecorationDisposition* decoration;
  {
    boost::lock_guard<boost::mutex> lk(m_lock);
    auto dFind = m_decorations.find(info);
    if(dFind == m_decorations.end())
      // Trivial return, there's no subscriber to this decoration and so we have nothing to do
      return;
    decoration = &dFind->second;
  }

  // Update everything
  for(auto& satCounter : decoration->m_subscribers) {
    if(satCounter.second)
      // Entry is mandatory, leave it unsatisfaible
      continue;

    // Entry is optional, we will call if we're satisfied after decrementing this optional field
    if(satCounter.first->Decrement(false))
        satCounter.first->CallAutoFilter(*this);
  }
}

void AutoPacket::UpdateSatisfaction(const std::type_info& info) {
  DecorationDisposition* decoration;
  {
    boost::lock_guard<boost::mutex> lk(m_lock);
    auto dFind = m_decorations.find(info);
    if(dFind == m_decorations.end())
      // Trivial return, there's no subscriber to this decoration and so we have nothing to do
      return;
    decoration = &dFind->second;
  }

  // Update everything
  for(auto& satCounter : decoration->m_subscribers)
    if(satCounter.first->Decrement(satCounter.second))
        satCounter.first->CallAutoFilter(*this);
}

void AutoPacket::PulseSatisfaction(DecorationDisposition* pTypeSubs[], size_t nInfos) {
  // First pass, decrement what we can:
  for(size_t i = nInfos; i--;) {
    for(std::pair<SatCounter*, bool>& subscriber : pTypeSubs[i]->m_subscribers) {
      SatCounter* cur = subscriber.first;
      if(
        // We only care about mandatory inputs
        subscriber.second &&

        // We only care about sat counters that aren't deferred--skip everyone else
        // Deferred calls will be too late.
        !cur->IsDeferred() &&

        // Now do the decrementation, and only proceed if the decremented value is zero
        !--cur->remaining
      )
        // Finally, a call is safe to make on this type
        cur->CallAutoFilter(*this);
    }
  }

  // Reset all counters
  // since data in this call will not be available subsequently
  for(size_t i = nInfos; i--;) {
    for(auto& satCounter : pTypeSubs[i]->m_subscribers) {
      auto& cur = satCounter.first;
      if (satCounter.second) {
        ++cur->remaining;
      }
    }
  }
}

void AutoPacket::Initialize(void) {
  // Initialize all counters:
  {
    boost::lock_guard<boost::mutex> lk(m_lock);
    for(auto& satCounter : m_satCounters)
      satCounter.Reset();
    for(auto& decoration : m_decorations)
      decoration.second.Reset();
  }

  // Call all subscribers with no required or optional arguments:
  for (auto& satCounter : m_satCounters)
    if (satCounter)
      satCounter.CallAutoFilter(*this);

  // Initial satisfaction of the AutoPacket:
  UpdateSatisfaction(typeid(AutoPacket));
}

bool AutoPacket::HasSubscribers(const std::type_info& ti) const {
  return m_decorations.count(ti) != 0;
}
<|endoftext|>


<commit_before>#include "render_test.h"
#include <QApplication>
#include <qdir.h>
#include "core/FS/file_system.h"
#include "core/FS/ifile.h"
#include "core/log.h"
#include "core/profiler.h"
#include "core/resource_manager.h"
#include "core/resource_manager_base.h"
#include "editor/world_editor.h"
#include "editor/gizmo.h"
#include "engine/engine.h"
#include "engine/plugin_manager.h"
#include "graphics/gl_ext.h"
#include "graphics/irender_device.h"
#include "graphics/pipeline.h"
#include "graphics/renderer.h"
#include "graphics/texture.h"
#include "physics/physics_scene.h"
#include "physics/physics_system.h"

class WGLRenderDevice : public Lumix::IRenderDevice
{
public:
	WGLRenderDevice(Lumix::Engine& engine, const char* pipeline_path)
	{
		Lumix::Pipeline* pipeline_object = static_cast<Lumix::Pipeline*>(engine.getResourceManager().get(Lumix::ResourceManager::PIPELINE)->load(Lumix::Path(pipeline_path)));
		ASSERT(pipeline_object);
		if (pipeline_object)
		{
			m_pipeline = Lumix::PipelineInstance::create(*pipeline_object, engine.getAllocator());
			m_pipeline->setRenderer(engine.getRenderer());
		}

	}

	~WGLRenderDevice()
	{
		if (m_pipeline)
		{
			Lumix::PipelineInstance::destroy(m_pipeline);
		}
	}

	virtual void beginFrame() override
	{
		PROFILE_FUNCTION();
		wglMakeCurrent(m_hdc, m_opengl_context);
	}

	virtual void endFrame() override
	{
		PROFILE_FUNCTION();
		wglSwapLayerBuffers(m_hdc, WGL_SWAP_MAIN_PLANE);
	}

	virtual Lumix::PipelineInstance& getPipeline()
	{
		return *m_pipeline;
	}

	virtual int getWidth() const override
	{
		return m_pipeline->getWidth();
	}

	virtual int getHeight() const override
	{
		return m_pipeline->getHeight();
	}

	Lumix::PipelineInstance* m_pipeline;
	HDC m_hdc;
	HGLRC m_opengl_context;
};

class App
{
public:
	App()
	{
		m_qt_app = NULL;
		m_main_window = NULL;
		m_current_test = -1;
		m_is_test_universe_loaded = false;
	}

	~App()
	{
		delete m_main_window;
		delete m_qt_app;
	}

	HGLRC createGLContext(HWND hwnd[], int count)
	{
		ASSERT(count > 0);
		QWidget* widget = new QWidget();
		HWND gl_hwnd = (HWND)widget->winId();
		HDC hdc;
		hdc = GetDC(gl_hwnd);
		ASSERT(hdc != NULL);
		if (hdc == NULL)
		{
			Lumix::g_log_error.log("renderer") << "Could not get the device context";
			return NULL;
		}
		BOOL success;
		PIXELFORMATDESCRIPTOR pfd =
		{
			sizeof(PIXELFORMATDESCRIPTOR),  //  size of this pfd
			1,                     // version number
			PFD_DRAW_TO_WINDOW |   // support window
			PFD_SUPPORT_OPENGL |   // support OpenGL
			PFD_DOUBLEBUFFER,      // double buffered
			PFD_TYPE_RGBA,         // RGBA type
			24,                    // 24-bit color depth
			0, 0, 0, 0, 0, 0,      // color bits ignored
			0,                     // no alpha buffer
			0,                     // shift bit ignored
			0,                     // no accumulation buffer
			0, 0, 0, 0,            // accum bits ignored
			32,                    // 32-bit z-buffer
			0,                     // no stencil buffer
			0,                     // no auxiliary buffer
			PFD_MAIN_PLANE,        // main layer
			0,                     // reserved
			0, 0, 0                // layer masks ignored
		};
		int pixelformat = ChoosePixelFormat(hdc, &pfd);
		if (pixelformat == 0)
		{
			delete widget;
			ASSERT(false);
			Lumix::g_log_error.log("renderer") << "Could not choose a pixel format";
			return NULL;
		}
		success = SetPixelFormat(hdc, pixelformat, &pfd);
		if (success == FALSE)
		{
			delete widget;
			ASSERT(false);
			Lumix::g_log_error.log("renderer") << "Could not set a pixel format";
			return NULL;
		}
		HGLRC hglrc = wglCreateContext(hdc);
		if (hglrc == NULL)
		{
			delete widget;
			ASSERT(false);
			Lumix::g_log_error.log("renderer") << "Could not create an opengl context";
			return NULL;
		}
		success = wglMakeCurrent(hdc, hglrc);
		if (success == FALSE)
		{
			delete widget;
			ASSERT(false);
			Lumix::g_log_error.log("renderer") << "Could not make the opengl context current rendering context";
			return NULL;
		}

			{
				UINT numFormats;
				int atrribs[] =
				{
					WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
					WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
					WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
					WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
					WGL_COLOR_BITS_ARB, 32,
					WGL_DEPTH_BITS_ARB, 24,
					WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
					WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
					WGL_SAMPLES_ARB, 4,
					0
				};
				PFNWGLCHOOSEPIXELFORMATARBPROC foo;
				foo = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
				if (!foo)
				{
					delete widget;
					ASSERT(false);
					Lumix::g_log_error.log("renderer") << "Could not get function wglChoosePixelFormatARB";
					return NULL;
				}
				success = foo(hdc, atrribs, NULL, 1, &pixelformat, &numFormats);
			}
			wglDeleteContext(hglrc);
			hglrc = NULL;
			delete widget;

			for (int i = 0; i < count; ++i)
			{
				if (hwnd[i])
				{
					hdc = GetDC(hwnd[i]);
					ChoosePixelFormat(hdc, &pfd);
					if (hdc == NULL)
					{
						ASSERT(false);
						Lumix::g_log_error.log("renderer") << "Could not get the device context";
						return NULL;
					}
					SetPixelFormat(hdc, pixelformat, &pfd);

					if (!hglrc)
					{
						hglrc = wglCreateContext(hdc);
						if (hglrc == NULL)
						{
							ASSERT(false);
							Lumix::g_log_error.log("renderer") << "Could not create an opengl context";
							return NULL;
						}
						success = wglMakeCurrent(hdc, hglrc);
						if (success == FALSE)
						{
							ASSERT(false);
							Lumix::g_log_error.log("renderer") << "Could not make the opengl context current rendering context";
							return NULL;
						}
					}
				}
			}

			return hglrc;
	}

	void universeFileLoaded(Lumix::FS::IFile* file, bool success, Lumix::FS::FileSystem& fs)
	{
		ASSERT(success);
		if (success)
		{
			ASSERT(file->getBuffer());
			Lumix::InputBlob blob(file->getBuffer(), file->size());
			uint32_t hash = 0;
			blob.read(hash);
			uint32_t engine_hash = 0;
			blob.read(engine_hash);
			if (crc32((const uint8_t*)blob.getData() + sizeof(hash), blob.getSize() - sizeof(hash)) != hash)
			{
				ASSERT(false);
				return;
			}
			bool deserialize_succeeded = m_engine->deserialize(blob);
			m_is_test_universe_loaded = true;
			ASSERT(deserialize_succeeded);
		}

		fs.close(file);
	}

	void init(int argc, char* argv[])
	{
		m_qt_app = new QApplication(argc, argv);
		QFile file("editor/stylesheet.qss");
		file.open(QFile::ReadOnly);
		m_qt_app->setStyleSheet(QLatin1String(file.readAll()));

		m_main_window = new RenderTest();
		m_main_window->show();

		HWND hwnd = (HWND)m_main_window->centralWidget()->winId();
		HWND hwnds[] = { hwnd };
		HGLRC hglrc = createGLContext(hwnds, sizeof(hwnds) / sizeof(hwnds[0]));

		m_engine = Lumix::Engine::create("", NULL, NULL, m_allocator);
		m_render_device = new WGLRenderDevice(*m_engine, "pipelines/main.json");
		m_render_device->m_hdc = GetDC(hwnd);
		m_render_device->m_opengl_context = hglrc;
		m_engine->createUniverse();
		m_render_device->getPipeline().setScene((Lumix::RenderScene*)m_engine->getScene(crc32("renderer")));
		m_engine->getRenderer().setRenderDevice(*m_render_device);
		m_render_device->getPipeline().resize(600, 400);
	}

	void shutdown()
	{
	}

	void handleEvents()
	{
		PROFILE_FUNCTION();
		{
			PROFILE_BLOCK("qt::processEvents");
			m_qt_app->processEvents();
		}
	}

	bool nextTest()
	{
		static const char* tests[] = {
			"render_tests/1"
		};

		Lumix::FS::FileSystem& fs = m_engine->getFileSystem();

		bool can_do_next_test = m_current_test == -1 || (!m_engine->getResourceManager().isLoading() && m_is_test_universe_loaded);
		if (can_do_next_test)
		{
			char path[LUMIX_MAX_PATH];
			if (m_current_test >= 0)
			{
				Lumix::copyString(path, sizeof(path), tests[m_current_test]);
				Lumix::catCString(path, sizeof(path), "_res.tga");
				m_engine->getRenderer().makeScreenshot(Lumix::Path(path), 500, 500);

				char path_preimage[LUMIX_MAX_PATH];
				Lumix::copyString(path_preimage, sizeof(path), tests[m_current_test]);
				Lumix::catCString(path_preimage, sizeof(path), ".tga");

				auto file1 = fs.open(fs.getDefaultDevice(), path, Lumix::FS::Mode::OPEN | Lumix::FS::Mode::READ);
				auto file2 = fs.open(fs.getDefaultDevice(), path_preimage, Lumix::FS::Mode::OPEN | Lumix::FS::Mode::READ);
				unsigned int diference = Lumix::Texture::compareTGA(m_allocator, file1, file2, 10);
				fs.close(file1);
				fs.close(file2);
				ASSERT(diference < 100);
			}

			++m_current_test;
			if (m_current_test < sizeof(tests) / sizeof(tests[0]))
			{
				Lumix::copyString(path, sizeof(path), tests[m_current_test]);
				Lumix::catCString(path, sizeof(path), ".unv");
				Lumix::FS::ReadCallback file_read_cb;
				file_read_cb.bind<App, &App::universeFileLoaded>(this);
				fs.openAsync(fs.getDefaultDevice(), path, Lumix::FS::Mode::OPEN | Lumix::FS::Mode::READ, file_read_cb);
				m_is_test_universe_loaded = false;
				return true;
			}
			return false;
		}
		return true;
	}

	void run()
	{
		while (m_main_window->isVisible())
		{
			{
				PROFILE_BLOCK("tick");
				m_engine->getRenderer().renderGame();
				m_engine->update(false, 0);
				if (!m_engine->getResourceManager().isLoading())
				{
					if (!nextTest())
						return;
				}
				m_engine->getFileSystem().updateAsyncTransactions();
				handleEvents();
			}

			Lumix::g_profiler.frame();
		}
	}

private:
	Lumix::DefaultAllocator m_allocator;
	Lumix::Engine* m_engine;
	RenderTest* m_main_window;
	QApplication* m_qt_app;
	WGLRenderDevice* m_render_device;
	QWidget* m_view;
	int m_current_test;
	bool m_is_test_universe_loaded;
};

int main(int argc, char* argv[])
{
	App app;
	app.init(argc, argv);
	app.run();
	app.shutdown();
	return 0;
}
<commit_msg>enumerate all tests in render_test directory<commit_after>#include "render_test.h"
#include <QApplication>
#include <qdir.h>
#include "core/FS/file_system.h"
#include "core/FS/ifile.h"
#include "core/log.h"
#include "core/profiler.h"
#include "core/resource_manager.h"
#include "core/resource_manager_base.h"
#include "editor/world_editor.h"
#include "editor/gizmo.h"
#include "engine/engine.h"
#include "engine/plugin_manager.h"
#include "graphics/gl_ext.h"
#include "graphics/irender_device.h"
#include "graphics/pipeline.h"
#include "graphics/renderer.h"
#include "graphics/texture.h"
#include "physics/physics_scene.h"
#include "physics/physics_system.h"

class WGLRenderDevice : public Lumix::IRenderDevice
{
public:
	WGLRenderDevice(Lumix::Engine& engine, const char* pipeline_path)
	{
		Lumix::Pipeline* pipeline_object = static_cast<Lumix::Pipeline*>(engine.getResourceManager().get(Lumix::ResourceManager::PIPELINE)->load(Lumix::Path(pipeline_path)));
		ASSERT(pipeline_object);
		if (pipeline_object)
		{
			m_pipeline = Lumix::PipelineInstance::create(*pipeline_object, engine.getAllocator());
			m_pipeline->setRenderer(engine.getRenderer());
		}

	}

	~WGLRenderDevice()
	{
		if (m_pipeline)
		{
			Lumix::PipelineInstance::destroy(m_pipeline);
		}
	}

	virtual void beginFrame() override
	{
		PROFILE_FUNCTION();
		wglMakeCurrent(m_hdc, m_opengl_context);
	}

	virtual void endFrame() override
	{
		PROFILE_FUNCTION();
		wglSwapLayerBuffers(m_hdc, WGL_SWAP_MAIN_PLANE);
	}

	virtual Lumix::PipelineInstance& getPipeline()
	{
		return *m_pipeline;
	}

	virtual int getWidth() const override
	{
		return m_pipeline->getWidth();
	}

	virtual int getHeight() const override
	{
		return m_pipeline->getHeight();
	}

	Lumix::PipelineInstance* m_pipeline;
	HDC m_hdc;
	HGLRC m_opengl_context;
};

class App
{
public:
	App()
	{
		m_qt_app = NULL;
		m_main_window = NULL;
		m_current_test = -1;
		m_is_test_universe_loaded = false;
	}

	~App()
	{
		delete m_main_window;
		delete m_qt_app;
	}

	HGLRC createGLContext(HWND hwnd[], int count)
	{
		ASSERT(count > 0);
		QWidget* widget = new QWidget();
		HWND gl_hwnd = (HWND)widget->winId();
		HDC hdc;
		hdc = GetDC(gl_hwnd);
		ASSERT(hdc != NULL);
		if (hdc == NULL)
		{
			Lumix::g_log_error.log("renderer") << "Could not get the device context";
			return NULL;
		}
		BOOL success;
		PIXELFORMATDESCRIPTOR pfd =
		{
			sizeof(PIXELFORMATDESCRIPTOR),  //  size of this pfd
			1,                     // version number
			PFD_DRAW_TO_WINDOW |   // support window
			PFD_SUPPORT_OPENGL |   // support OpenGL
			PFD_DOUBLEBUFFER,      // double buffered
			PFD_TYPE_RGBA,         // RGBA type
			24,                    // 24-bit color depth
			0, 0, 0, 0, 0, 0,      // color bits ignored
			0,                     // no alpha buffer
			0,                     // shift bit ignored
			0,                     // no accumulation buffer
			0, 0, 0, 0,            // accum bits ignored
			32,                    // 32-bit z-buffer
			0,                     // no stencil buffer
			0,                     // no auxiliary buffer
			PFD_MAIN_PLANE,        // main layer
			0,                     // reserved
			0, 0, 0                // layer masks ignored
		};
		int pixelformat = ChoosePixelFormat(hdc, &pfd);
		if (pixelformat == 0)
		{
			delete widget;
			ASSERT(false);
			Lumix::g_log_error.log("renderer") << "Could not choose a pixel format";
			return NULL;
		}
		success = SetPixelFormat(hdc, pixelformat, &pfd);
		if (success == FALSE)
		{
			delete widget;
			ASSERT(false);
			Lumix::g_log_error.log("renderer") << "Could not set a pixel format";
			return NULL;
		}
		HGLRC hglrc = wglCreateContext(hdc);
		if (hglrc == NULL)
		{
			delete widget;
			ASSERT(false);
			Lumix::g_log_error.log("renderer") << "Could not create an opengl context";
			return NULL;
		}
		success = wglMakeCurrent(hdc, hglrc);
		if (success == FALSE)
		{
			delete widget;
			ASSERT(false);
			Lumix::g_log_error.log("renderer") << "Could not make the opengl context current rendering context";
			return NULL;
		}

			{
				UINT numFormats;
				int atrribs[] =
				{
					WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
					WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
					WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
					WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
					WGL_COLOR_BITS_ARB, 32,
					WGL_DEPTH_BITS_ARB, 24,
					WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
					WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
					WGL_SAMPLES_ARB, 4,
					0
				};
				PFNWGLCHOOSEPIXELFORMATARBPROC foo;
				foo = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
				if (!foo)
				{
					delete widget;
					ASSERT(false);
					Lumix::g_log_error.log("renderer") << "Could not get function wglChoosePixelFormatARB";
					return NULL;
				}
				success = foo(hdc, atrribs, NULL, 1, &pixelformat, &numFormats);
			}
			wglDeleteContext(hglrc);
			hglrc = NULL;
			delete widget;

			for (int i = 0; i < count; ++i)
			{
				if (hwnd[i])
				{
					hdc = GetDC(hwnd[i]);
					ChoosePixelFormat(hdc, &pfd);
					if (hdc == NULL)
					{
						ASSERT(false);
						Lumix::g_log_error.log("renderer") << "Could not get the device context";
						return NULL;
					}
					SetPixelFormat(hdc, pixelformat, &pfd);

					if (!hglrc)
					{
						hglrc = wglCreateContext(hdc);
						if (hglrc == NULL)
						{
							ASSERT(false);
							Lumix::g_log_error.log("renderer") << "Could not create an opengl context";
							return NULL;
						}
						success = wglMakeCurrent(hdc, hglrc);
						if (success == FALSE)
						{
							ASSERT(false);
							Lumix::g_log_error.log("renderer") << "Could not make the opengl context current rendering context";
							return NULL;
						}
					}
				}
			}

			return hglrc;
	}

	void universeFileLoaded(Lumix::FS::IFile* file, bool success, Lumix::FS::FileSystem& fs)
	{
		ASSERT(success);
		if (success)
		{
			ASSERT(file->getBuffer());
			Lumix::InputBlob blob(file->getBuffer(), file->size());
			uint32_t hash = 0;
			blob.read(hash);
			uint32_t engine_hash = 0;
			blob.read(engine_hash);
			if (crc32((const uint8_t*)blob.getData() + sizeof(hash), blob.getSize() - sizeof(hash)) != hash)
			{
				ASSERT(false);
				return;
			}
			bool deserialize_succeeded = m_engine->deserialize(blob);
			m_is_test_universe_loaded = true;
			ASSERT(deserialize_succeeded);
		}

		fs.close(file);
	}

	void init(int argc, char* argv[])
	{
		m_qt_app = new QApplication(argc, argv);
		QFile file("editor/stylesheet.qss");
		file.open(QFile::ReadOnly);
		m_qt_app->setStyleSheet(QLatin1String(file.readAll()));

		m_main_window = new RenderTest();
		m_main_window->show();

		HWND hwnd = (HWND)m_main_window->centralWidget()->winId();
		HWND hwnds[] = { hwnd };
		HGLRC hglrc = createGLContext(hwnds, sizeof(hwnds) / sizeof(hwnds[0]));

		m_engine = Lumix::Engine::create("", NULL, NULL, m_allocator);
		m_render_device = new WGLRenderDevice(*m_engine, "pipelines/main.json");
		m_render_device->m_hdc = GetDC(hwnd);
		m_render_device->m_opengl_context = hglrc;
		m_engine->createUniverse();
		m_render_device->getPipeline().setScene((Lumix::RenderScene*)m_engine->getScene(crc32("renderer")));
		m_engine->getRenderer().setRenderDevice(*m_render_device);
		m_render_device->getPipeline().resize(600, 400);

		enumerateTests();
	}

	void shutdown()
	{
	}

	void handleEvents()
	{
		PROFILE_FUNCTION();
		{
			PROFILE_BLOCK("qt::processEvents");
			m_qt_app->processEvents();
		}
	}

	void enumerateTests()
	{
		QDir dir("render_tests");
		QStringList files = dir.entryList(QStringList() << "*.unv");
		for (int i = 0; i < files.size(); ++i)
		{
			m_tests.push_back(QString("render_tests/") + files[i].left(files[i].size() - 4));
		}
	}

	bool nextTest()
	{
		Lumix::FS::FileSystem& fs = m_engine->getFileSystem();

		bool can_do_next_test = m_current_test == -1 || (!m_engine->getResourceManager().isLoading() && m_is_test_universe_loaded);
		if (can_do_next_test)
		{
			char path[LUMIX_MAX_PATH];
			if (m_current_test >= 0)
			{
				Lumix::copyString(path, sizeof(path), m_tests[m_current_test].toLatin1().data());
				Lumix::catCString(path, sizeof(path), "_res.tga");
				m_engine->getRenderer().makeScreenshot(Lumix::Path(path), 500, 500);

				char path_preimage[LUMIX_MAX_PATH];
				Lumix::copyString(path_preimage, sizeof(path), m_tests[m_current_test].toLatin1().data());
				Lumix::catCString(path_preimage, sizeof(path), ".tga");

				auto file1 = fs.open(fs.getDefaultDevice(), path, Lumix::FS::Mode::OPEN | Lumix::FS::Mode::READ);
				auto file2 = fs.open(fs.getDefaultDevice(), path_preimage, Lumix::FS::Mode::OPEN | Lumix::FS::Mode::READ);
				unsigned int diference = Lumix::Texture::compareTGA(m_allocator, file1, file2, 10);
				fs.close(file1);
				fs.close(file2);
				ASSERT(diference < 100);
			}

			++m_current_test;
			if (m_current_test < m_tests.size())
			{
				Lumix::copyString(path, sizeof(path), m_tests[m_current_test].toLatin1().data());
				Lumix::catCString(path, sizeof(path), ".unv");
				Lumix::FS::ReadCallback file_read_cb;
				file_read_cb.bind<App, &App::universeFileLoaded>(this);
				fs.openAsync(fs.getDefaultDevice(), path, Lumix::FS::Mode::OPEN | Lumix::FS::Mode::READ, file_read_cb);
				m_is_test_universe_loaded = false;
				return true;
			}
			return false;
		}
		return true;
	}

	void run()
	{
		while (m_main_window->isVisible())
		{
			{
				PROFILE_BLOCK("tick");
				m_engine->getRenderer().renderGame();
				m_engine->update(false, 0);
				if (!m_engine->getResourceManager().isLoading())
				{
					if (!nextTest())
						return;
				}
				m_engine->getFileSystem().updateAsyncTransactions();
				handleEvents();
			}

			Lumix::g_profiler.frame();
		}
	}

private:
	Lumix::DefaultAllocator m_allocator;
	Lumix::Engine* m_engine;
	RenderTest* m_main_window;
	QApplication* m_qt_app;
	WGLRenderDevice* m_render_device;
	QWidget* m_view;
	QStringList m_tests;
	int m_current_test;
	bool m_is_test_universe_loaded;
};

int main(int argc, char* argv[])
{
	App app;
	app.init(argc, argv);
	app.run();
	app.shutdown();
	return 0;
}
<|endoftext|>


<commit_before>/**********************************************************************/
/* Copyright 2014 RCF                                                 */
/*                                                                    */
/* 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.                                 */
/**********************************************************************/

/**
 * @file  Simplex.cpp
 * @brief Main interface for use of the Network Simplex Algorithm
 */

// Default libraries
#include <cstdio>
#include <iostream>
using namespace std;

// Libraries
#include "Options.hpp"
#include "graph/graph.tcc"
#include "graph/flow/flow.tcc"

/**
 * @fn Main
 * @param  argc Number of arguments in the command line
 * @param  argv Array of string with the arguments
 * @return 0 if success; non-zero otherwise
 */
int main(int argc, char **argv)
{
    // Process options
    Options::parse_args(argc, argv);

    if(argc-optind != 1)
    {
        cerr << "Usage: Simplex [-h] [-d] input.dat ..." << endl;
        cerr << "Type --help for more information"       << endl;

        return EXIT_FAILURE;
    }

    typedef graph::flow::Vertex<>::type vertex;
    typedef graph::flow::Arc<>::type    arc;

    vertex v1 { 0 }, v2 { 1 };
    arc a1 { v1, v2 }, a2 { v2, v1 };

    cout << a1.beg << endl;
    cout << a1.end << endl;
    cout << a1 << endl;

    cout << a2.beg << endl;
    cout << a2.end << endl;
    cout << a2 << endl;

    cout << "Vertex list" << endl;
    cout << "=======================" << endl;
    typedef std::vector<vertex> vertex_list;
    vertex_list vl { v1, v2 };
    for(const vertex& v : vl)
        cout << v << endl;

    cout << "Arc list" << endl;
    cout << "=======================" << endl;
    typedef std::vector<arc> arc_list;
    arc_list al { a1, a2 };
    for(const arc& a : al)
        cout << a << endl;

    cout << "Adjacency list" << endl;
    cout << "=======================" << endl;
    typedef graph::Adjacency_list<graph::directed,vertex,arc> digraph;
    digraph adj ( vl, al );

    cout << "Digraph" << endl;
    cout << "=======================" << endl;

    vertex_list tr1_v;

    vertex::id_type id {};
    for(size_t i = 0; i < 5; i++)
        tr1_v.emplace_back(id++);

    arc_list tr1_a {
        arc{ tr1_v[0], tr1_v[1], {9 } },
        arc{ tr1_v[0], tr1_v[3], {10} },
        arc{ tr1_v[1], tr1_v[2], {7 } },
        arc{ tr1_v[1], tr1_v[3], {4 } },
        arc{ tr1_v[1], tr1_v[4], {5 } },
        arc{ tr1_v[2], tr1_v[4], {9 } },
        arc{ tr1_v[3], tr1_v[1], {4 } },
        arc{ tr1_v[3], tr1_v[4], {9 } }
    };

    digraph T { tr1_v, tr1_a };

    auto it  = T.out_arcs(tr1_v[0]).first;
    auto end = T.out_arcs(tr1_v[0]).second;
    for(; it != end; it++)
        cout << **it << endl;

    return EXIT_SUCCESS;
}
<commit_msg>Cleaning example and updating<commit_after>/**********************************************************************/
/* Copyright 2014 RCF                                                 */
/*                                                                    */
/* 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.                                 */
/**********************************************************************/

/**
 * @file  Simplex.cpp
 * @brief Main interface for use of the Network Simplex Algorithm
 */

// Default libraries
#include <cstdio>
#include <iostream>
using namespace std;

// Libraries
#include "Options.hpp"
#include "graph/graph.tcc"
#include "graph/flow/flow.tcc"

/**
 * @fn Main
 * @param  argc Number of arguments in the command line
 * @param  argv Array of string with the arguments
 * @return 0 if success; non-zero otherwise
 */
int main(int argc, char **argv)
{
    // Process options
    Options::parse_args(argc, argv);

    if(argc-optind != 1)
    {
        cerr << "Usage: Simplex [-h] [-d] input.dat ..." << endl;
        cerr << "Type --help for more information"       << endl;

        return EXIT_FAILURE;
    }

    typedef graph::flow::Vertex<>::type vertex;
    typedef graph::flow::Arc<>::type    arc;

    vertex v1 { 0 }, v2 { 1 };
    arc a1 { v1, v2 }, a2 { v2, v1 };

    cout << endl << "Vertex list" << endl;
    cout << "=======================" << endl;
    typedef std::vector<vertex> vertex_list;
    vertex_list vl { v1, v2 };
    for(const vertex& v : vl)
        cout << v << endl;

    cout << endl << "Arc list" << endl;
    cout << "=======================" << endl;
    typedef std::vector<arc> arc_list;
    arc_list al { a1, a2 };
    for(const arc& a : al)
        cout << a << endl;

    cout << endl << "Digraph" << endl;
    cout << "=======================" << endl;
    typedef graph::Adjacency_list<graph::directed,vertex,arc> digraph;

    vertex_list tr1_v;

    vertex::id_type id {};
    for(size_t i = 0; i < 5; i++)
        tr1_v.emplace_back(id++);

    arc_list tr1_a {
        arc{ tr1_v[0], tr1_v[1], {9 } },
        arc{ tr1_v[0], tr1_v[3], {10} },
        arc{ tr1_v[1], tr1_v[2], {7 } },
        arc{ tr1_v[1], tr1_v[3], {4 } },
        arc{ tr1_v[1], tr1_v[4], {5 } },
        arc{ tr1_v[2], tr1_v[4], {9 } },
        arc{ tr1_v[3], tr1_v[1], {4 } },
        arc{ tr1_v[3], tr1_v[4], {9 } }
    };

    digraph T { tr1_v, tr1_a };

    auto it  = T.out_arcs(tr1_v[0]).first;
    auto end = T.out_arcs(tr1_v[0]).second;
    for(; it != end; it++)
        cout << **it << endl;

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 "Semaphore.h"

using namespace decaf;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
using namespace decaf::util;
using namespace decaf::util::concurrent;

////////////////////////////////////////////////////////////////////////////////
namespace decaf {
namespace util {
namespace concurrent {

    class SemaphoreHandle {
    public:

        int permits;
        bool fair;

    public:

        SemaphoreHandle( int permits ) : permits( permits ), fair( false ) {
        }

        SemaphoreHandle( int permits, bool fair ) : permits( permits ), fair( fair ) {
        }

        ~SemaphoreHandle() {
        }

    };

}}}

////////////////////////////////////////////////////////////////////////////////
Semaphore::Semaphore( int permits ) {

    this->handle.reset( new SemaphoreHandle( permits ) );
}

////////////////////////////////////////////////////////////////////////////////
Semaphore::Semaphore( int permits, bool fair ) {

    this->handle.reset( new SemaphoreHandle( permits, fair ) );
}

////////////////////////////////////////////////////////////////////////////////
Semaphore::~Semaphore() {
}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::acquire() throw( decaf::lang::exceptions::InterruptedException,
                                 decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::acquireUninterruptibly() throw ( decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
bool Semaphore::tryAcquire() throw ( decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
bool Semaphore::tryAcquire( long long timeout, const TimeUnit& unit )
    throw( decaf::lang::exceptions::InterruptedException,
           decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::release() throw ( decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::acquire( int permits ) throw( decaf::lang::exceptions::InterruptedException,
                                              decaf::lang::exceptions::IllegalArgumentException,
                                              decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::acquireUninterruptibly( int permits )
    throw( decaf::lang::exceptions::IllegalArgumentException,
           decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
bool Semaphore::tryAcquire( int permits )
    throw( decaf::lang::exceptions::IllegalArgumentException,
           decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
bool Semaphore::tryAcquire( int permits, long long timeout, const TimeUnit& unit )
    throw( decaf::lang::exceptions::IllegalArgumentException,
           decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::release( int permits )
    throw( decaf::lang::exceptions::IllegalArgumentException,
           decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
int Semaphore::availablePermits() const {

}

////////////////////////////////////////////////////////////////////////////////
int Semaphore::drainPermits() throw( decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
bool Semaphore::isFair() const {

}

////////////////////////////////////////////////////////////////////////////////
std::string Semaphore::toString() const {

}
<commit_msg>Commit some fixes found while building on Solaris.<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 "Semaphore.h"

using namespace decaf;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
using namespace decaf::util;
using namespace decaf::util::concurrent;

////////////////////////////////////////////////////////////////////////////////
namespace decaf {
namespace util {
namespace concurrent {

    class SemaphoreHandle {
    public:

        int permits;
        bool fair;

    public:

        SemaphoreHandle( int permits ) : permits( permits ), fair( false ) {
        }

        SemaphoreHandle( int permits, bool fair ) : permits( permits ), fair( fair ) {
        }

        ~SemaphoreHandle() {
        }

    };

}}}

////////////////////////////////////////////////////////////////////////////////
Semaphore::Semaphore( int permits ) {

    this->handle.reset( new SemaphoreHandle( permits ) );
}

////////////////////////////////////////////////////////////////////////////////
Semaphore::Semaphore( int permits, bool fair ) {

    this->handle.reset( new SemaphoreHandle( permits, fair ) );
}

////////////////////////////////////////////////////////////////////////////////
Semaphore::~Semaphore() {
}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::acquire() throw( decaf::lang::exceptions::InterruptedException,
                                 decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::acquireUninterruptibly() throw ( decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
bool Semaphore::tryAcquire() throw ( decaf::lang::exceptions::RuntimeException ) {
    return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Semaphore::tryAcquire( long long timeout, const TimeUnit& unit )
    throw( decaf::lang::exceptions::InterruptedException,
           decaf::lang::exceptions::RuntimeException ) {

    return false;
}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::release() throw ( decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::acquire( int permits ) throw( decaf::lang::exceptions::InterruptedException,
                                              decaf::lang::exceptions::IllegalArgumentException,
                                              decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::acquireUninterruptibly( int permits )
    throw( decaf::lang::exceptions::IllegalArgumentException,
           decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
bool Semaphore::tryAcquire( int permits )
    throw( decaf::lang::exceptions::IllegalArgumentException,
           decaf::lang::exceptions::RuntimeException ) {

    return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Semaphore::tryAcquire( int permits, long long timeout, const TimeUnit& unit )
    throw( decaf::lang::exceptions::IllegalArgumentException,
           decaf::lang::exceptions::RuntimeException ) {

    return false;
}

////////////////////////////////////////////////////////////////////////////////
void Semaphore::release( int permits )
    throw( decaf::lang::exceptions::IllegalArgumentException,
           decaf::lang::exceptions::RuntimeException ) {

}

////////////////////////////////////////////////////////////////////////////////
int Semaphore::availablePermits() const {
    return 0;
}

////////////////////////////////////////////////////////////////////////////////
int Semaphore::drainPermits() throw( decaf::lang::exceptions::RuntimeException ) {
    return 0;
}

////////////////////////////////////////////////////////////////////////////////
bool Semaphore::isFair() const {
    return false;
}

////////////////////////////////////////////////////////////////////////////////
std::string Semaphore::toString() const {
    return "";
}
<|endoftext|>


<commit_before><commit_msg>Fix error of not calculating dose second time<commit_after><|endoftext|>


<commit_before>//
// Copyright (C) 2003	 Grzegorz Jaskiewicz <gj at pointblue.com.pl>
//
// gadupubdir.cpp
//  Gadu-Gadu Public directory contains people data, using it you can search friends
// different criteria
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301, USA.
//

#include "gadupubdir.h"
#include "gadueditcontact.h"
#include "gaducontactlist.h"
#include "gaduaccount.h"
#include "gaduprotocol.h"

#include <q3widgetstack.h>
#include <q3listview.h>
#include <q3ptrlist.h>
#include <qradiobutton.h>
#include <qspinbox.h>
#include <qcheckbox.h>
//Added by qt3to4:
#include <QPixmap>

#include <kcombobox.h>
#include <krestrictedline.h>
#include <klineedit.h>
#include <k3listview.h>
#include <klocale.h>

GaduPublicDir::GaduPublicDir( GaduAccount* account, QWidget* parent )
: KDialog( parent )
{
	setButtons( KDialog::User1 | KDialog::User2 | KDialog::User3 | KDialog::Cancel );
	setDefaultButton( KDialog::User2 );

	mAccount = account;
	createWidget();
	initConnections();

	show();
}

GaduPublicDir::GaduPublicDir( GaduAccount* account, int searchFor, QWidget* parent )
: KDialog( parent )
{
	setButtons( KDialog::User1 | KDialog::User2 | KDialog::User3 | KDialog::Cancel );
	setDefaultButton( KDialog::User2 );

	ResLine rs;

	mAccount = account;
	createWidget();
	initConnections();

	kDebug( 14100 ) << "search for Uin: " << searchFor << endl;

	mMainWidget->listFound->clear();
	show();

	if ( searchFor == 0 ) {
		return;
	}

	mMainWidget->pubsearch->raiseWidget( 1 );
	mMainWidget->radioByUin->setChecked( true );

	setButtonGuiItem( KDialog::User2, KGuiItem( i18n( "Search &More..." ) ) );
	showButton( KDialog::User3, true );
	showButton( KDialog::User1, true );
	enableButton( KDialog::User3, false );
	enableButton( KDialog::User2, false );

	// now it is time to switch to Right Page(tm)
	rs.uin = searchFor;

	fName	= fSurname = fNick = fCity = QString::null;
	fUin	= searchFor;
	fGender	= fAgeFrom = fAgeTo = 0;
	fOnlyOnline = false;

	mAccount->pubDirSearch( rs, fAgeFrom, fAgeTo, fOnlyOnline );

}

GaduPublicDir::~GaduPublicDir()
{
	delete mMainWidget;
}

void
GaduPublicDir::createWidget()
{
	setCaption( i18n( "Gadu-Gadu Public Directory" ) );

	QWidget* w = new QWidget( this );
	mMainWidget = new Ui::GaduPublicDirectory;
	mMainWidget->setupUi( this );
	setMainWidget( w );

	mMainWidget->UIN->setValidChars( "1234567890" );

	setButtonGuiItem( KDialog::User1, KGuiItem( i18n( "&New Search" ) ) );
	setButtonGuiItem( KDialog::User2, KGuiItem( i18n( "S&earch" ) ) );
	setButtonGuiItem( KDialog::User3, KGuiItem( i18n( "&Add User..." ) ) );
	setButtonGuiItem( KDialog::Cancel, KGuiItem( i18n( "&Close" ) ) );

	showButton( KDialog::User1, false );
	showButton( KDialog::User3, false );
	enableButton( KDialog::User2, false );

	mMainWidget->radioByData->setChecked( true );

	mAccount->pubDirSearchClose();

}

void
GaduPublicDir::slotAddContact()
{
	GaduContactsList::ContactLine* cl = new GaduContactsList::ContactLine;
	Q3ListViewItem* item = mMainWidget->listFound->currentItem();

	cl->ignored	= false;
	cl->firstname	= item->text( 1 );
	cl->uin		= item->text( 5 );
	cl->nickname 	= item->text( 2 );

	cl->surname	= fSurname;

//	GaduEditContact *ed =
	new GaduEditContact( mAccount, cl, this );
}

void
GaduPublicDir::slotListSelected(  )
{
	Q3ListViewItem* item = mMainWidget->listFound->currentItem();
	if ( item ) {
		enableButton( KDialog::User3, true );
	}
	else {
		enableButton( KDialog::User3, false );
	}
}

void
GaduPublicDir::initConnections()
{
	connect( this, SIGNAL( user2Clicked() ), SLOT( slotSearch() ) );
	connect( this, SIGNAL( user1Clicked() ), SLOT( slotNewSearch() ) );
	connect( this, SIGNAL( user3Clicked() ), SLOT( slotAddContact() ) );

	connect( mAccount, SIGNAL( pubDirSearchResult( const SearchResult&, unsigned int ) ),
				SLOT( slotSearchResult( const SearchResult&, unsigned int ) ) );

	connect( mMainWidget->nameS,		SIGNAL( textChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->surname,		SIGNAL( textChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->nick,		SIGNAL( textChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->UIN,		SIGNAL( textChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->cityS,		SIGNAL( textChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->gender,		SIGNAL( activated( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->ageFrom,		SIGNAL( valueChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->ageTo,		SIGNAL( valueChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->radioByData,	SIGNAL( toggled( bool ) ), SLOT( inputChanged( bool ) ) );

	connect( mMainWidget->listFound,	SIGNAL( selectionChanged () ), SLOT( slotListSelected() ) );

}

void
GaduPublicDir::inputChanged( bool )
{
	inputChanged( QString::null );
}

void
GaduPublicDir::inputChanged( const QString& )
{
	if ( validateData() == false ) {
		enableButton( User2, false );
	}
	else {
		enableButton( User2, true );
	}
}

void
GaduPublicDir::getData()
{
	fName		= mMainWidget->nameS->text();
	fSurname	= mMainWidget->surname->text();
	fNick		= mMainWidget->nick->text();
	fUin		= mMainWidget->UIN->text().toInt();
	fGender		= mMainWidget->gender->currentItem();
	fOnlyOnline	= mMainWidget->onlyOnline->isChecked();
	fAgeFrom	= mMainWidget->ageFrom->value();
	fAgeTo		= mMainWidget->ageTo->value();
	fCity		= mMainWidget->cityS->text();
}

// return true if not empty
#define CHECK_STRING(A) { if ( !A.isEmpty() ) { return true; } }
#define CHECK_INT(A) { if ( A ) { return true; } }

bool
GaduPublicDir::validateData()
{
	getData();

	if ( mMainWidget->radioByData->isChecked() ) {
		CHECK_STRING( fCity );
		CHECK_STRING( fName );
		CHECK_STRING( fSurname );
		CHECK_STRING( fNick );
		CHECK_INT( fGender );
		CHECK_INT( fAgeFrom );
		CHECK_INT( fAgeTo );
	}
	else {
		fSurname = QString::null;
		CHECK_INT( fUin );
	}
	return false;
}

// Move to GaduProtocol someday
QPixmap
GaduPublicDir::iconForStatus( uint status )
{
	QPixmap n;

	if ( GaduProtocol::protocol() ) {
		return GaduProtocol::protocol()->convertStatus( status ).protocolIcon();
	}
	return n;
}

void
GaduPublicDir::slotSearchResult( const SearchResult& result, unsigned int )
{
	Q3ListView* list = mMainWidget->listFound;

	kDebug(14100) << "searchResults(" << result.count() <<")" << endl;

	Q3ListViewItem* sl;

	SearchResult::const_iterator r;

	for ( r = result.begin(); r != result.end() ; ++r ){
		kDebug(14100) << "adding" << (*r).uin << endl;
		sl= new Q3ListViewItem(
					list, QString::fromAscii(""),
					(*r).firstname,
					(*r).nickname,
					(*r).age,
					(*r).city,
					QString::number( (*r).uin ).toAscii()
						);
		sl->setPixmap( 0, iconForStatus( (*r).status ) );
	}

	// if not found anything, obviously we don't want to search for more
	// if we are looking just for one UIN, don't allow search more - it is pointless

	if ( result.count() && fUin==0 ) {
		enableButton( KDialog:: User2, true );
	}

	enableButton( KDialog::User1, true );
	enableButton( KDialog::User3, false );
	mMainWidget->pubsearch->setDisabled( false );

}

void
GaduPublicDir::slotNewSearch()
{
	mMainWidget->pubsearch->raiseWidget( 0 );

	setButtonGuiItem( KDialog::User2, KGuiItem( i18n( "S&earch" ) ) );

	showButton( KDialog::User1, false );
	showButton( KDialog::User3, false );
	enableButton( KDialog::User2, false );
 	inputChanged( QString() );
 	mAccount->pubDirSearchClose();
}

void
GaduPublicDir::slotSearch()
{

	mMainWidget->listFound->clear();
	QString empty;

	// search more, or search ?
	if ( mMainWidget->pubsearch->id( mMainWidget->pubsearch->visibleWidget() ) == 0 ) {
		kDebug(14100) << "start search... " << endl;
		getData();

		// validate data
		if ( validateData() == false ) {
			return;
		}

		// go on
		mMainWidget->pubsearch->raiseWidget( 1 );

	}
	else{
		kDebug(14100) << "search more... " << endl;
		// Search for more
	}
	mMainWidget->pubsearch->setDisabled( true );
	setButtonGuiItem( KDialog::User2, KGuiItem( i18n( "Search &More..." ) ) );
	showButton( KDialog::User3, true );
	showButton( KDialog::User1, true );
	enableButton( KDialog::User3, false );
	enableButton( KDialog::User2, false );

	ResLine rs;
	rs.firstname	= fName;
	rs.surname	= fSurname;
	rs.nickname	= fNick;
	rs.uin		= fUin;
	rs.city		= fCity;

	if ( fGender == 1 ) {
		rs.gender =  GG_PUBDIR50_GENDER_MALE;
	}
	if ( fGender == 2 ) {
		rs.gender = GG_PUBDIR50_GENDER_FEMALE;
	}

	if ( mMainWidget->radioByData->isChecked() ) {
		mAccount->pubDirSearch( rs, fAgeFrom, fAgeTo, fOnlyOnline );
	}
	else {
		mAccount->pubDirSearch( rs, 0, 0, fOnlyOnline );
	}
}

#include "gadupubdir.moc"
<commit_msg>replaced assignment to QString::null with QString() (should compile/work without problems, if not please e-mail me)<commit_after>//
// Copyright (C) 2003	 Grzegorz Jaskiewicz <gj at pointblue.com.pl>
//
// gadupubdir.cpp
//  Gadu-Gadu Public directory contains people data, using it you can search friends
// different criteria
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301, USA.
//

#include "gadupubdir.h"
#include "gadueditcontact.h"
#include "gaducontactlist.h"
#include "gaduaccount.h"
#include "gaduprotocol.h"

#include <q3widgetstack.h>
#include <q3listview.h>
#include <q3ptrlist.h>
#include <qradiobutton.h>
#include <qspinbox.h>
#include <qcheckbox.h>
//Added by qt3to4:
#include <QPixmap>

#include <kcombobox.h>
#include <krestrictedline.h>
#include <klineedit.h>
#include <k3listview.h>
#include <klocale.h>

GaduPublicDir::GaduPublicDir( GaduAccount* account, QWidget* parent )
: KDialog( parent )
{
	setButtons( KDialog::User1 | KDialog::User2 | KDialog::User3 | KDialog::Cancel );
	setDefaultButton( KDialog::User2 );

	mAccount = account;
	createWidget();
	initConnections();

	show();
}

GaduPublicDir::GaduPublicDir( GaduAccount* account, int searchFor, QWidget* parent )
: KDialog( parent )
{
	setButtons( KDialog::User1 | KDialog::User2 | KDialog::User3 | KDialog::Cancel );
	setDefaultButton( KDialog::User2 );

	ResLine rs;

	mAccount = account;
	createWidget();
	initConnections();

	kDebug( 14100 ) << "search for Uin: " << searchFor << endl;

	mMainWidget->listFound->clear();
	show();

	if ( searchFor == 0 ) {
		return;
	}

	mMainWidget->pubsearch->raiseWidget( 1 );
	mMainWidget->radioByUin->setChecked( true );

	setButtonGuiItem( KDialog::User2, KGuiItem( i18n( "Search &More..." ) ) );
	showButton( KDialog::User3, true );
	showButton( KDialog::User1, true );
	enableButton( KDialog::User3, false );
	enableButton( KDialog::User2, false );

	// now it is time to switch to Right Page(tm)
	rs.uin = searchFor;

	fName	= fSurname = fNick = fCity = QString();
	fUin	= searchFor;
	fGender	= fAgeFrom = fAgeTo = 0;
	fOnlyOnline = false;

	mAccount->pubDirSearch( rs, fAgeFrom, fAgeTo, fOnlyOnline );

}

GaduPublicDir::~GaduPublicDir()
{
	delete mMainWidget;
}

void
GaduPublicDir::createWidget()
{
	setCaption( i18n( "Gadu-Gadu Public Directory" ) );

	QWidget* w = new QWidget( this );
	mMainWidget = new Ui::GaduPublicDirectory;
	mMainWidget->setupUi( this );
	setMainWidget( w );

	mMainWidget->UIN->setValidChars( "1234567890" );

	setButtonGuiItem( KDialog::User1, KGuiItem( i18n( "&New Search" ) ) );
	setButtonGuiItem( KDialog::User2, KGuiItem( i18n( "S&earch" ) ) );
	setButtonGuiItem( KDialog::User3, KGuiItem( i18n( "&Add User..." ) ) );
	setButtonGuiItem( KDialog::Cancel, KGuiItem( i18n( "&Close" ) ) );

	showButton( KDialog::User1, false );
	showButton( KDialog::User3, false );
	enableButton( KDialog::User2, false );

	mMainWidget->radioByData->setChecked( true );

	mAccount->pubDirSearchClose();

}

void
GaduPublicDir::slotAddContact()
{
	GaduContactsList::ContactLine* cl = new GaduContactsList::ContactLine;
	Q3ListViewItem* item = mMainWidget->listFound->currentItem();

	cl->ignored	= false;
	cl->firstname	= item->text( 1 );
	cl->uin		= item->text( 5 );
	cl->nickname 	= item->text( 2 );

	cl->surname	= fSurname;

//	GaduEditContact *ed =
	new GaduEditContact( mAccount, cl, this );
}

void
GaduPublicDir::slotListSelected(  )
{
	Q3ListViewItem* item = mMainWidget->listFound->currentItem();
	if ( item ) {
		enableButton( KDialog::User3, true );
	}
	else {
		enableButton( KDialog::User3, false );
	}
}

void
GaduPublicDir::initConnections()
{
	connect( this, SIGNAL( user2Clicked() ), SLOT( slotSearch() ) );
	connect( this, SIGNAL( user1Clicked() ), SLOT( slotNewSearch() ) );
	connect( this, SIGNAL( user3Clicked() ), SLOT( slotAddContact() ) );

	connect( mAccount, SIGNAL( pubDirSearchResult( const SearchResult&, unsigned int ) ),
				SLOT( slotSearchResult( const SearchResult&, unsigned int ) ) );

	connect( mMainWidget->nameS,		SIGNAL( textChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->surname,		SIGNAL( textChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->nick,		SIGNAL( textChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->UIN,		SIGNAL( textChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->cityS,		SIGNAL( textChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->gender,		SIGNAL( activated( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->ageFrom,		SIGNAL( valueChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->ageTo,		SIGNAL( valueChanged( const QString &) ), SLOT( inputChanged( const QString & ) ) );
	connect( mMainWidget->radioByData,	SIGNAL( toggled( bool ) ), SLOT( inputChanged( bool ) ) );

	connect( mMainWidget->listFound,	SIGNAL( selectionChanged () ), SLOT( slotListSelected() ) );

}

void
GaduPublicDir::inputChanged( bool )
{
	inputChanged( QString::null );
}

void
GaduPublicDir::inputChanged( const QString& )
{
	if ( validateData() == false ) {
		enableButton( User2, false );
	}
	else {
		enableButton( User2, true );
	}
}

void
GaduPublicDir::getData()
{
	fName		= mMainWidget->nameS->text();
	fSurname	= mMainWidget->surname->text();
	fNick		= mMainWidget->nick->text();
	fUin		= mMainWidget->UIN->text().toInt();
	fGender		= mMainWidget->gender->currentItem();
	fOnlyOnline	= mMainWidget->onlyOnline->isChecked();
	fAgeFrom	= mMainWidget->ageFrom->value();
	fAgeTo		= mMainWidget->ageTo->value();
	fCity		= mMainWidget->cityS->text();
}

// return true if not empty
#define CHECK_STRING(A) { if ( !A.isEmpty() ) { return true; } }
#define CHECK_INT(A) { if ( A ) { return true; } }

bool
GaduPublicDir::validateData()
{
	getData();

	if ( mMainWidget->radioByData->isChecked() ) {
		CHECK_STRING( fCity );
		CHECK_STRING( fName );
		CHECK_STRING( fSurname );
		CHECK_STRING( fNick );
		CHECK_INT( fGender );
		CHECK_INT( fAgeFrom );
		CHECK_INT( fAgeTo );
	}
	else {
		fSurname = QString::null;
		CHECK_INT( fUin );
	}
	return false;
}

// Move to GaduProtocol someday
QPixmap
GaduPublicDir::iconForStatus( uint status )
{
	QPixmap n;

	if ( GaduProtocol::protocol() ) {
		return GaduProtocol::protocol()->convertStatus( status ).protocolIcon();
	}
	return n;
}

void
GaduPublicDir::slotSearchResult( const SearchResult& result, unsigned int )
{
	Q3ListView* list = mMainWidget->listFound;

	kDebug(14100) << "searchResults(" << result.count() <<")" << endl;

	Q3ListViewItem* sl;

	SearchResult::const_iterator r;

	for ( r = result.begin(); r != result.end() ; ++r ){
		kDebug(14100) << "adding" << (*r).uin << endl;
		sl= new Q3ListViewItem(
					list, QString::fromAscii(""),
					(*r).firstname,
					(*r).nickname,
					(*r).age,
					(*r).city,
					QString::number( (*r).uin ).toAscii()
						);
		sl->setPixmap( 0, iconForStatus( (*r).status ) );
	}

	// if not found anything, obviously we don't want to search for more
	// if we are looking just for one UIN, don't allow search more - it is pointless

	if ( result.count() && fUin==0 ) {
		enableButton( KDialog:: User2, true );
	}

	enableButton( KDialog::User1, true );
	enableButton( KDialog::User3, false );
	mMainWidget->pubsearch->setDisabled( false );

}

void
GaduPublicDir::slotNewSearch()
{
	mMainWidget->pubsearch->raiseWidget( 0 );

	setButtonGuiItem( KDialog::User2, KGuiItem( i18n( "S&earch" ) ) );

	showButton( KDialog::User1, false );
	showButton( KDialog::User3, false );
	enableButton( KDialog::User2, false );
 	inputChanged( QString() );
 	mAccount->pubDirSearchClose();
}

void
GaduPublicDir::slotSearch()
{

	mMainWidget->listFound->clear();
	QString empty;

	// search more, or search ?
	if ( mMainWidget->pubsearch->id( mMainWidget->pubsearch->visibleWidget() ) == 0 ) {
		kDebug(14100) << "start search... " << endl;
		getData();

		// validate data
		if ( validateData() == false ) {
			return;
		}

		// go on
		mMainWidget->pubsearch->raiseWidget( 1 );

	}
	else{
		kDebug(14100) << "search more... " << endl;
		// Search for more
	}
	mMainWidget->pubsearch->setDisabled( true );
	setButtonGuiItem( KDialog::User2, KGuiItem( i18n( "Search &More..." ) ) );
	showButton( KDialog::User3, true );
	showButton( KDialog::User1, true );
	enableButton( KDialog::User3, false );
	enableButton( KDialog::User2, false );

	ResLine rs;
	rs.firstname	= fName;
	rs.surname	= fSurname;
	rs.nickname	= fNick;
	rs.uin		= fUin;
	rs.city		= fCity;

	if ( fGender == 1 ) {
		rs.gender =  GG_PUBDIR50_GENDER_MALE;
	}
	if ( fGender == 2 ) {
		rs.gender = GG_PUBDIR50_GENDER_FEMALE;
	}

	if ( mMainWidget->radioByData->isChecked() ) {
		mAccount->pubDirSearch( rs, fAgeFrom, fAgeTo, fOnlyOnline );
	}
	else {
		mAccount->pubDirSearch( rs, 0, 0, fOnlyOnline );
	}
}

#include "gadupubdir.moc"
<|endoftext|>