コード例 #1
0
ファイル: hpx_user_main.cpp プロジェクト: 41i/hpx
// depending on whether the main executable defines this symbol or not.
int hpx_startup::user_main()
{
//     hpx::util::section const& ini = hpx::get_runtime().get_config();
//     std::string cmdline(ini.get_entry("hpx.reconstructed_cmd_line", ""));
// 
//     using namespace boost::program_options;
// #if defined(BOOST_WINDOWS)
//     std::vector<std::string> args = split_winmain(cmdline);
// #else
//     std::vector<std::string> args = split_unix(cmdline);
// #endif
// 
//     // Copy all arguments which are not hpx related to a temporary array
//     boost::scoped_array<char*> argv(new char*[args.size()]);
//     std::size_t argcount = 0;
//     for(std::size_t i = 0; i < args.size(); ++i)
//     {
//         if (0 != args[i].find("--hpx:"))
//             argv[argcount++] = const_cast<char*>(args[i].data());
//     }
// 
//     // Invoke hpx_main
//     return user_main(static_cast<int>(argcount), argv.get());
    HPX_THROW_EXCEPTION(hpx::not_implemented, 
        "The console locality does not implement any main entry point usable "
        "as the main HPX thread (e.g. no hpx_main, hpx_startup::user_main, etc.)", 
        "hpx_startup::user_main")
}

コード例 #2
0
 virtual counter_value get_counter_value(bool /*reset*/) override
 {
     HPX_THROW_EXCEPTION(invalid_status, "get_counter_value",
         "get_counter_value is not implemented for this counter");
     return counter_value();
 }
コード例 #3
0
    binpacking_factory::remote_result_type
    binpacking_factory::create_components(components::component_type type,
        std::size_t count) const
    {
        // make sure we get localities for derived component type, if any
        components::component_type prefix_type = type;
        if (type != components::get_base_type(type))
            prefix_type = components::get_derived_type(type);

        // get list of locality prefixes
        std::vector<naming::id_type> localities =
            hpx::find_all_localities(prefix_type);

        if (localities.empty())
        {
            HPX_THROW_EXCEPTION(bad_component_type,
                "binpacking_factory::create_components_binpacked",
                "attempt to create component instance of unknown type: " +
                components::get_component_type_name(type));
        }

        if (count == std::size_t(-1))
            count = localities.size();

        // retrieve the current number of instances of the given component
        std::vector<lcos::future<boost::int32_t> > lazy_counts;
        for (naming::id_type const& id : localities)
        {
            lazy_counts.push_back(
                stubs::runtime_support::get_instance_count_async(id, type));
        }

        // wait for counts to get back, collect statistics
        long maxcount = 0;
        long existing = 0;

        std::vector<long> counts;
        counts.reserve(lazy_counts.size());
        for (lcos::future<boost::int32_t>& f : lazy_counts)
        {
            counts.push_back(f.get());
            maxcount = (std::max)(maxcount, counts.back());
            existing += counts.back();
        }

        // distribute the number of components to create in a way, so that the
        // overall number of component instances on all localities is
        // approximately the same
        HPX_ASSERT(std::size_t(maxcount) * counts.size() >= std::size_t(existing));
        std::size_t missing = std::size_t(maxcount) * counts.size() -
            std::size_t(existing);
        if (missing == 0) missing = 1;

        double hole_ratio = (std::min)(count, missing) / double(missing);
        HPX_ASSERT(hole_ratio <= 1.);

        std::size_t overflow_count =
            (count > missing) ? (count - missing) / counts.size() : 0;
        std::size_t excess = count - overflow_count * counts.size();

        typedef std::vector<lazy_result> future_values_type;
        typedef server::runtime_support::bulk_create_components_action
            action_type;

        std::size_t created_count = 0;
        future_values_type v;

        // start an asynchronous operation for each of the localities
        for (std::size_t i = 0; i < counts.size(); ++i)
        {
            std::size_t numcreate =
                std::size_t((maxcount - counts[i]) * hole_ratio) + overflow_count;

            if (excess != 0) {
                --excess;
                ++numcreate;
            }

            if (i == counts.size()-1) {
                // last bin gets all the rest
                if (created_count + numcreate < count)
                    numcreate = count - created_count;
            }

            if (created_count + numcreate > count)
                numcreate = count - created_count;

            if (numcreate == 0)
                break;

            // create one component at a time
            v.push_back(future_values_type::value_type(localities[i].get_gid()));
            lcos::packaged_action<action_type, std::vector<naming::gid_type> > p;
            p.apply(launch::async, localities[i], type, numcreate);
            v.back().gids_ = p.get_future();

            created_count += numcreate;
            if (created_count >= count)
                break;
        }

        // now wait for the results
        remote_result_type results;

        for (lazy_result& lr : v)
        {
            results.push_back(remote_result_type::value_type(lr.locality_, type));
            results.back().gids_ = std::move(lr.gids_.get());
        }

        return results;
    }
コード例 #4
0
ファイル: hwloc_topology.cpp プロジェクト: fpelliccioni/hpx
    hwloc_topology::hwloc_topology()
      : topo(0), machine_affinity_mask_(0)
    { // {{{
        int err = hwloc_topology_init(&topo);
        if (err != 0)
        {
            HPX_THROW_EXCEPTION(no_success, "hwloc_topology::hwloc_topology",
                "Failed to init hwloc topology");
        }

        err = hwloc_topology_load(topo);
        if (err != 0)
        {
            HPX_THROW_EXCEPTION(no_success, "hwloc_topology::hwloc_topology",
                "Failed to load hwloc topology");
        }

        init_num_of_pus();

        socket_numbers_.reserve(num_of_pus_);
        numa_node_numbers_.reserve(num_of_pus_);
        core_numbers_.reserve(num_of_pus_);

        // Initialize each set of data entirely, as some of the initialization
        // routines rely on access to other pieces of topology data. The
        // compiler will optimize the loops where possible anyways.

        std::size_t num_of_sockets = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_SOCKET);
        if (num_of_sockets == 0) num_of_sockets = 1;
        for (std::size_t i = 0; i < num_of_pus_; ++i)
        {
            std::size_t socket = init_socket_number(i);
            BOOST_ASSERT(socket < num_of_sockets);
            socket_numbers_.push_back(socket);
        }

        std::size_t num_of_nodes = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_NODE);
        if (num_of_nodes == 0) num_of_nodes = 1;
        for (std::size_t i = 0; i < num_of_pus_; ++i)
        {
            std::size_t numa_node = init_numa_node_number(i);
            BOOST_ASSERT(numa_node < num_of_nodes);
            numa_node_numbers_.push_back(numa_node);
        }

        std::size_t num_of_cores = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_CORE);
        if (num_of_cores == 0) num_of_cores = 1;
        for (std::size_t i = 0; i < num_of_pus_; ++i)
        {
            std::size_t core_number = init_core_number(i);
            BOOST_ASSERT(core_number < num_of_cores);
            core_numbers_.push_back(core_number);
        }

        machine_affinity_mask_ = init_machine_affinity_mask();
        socket_affinity_masks_.reserve(num_of_pus_);
        numa_node_affinity_masks_.reserve(num_of_pus_);
        core_affinity_masks_.reserve(num_of_pus_);
        thread_affinity_masks_.reserve(num_of_pus_);

        for (std::size_t i = 0; i < num_of_pus_; ++i)
        {
            socket_affinity_masks_.push_back(init_socket_affinity_mask(i));
        }

        for (std::size_t i = 0; i < num_of_pus_; ++i)
        {
            numa_node_affinity_masks_.push_back(init_numa_node_affinity_mask(i));
        }

        for (std::size_t i = 0; i < num_of_pus_; ++i)
        {
            core_affinity_masks_.push_back(init_core_affinity_mask(i));
        }

        for (std::size_t i = 0; i < num_of_pus_; ++i)
        {
            thread_affinity_masks_.push_back(init_thread_affinity_mask(i));
        }
    } // }}}
コード例 #5
0
ファイル: one_size_heap_list.hpp プロジェクト: johnforce/hpx
        // operations
        void* alloc(std::size_t count = 1)
        {
            unique_lock_type guard(mtx_);

            if (HPX_UNLIKELY(0 == count))
            {
                HPX_THROW_EXCEPTION(bad_parameter,
                    name() + "::alloc",
                    "cannot allocate 0 objects");
            }

            //std::size_t size = 0;
            value_type* p = NULL;
            {
                if (!heap_list_.empty())
                {
                    //size = heap_list_.size();
                    for (iterator it = heap_list_.begin(); it != heap_list_.end(); ++it)
                    {
                        typename list_type::value_type heap = *it;
                        bool allocated = false;

                        {
                            util::scoped_unlock<unique_lock_type> ul(guard);
                            allocated = heap->alloc(&p, count);
                        }

                        if (allocated)
                        {
#if defined(HPX_DEBUG)
                            // Allocation succeeded, update statistics.
                            alloc_count_ += count;
                            if (alloc_count_ - free_count_ > max_alloc_count_)
                                max_alloc_count_ = alloc_count_- free_count_;
#endif
                            return p;
                        }

#if defined(HPX_DEBUG)
                        LOSH_(info)
                            << (boost::format(
                                "%1%::alloc: failed to allocate from heap[%2%] "
                                "(heap[%2%] has allocated %3% objects and has "
                                "space for %4% more objects)")
                                % name()
                                % (*it)->heap_count_
                                % (*it)->size()
                                % (*it)->free_size());
#endif
                    }
                }
            }

            // Create new heap.
            bool did_create = false;
            {
#if defined(HPX_DEBUG)
                heap_list_.push_front(typename list_type::value_type(
                    new heap_type(class_name_.c_str(), heap_count_ + 1, heap_step)));
#else
                heap_list_.push_front(typename list_type::value_type(
                    new heap_type(class_name_.c_str(), 0, heap_step)));
#endif

                iterator itnew = heap_list_.begin();
                typename list_type::value_type heap = *itnew;
                bool result = false;

                {
                    util::scoped_unlock<unique_lock_type> ul(guard);
                    result = heap->alloc(&p, count);
                }

                if (HPX_UNLIKELY(!result || NULL == p))
                {
                    // out of memory
                    HPX_THROW_EXCEPTION(out_of_memory,
                        name() + "::alloc",
                        boost::str(boost::format(
                            "new heap failed to allocate %1% objects")
                            % count));
                }

#if defined(HPX_DEBUG)
                alloc_count_ += count;
                ++heap_count_;

                LOSH_(info)
                    << (boost::format(
                        "%1%::alloc: creating new heap[%2%], size is now %3%")
                        % name()
                        % heap_count_
                        % heap_list_.size());
#endif
                did_create = true;
            }

            if (did_create)
                return p;

            guard.unlock();

            // Try again, we just got a new heap, so we should be good.
            return alloc(count);
        }
コード例 #6
0
 virtual void set_counter_value(counter_value const& /*value*/)
 {
     HPX_THROW_EXCEPTION(invalid_status, "set_counter_value",
         "set_counter_value is not implemented for this counter");
 }
コード例 #7
0
        // operations
        value_type* alloc(std::size_t count = 1)
        {
            if (HPX_UNLIKELY(0 == count))
            {
                HPX_THROW_EXCEPTION(bad_parameter,
                    name() + "::alloc",
                    "cannot allocate 0 objects");
            }

            std::size_t size = 0;
            value_type* p = NULL;
            {
                shared_lock_type guard(mtx_);

                size = heap_list_.size();
                if (size)
                {
                    for (iterator it = heap_list_.begin(); it != heap_list_.end(); ++it)
                    {
                        if ((*it)->alloc(&p, count))
                        {
                            // Allocation succeeded, update statistics.
                            alloc_count_ += count;

                            if (alloc_count_ - free_count_ > max_alloc_count_)
                                max_alloc_count_ = alloc_count_- free_count_;

                            return p;
                        }

                        LOSH_(info)
                            << (boost::format(
                                "%1%::alloc: failed to allocate from heap[%2%] "
                                "(heap[%2%] has allocated %3% objects and has "
                                "space for %4% more objects)")
                                % name()
                                % (*it)->heap_count_
                                % (*it)->size()
                                % (*it)->free_size());
                    }
                }
            }

            // Create new heap.
            bool did_create = false;
            {
                // Acquire exclusive access.
                unique_lock_type ul(mtx_);

                iterator itnew = heap_list_.insert(heap_list_.begin(),
                    typename list_type::value_type(new heap_type
                        (class_name_.c_str(), heap_count_ + 1, heap_step)));

                if (HPX_UNLIKELY(itnew == heap_list_.end()))
                {
                    HPX_THROW_EXCEPTION(out_of_memory,
                        name() + "::alloc",
                        "new heap could not be added");
                }

                bool result = (*itnew)->alloc(&p, count);

                if (HPX_UNLIKELY(!result || NULL == p))
                {
                    // out of memory
                    HPX_THROW_EXCEPTION(out_of_memory,
                        name() + "::alloc",
                        boost::str(boost::format(
                            "new heap failed to allocate %1% objects")
                            % count));
                }

                alloc_count_ += count;
                ++heap_count_;

                LOSH_(info)
                    << (boost::format(
                        "%1%::alloc: creating new heap[%2%], size is now %3%")
                        % name()
                        % heap_count_
                        % heap_list_.size());
                did_create = true;
            }

            if (did_create)
                return p;

            // Try again, we just got a new heap, so we should be good.
            return alloc(count);
        }
コード例 #8
0
ファイル: parcelport.cpp プロジェクト: adk9/hpx
    boost::shared_ptr<parcelport> parcelport::create(int type,
        util::runtime_configuration const& cfg,
        HPX_STD_FUNCTION<void(std::size_t, char const*)> const& on_start_thread,
        HPX_STD_FUNCTION<void()> const& on_stop_thread)
    {
        switch(type) {
        case connection_tcp:
            {
#if defined(HPX_HAVE_PARCELPORT_TCP)
                std::string enable_tcp =
                    cfg.get_entry("hpx.parcel.tcp.enable", "1");

                if (boost::lexical_cast<int>(enable_tcp))
                {
                    return boost::make_shared<policies::tcp::connection_handler>(
                        cfg, on_start_thread, on_stop_thread);
                }
#endif

                HPX_THROW_EXCEPTION(bad_parameter, "parcelport::create",
                    "unsupported connection type 'connection_tcp'");
            }

        case connection_ipc:
            {
#if defined(HPX_HAVE_PARCELPORT_IPC)
                // Create ipc based parcelport only if allowed by the
                // configuration info.
                std::string enable_ipc =
                    cfg.get_entry("hpx.parcel.ipc.enable", "0");

                if (boost::lexical_cast<int>(enable_ipc))
                {
                    return boost::make_shared<policies::ipc::connection_handler>(
                        cfg, on_start_thread, on_stop_thread);
                }
#endif
                HPX_THROW_EXCEPTION(bad_parameter, "parcelport::create",
                    "unsupported connection type 'connection_ipc'");
            }
            break;

        case connection_ibverbs:
#if defined(HPX_HAVE_PARCELPORT_IBVERBS)
            {
                // Create ibverbs based parcelport only if allowed by the
                // configuration info.
                std::string enable_ibverbs =
                    cfg.get_entry("hpx.parcel.ibverbs.enable", "0");

                if (boost::lexical_cast<int>(enable_ibverbs))
                {
                    return boost::make_shared<policies::ibverbs::connection_handler>(
                        cfg, on_start_thread, on_stop_thread);
                }
            }
#endif
            HPX_THROW_EXCEPTION(bad_parameter, "parcelport::create",
                "unsupported connection type 'connection_ibverbs'");
            break;

        case connection_portals4:
            HPX_THROW_EXCEPTION(bad_parameter, "parcelport::create",
                "unsupported connection type 'connection_portals4'");
            break;

        case connection_mpi:
#if defined(HPX_HAVE_PARCELPORT_MPI)
            {
                // Create MPI based parcelport only if allowed by the
                // configuration info.
                std::string enable_mpi =
                    cfg.get_entry("hpx.parcel.mpi.enable", "0");

                if (boost::lexical_cast<int>(enable_mpi))
                {
                    return boost::make_shared<policies::mpi::connection_handler>(
                        cfg, on_start_thread, on_stop_thread);
                }
            }
#endif

            HPX_THROW_EXCEPTION(bad_parameter, "parcelport::create",
                "unsupported connection type 'connection_mpi'");
            break;

        default:
            HPX_THROW_EXCEPTION(bad_parameter, "parcelport::create",
                "unknown connection type");
            break;
        }

        return boost::shared_ptr<parcelport>();
    }
コード例 #9
0
    distributing_factory::remote_result_type
    distributing_factory::create_partitioned(components::component_type type,
        std::size_t count, std::size_t parts, partition_info const& info) const
    {
        // make sure we get prefixes for derived component type, if any
        components::component_type prefix_type = type;
        if (type != components::get_base_type(type))
            prefix_type = components::get_derived_type(type);

        // get list of locality prefixes
        std::vector<naming::id_type> localities =
            hpx::find_all_localities(prefix_type);

        if (localities.empty())
        {
            // no locality supports creating the requested component type
            HPX_THROW_EXCEPTION(bad_component_type,
                "distributing_factory::create_partitioned",
                "attempt to create component instance of unknown type: " +
                components::get_component_type_name(type));
        }

        std::size_t part_size = info.size();
        if (part_size < localities.size())
        {
            // we have less localities than required by one partition
            HPX_THROW_EXCEPTION(bad_parameter,
                "distributing_factory::create_partitioned",
                "partition size is larger than number of localities");
        }

        // a new partition starts every parts_delta localities
        std::size_t parts_delta = 0;
        if (localities.size() > part_size)
            parts_delta = localities.size() / part_size;

        // distribute the number of components to create evenly over all
        // available localities
        typedef std::vector<lazy_result> future_values_type;
        typedef server::runtime_support::bulk_create_components_action
            action_type;

        // start an asynchronous operation for each of the localities
        future_values_type v;

        for (std::size_t i = 0, j = 0;
             i < localities.size() && j < parts;
             i += parts_delta, ++j)
        {
            // create components for each locality in one go, overall, 'count'
            // components for each partition
            v.push_back(future_values_type::value_type(localities[i].get_gid()));
            lcos::packaged_action<action_type, std::vector<naming::gid_type> > p;
            p.apply(localities[i], type, count);
            v.back().gids_ = p.get_future();
        }

        // now wait for the results
        remote_result_type results;

        BOOST_FOREACH(lazy_result& lr, v)
        {
            results.push_back(remote_result_type::value_type(lr.locality_, type));
            results.back().gids_ = boost::move(lr.gids_.move());
        }
コード例 #10
0
        ///////////////////////////////////////////////////////////////////////
        // Queries the current thread count of the queues.
        std::int64_t get_thread_count(thread_state_enum state = unknown,
            thread_priority priority = thread_priority_default,
            std::size_t num_thread = std::size_t(-1), bool reset = false) const
        {
            // Return thread count of one specific queue.
            std::int64_t count = 0;
            if (std::size_t(-1) != num_thread)
            {
                HPX_ASSERT(num_thread < queues_.size());

                switch (priority) {
                case thread_priority_default:
                    {
                        if (num_thread < high_priority_queues_.size())
                            count = high_priority_queues_[num_thread]->
                                get_thread_count(state);

                        if (queues_.size()-1 == num_thread)
                            count += low_priority_queue_.get_thread_count(state);

                        return count + queues_[num_thread]->get_thread_count(state);
                    }

                case thread_priority_low:
                    {
                        if (queues_.size()-1 == num_thread)
                            return low_priority_queue_.get_thread_count(state);
                        break;
                    }

                case thread_priority_normal:
                    return queues_[num_thread]->get_thread_count(state);

                case thread_priority_boost:
                case thread_priority_critical:
                    {
                        if (num_thread < high_priority_queues_.size())
                            return high_priority_queues_[num_thread]->
                            get_thread_count(state);
                        break;
                    }

                default:
                case thread_priority_unknown:
                    {
                        HPX_THROW_EXCEPTION(bad_parameter,
                            "local_priority_queue_scheduler::get_thread_count",
                            "unknown thread priority value (thread_priority_unknown)");
                        return 0;
                    }
                }
                return 0;
            }

            // Return the cumulative count for all queues.
            switch (priority) {
            case thread_priority_default:
                {
                    for (std::size_t i = 0; i != high_priority_queues_.size(); ++i)
                        count += high_priority_queues_[i]->get_thread_count(state);

                    count += low_priority_queue_.get_thread_count(state);

                    for (std::size_t i = 0; i != queues_.size(); ++i)
                        count += queues_[i]->get_thread_count(state);

                    break;
                }

            case thread_priority_low:
                return low_priority_queue_.get_thread_count(state);

            case thread_priority_normal:
                {
                    for (std::size_t i = 0; i != queues_.size(); ++i)
                        count += queues_[i]->get_thread_count(state);
                    break;
                }

            case thread_priority_boost:
            case thread_priority_critical:
                {
                    for (std::size_t i = 0; i != high_priority_queues_.size(); ++i)
                        count += high_priority_queues_[i]->get_thread_count(state);
                    break;
                }

            default:
            case thread_priority_unknown:
                {
                    HPX_THROW_EXCEPTION(bad_parameter,
                        "local_priority_queue_scheduler::get_thread_count",
                        "unknown thread priority value (thread_priority_unknown)");
                    return 0;
                }
            }
            return count;
        }
コード例 #11
0
ファイル: simple_component_base.hpp プロジェクト: DawidvC/hpx
        /// \brief Create a new GID (if called for the first time), assign this
        ///        GID to this instance of a component and register this gid
        ///        with the AGAS service
        ///
        /// \returns      The global id (GID) assigned to this instance of a
        ///               component
        naming::gid_type get_base_gid(
            naming::gid_type const& assign_gid = naming::invalid_gid) const
        {
            if (!gid_)
            {
                applier::applier& appl = hpx::applier::get_applier();
                naming::address addr(appl.here(),
                    components::get_component_type<wrapped_type>(),
                    boost::uint64_t(static_cast<this_component_type const*>(this)));

                if (!assign_gid)
                {
                    gid_ = hpx::detail::get_next_id();
                    if (!applier::bind_gid_local(gid_, addr))
                    {
                        hpx::util::osstream strm;
                        strm << gid_;

                        gid_ = naming::invalid_gid;   // invalidate GID

                        HPX_THROW_EXCEPTION(duplicate_component_address,
                            "simple_component_base<Component>::get_base_gid",
                            hpx::util::osstream_get_string(strm));
                    }
                }
                else
                {
                    gid_ = assign_gid;
                    naming::detail::strip_credits_from_gid(gid_);

                    if (!agas::bind_sync(gid_, addr, appl.get_locality_id()))
                    {
                        hpx::util::osstream strm;
                        strm << gid_;

                        gid_ = naming::invalid_gid;   // invalidate GID

                        HPX_THROW_EXCEPTION(duplicate_component_address,
                            "simple_component_base<Component>::get_base_gid",
                            hpx::util::osstream_get_string(strm));
                    }
                }
            }

            naming::gid_type::mutex_type::scoped_lock l(gid_.get_mutex());

            if (!naming::detail::has_credits(gid_))
            {
                naming::gid_type gid = gid_;
                return gid;
            }

            // on first invocation take all credits to avoid a self reference
            naming::gid_type gid = gid_;

            naming::detail::strip_credits_from_gid(
                const_cast<naming::gid_type&>(gid_));

            HPX_ASSERT(naming::detail::has_credits(gid));

            // We have to assume this credit was split as otherwise the gid
            // returned at this point will control the lifetime of the
            // component.
            naming::detail::set_credit_split_mask_for_gid(gid);
            return gid;
        }
コード例 #12
0
ファイル: error_handling.cpp プロジェクト: AntonBikineev/hpx
//[error_handling_raise_exception
void raise_exception()
{
    HPX_THROW_EXCEPTION(hpx::no_success, "raise_exception", "simulated error");
}
コード例 #13
0
ファイル: decode_parcels.hpp プロジェクト: ltroska/hpx
    void decode_message_with_chunks(
        Parcelport & pp
      , Buffer buffer
      , std::size_t parcel_count
      , std::vector<serialization::serialization_chunk> &chunks
      , std::size_t num_thread = -1
    )
    {
        std::uint64_t inbound_data_size = buffer.data_size_;

        // protect from un-handled exceptions bubbling up
        try {
            try {
                // mark start of serialization
                util::high_resolution_timer timer;
                std::int64_t overall_add_parcel_time = 0;
                performance_counters::parcels::data_point& data =
                    buffer.data_point_;

                {
                    std::vector<parcel> deferred_parcels;
                    // De-serialize the parcel data
                    serialization::input_archive archive(buffer.data_,
                        inbound_data_size, &chunks);

                    if(parcel_count == 0)
                    {
                        archive >> parcel_count; //-V128
                        if (parcel_count > 1)
                            deferred_parcels.reserve(parcel_count);
                    }
                    for(std::size_t i = 0; i != parcel_count; ++i)
                    {
                        bool deferred_schedule = true;
                        if (i == parcel_count - 1) deferred_schedule = false;

#if defined(HPX_HAVE_PARCELPORT_ACTION_COUNTERS)
                        std::size_t archive_pos = archive.current_pos();
                        std::int64_t serialize_time = timer.elapsed_nanoseconds();
#endif
                        // de-serialize parcel and add it to incoming parcel queue
                        parcel p;
                        // deferred_schedule will be set to false if it was previously
                        // set to true and the action to be scheduled is direct.
                        bool migrated = p.load_schedule(archive, num_thread,
                            deferred_schedule);

                        std::int64_t add_parcel_time = timer.elapsed_nanoseconds();

#if defined(HPX_HAVE_PARCELPORT_ACTION_COUNTERS)
                        performance_counters::parcels::data_point action_data;
                        action_data.bytes_ = archive.current_pos() - archive_pos;
                        action_data.serialization_time_ =
                            add_parcel_time - serialize_time;
                        action_data.num_parcels_ = 1;
                        pp.add_received_data(p.get_action()->get_action_name(),
                            action_data);
#endif

                        // make sure this parcel ended up on the right locality
                        naming::gid_type const& here = hpx::get_locality();
                        if (hpx::get_runtime_ptr() && here &&
                            (naming::get_locality_id_from_gid(
                                 p.destination_locality()) !=
                             naming::get_locality_id_from_gid(here)))
                        {
                            std::ostringstream os;
                            os << "parcel destination does not match "
                                  "locality which received the parcel ("
                               << here << "), " << p;
                            HPX_THROW_EXCEPTION(invalid_status,
                                "hpx::parcelset::decode_message",
                                os.str());
                            return;
                        }

                        if (migrated)
                        {
                            naming::resolver_client& client =
                                hpx::naming::get_agas_client();
                            client.route(
                                std::move(p),
                                &detail::parcel_route_handler,
                                threads::thread_priority_normal);
                        }
                        else if (deferred_schedule)
                            deferred_parcels.push_back(std::move(p));

                        // be sure not to measure add_parcel as serialization time
                        overall_add_parcel_time += timer.elapsed_nanoseconds() -
                            add_parcel_time;
                    }

                    // complete received data with parcel count
                    data.num_parcels_ = parcel_count;
                    data.raw_bytes_ = archive.bytes_read();

                    for (std::size_t i = 0; i != deferred_parcels.size(); ++i)
                    {
                        // If we are the last deferred parcel, we don't need to spin
                        // a new thread...
                        if (i == deferred_parcels.size() - 1)
                        {
                            deferred_parcels[i].schedule_action(num_thread);
                        }
                        // ... otherwise, schedule the parcel on a new thread.
                        else
                        {
                            hpx::applier::register_thread_nullary(
                                util::bind(
                                    util::one_shot(
                                        [num_thread](parcel&& p)
                                        {
                                            p.schedule_action(num_thread);
                                        }
                                    ), std::move(deferred_parcels[i])),
                                "schedule_parcel",
                                threads::pending, true, threads::thread_priority_critical,
                                num_thread, threads::thread_stacksize_default);
                        }
                    }
                }

                // store the time required for serialization
                data.serialization_time_ = timer.elapsed_nanoseconds() -
                    overall_add_parcel_time;

                pp.add_received_data(data);
            }
            catch (hpx::exception const& e) {
                LPT_(error)
                    << "decode_message: caught hpx::exception: "
                    << e.what();
                hpx::report_error(boost::current_exception());
            }
            catch (boost::system::system_error const& e) {
                LPT_(error)
                    << "decode_message: caught boost::system::error: "
                    << e.what();
                hpx::report_error(boost::current_exception());
            }
            catch (boost::exception const&) {
                LPT_(error)
                    << "decode_message: caught boost::exception.";
                hpx::report_error(boost::current_exception());
            }
            catch (std::exception const& e) {
                // We have to repackage all exceptions thrown by the
                // serialization library as otherwise we will loose the
                // e.what() description of the problem, due to slicing.
                boost::throw_exception(boost::enable_error_info(
                    hpx::exception(serialization_error, e.what())));
            }
        }
コード例 #14
0
ファイル: thread_queue.hpp プロジェクト: ct-clmsn/hpx
        ///////////////////////////////////////////////////////////////////////
        // add new threads if there is some amount of work available
        std::size_t add_new(std::int64_t add_count, thread_queue* addfrom,
            std::unique_lock<mutex_type> &lk, bool steal = false)
        {
            HPX_ASSERT(lk.owns_lock());

            if (HPX_UNLIKELY(0 == add_count))
                return 0;

            std::size_t added = 0;
            task_description* task = nullptr;
            while (add_count-- && addfrom->new_tasks_.pop(task, steal))
            {
#ifdef HPX_HAVE_THREAD_QUEUE_WAITTIME
                if (maintain_queue_wait_times) {
                    addfrom->new_tasks_wait_ +=
                        util::high_resolution_clock::now() - util::get<2>(*task);
                    ++addfrom->new_tasks_wait_count_;
                }
#endif
                --addfrom->new_tasks_count_;

                // measure thread creation time
                util::block_profiler_wrapper<add_new_tag> bp(add_new_logger_);

                // create the new thread
                threads::thread_init_data& data = util::get<0>(*task);
                thread_state_enum state = util::get<1>(*task);
                threads::thread_id_type thrd;

                create_thread_object(thrd, data, state, lk);

                delete task;

                // add the new entry to the map of all threads
                std::pair<thread_map_type::iterator, bool> p =
                    thread_map_.insert(thrd);

                if (HPX_UNLIKELY(!p.second)) {
                    lk.unlock();
                    HPX_THROW_EXCEPTION(hpx::out_of_memory,
                        "threadmanager::add_new",
                        "Couldn't add new thread to the thread map");
                    return 0;
                }
                ++thread_map_count_;

                // only insert the thread into the work-items queue if it is in
                // pending state
                if (state == pending) {
                    // pushing the new thread into the pending queue of the
                    // specified thread_queue
                    ++added;
                    schedule_thread(thrd.get());
                }

                // this thread has to be in the map now
                HPX_ASSERT(thread_map_.find(thrd.get()) != thread_map_.end());
                HPX_ASSERT(thrd->get_pool() == &memory_pool_);
            }

            if (added) {
                LTM_(debug) << "add_new: added " << added << " tasks to queues"; //-V128
            }
            return added;
        }
コード例 #15
0
ファイル: applier.cpp プロジェクト: gbibek/hpx-1
    // schedule threads based on given parcel
    void applier::schedule_action(parcelset::parcel const& p)
    {
        // decode the action-type in the parcel
        actions::continuation_type cont = p.get_continuation();
        actions::action_type act = p.get_action();

#if defined(HPX_HAVE_SECURITY)
        // we look up the certificate of the originating locality, no matter
        // whether this parcel was routed through another locality or not
        boost::uint32_t locality_id =
            naming::get_locality_id_from_gid(p.get_parcel_id());
        error_code ec(lightweight);
        components::security::signed_certificate const& cert =
            get_locality_certificate(locality_id, ec);

        if (verify_capabilities_ && ec) {
            // we should have received the sender's certificate by now
            HPX_THROW_EXCEPTION(security_error,
                "applier::schedule_action",
                boost::str(boost::format("couldn't extract sender's "
                    "certificate (sender locality id: %1%)") % locality_id));
            return;
        }

        components::security::capability caps_sender;
        if (verify_capabilities_)
            caps_sender = cert.get_type().get_capability();
#endif
        int comptype = act->get_component_type();
        naming::locality dest = p.get_destination_locality();

        // fetch the set of destinations
        std::size_t size = p.size();
        naming::id_type const* ids = p.get_destinations();
        naming::address const* addrs = p.get_destination_addrs();

        // if the parcel carries a continuation it should be directed to a
        // single destination
        HPX_ASSERT(!cont || size == 1);

        // schedule a thread for each of the destinations
        for (std::size_t i = 0; i != size; ++i)
        {
            naming::address const& addr = addrs[i];

            // make sure this parcel destination matches the proper locality
            HPX_ASSERT(dest == addr.locality_);

            // decode the local virtual address of the parcel
            naming::address::address_type lva = addr.address_;

            // by convention, a zero address references the local runtime
            // support component
            if (0 == lva)
            {
                lva = get_runtime_support_raw_gid().get_lsb();
            }
            else if (comptype == components::component_memory)
            {
                HPX_ASSERT(naming::refers_to_virtual_memory(ids[i].get_gid()));
                lva = get_memory_raw_gid().get_lsb();
            }

#if defined(HPX_HAVE_SECURITY)
            if (verify_capabilities_) {
                components::security::capability caps_action =
                    act->get_required_capabilities(lva);

                if (caps_action.verify(caps_sender) == false) {
                    HPX_THROW_EXCEPTION(security_error,
                        "applier::schedule_action",
                        boost::str(boost::format("sender has insufficient capabilities "
                            "to execute the action (%1%, sender: %2%, action %3%)") %
                            act->get_action_name() % caps_sender % caps_action));
                    return;
                }
            }
#endif
            // make sure the component_type of the action matches the
            // component type in the destination address
            if (HPX_UNLIKELY(!components::types_are_compatible(
                addr.type_, comptype)))
            {
                hpx::util::osstream strm;
                strm << " types are not compatible: destination_type("
                      << addr.type_ << ") action_type(" << comptype
                      << ") parcel ("  << p << ")";
                HPX_THROW_EXCEPTION(bad_component_type,
                    "action_manager::fetch_parcel",
                    hpx::util::osstream_get_string(strm));
            }

            // dispatch action, register work item either with or without
            // continuation support
            if (!cont) {
                // No continuation is to be executed, register the plain
                // action and the local-virtual address.
                act->schedule_thread(ids[i], lva, threads::pending);
            }
            else {
                // This parcel carries a continuation, register a wrapper
                // which first executes the original thread function as
                // required by the action and triggers the continuations
                // afterwards.
                act->schedule_thread(cont, ids[i], lva, threads::pending);
            }
        }
    }
コード例 #16
0
    ///////////////////////////////////////////////////////////////////////////
    // Call-back function for parcelHandler to call when new parcels are received
    void action_manager::fetch_parcel(
        parcelset::parcelhandler& parcel_handler,
        naming::gid_type const& parcel_id)
    {
        parcelset::parcel p;
        if (!parcel_handler.get_parcel(p, parcel_id))
            return;

        while (threads::threadmanager_is(starting))
        {
            boost::this_thread::sleep(boost::get_system_time() +
                boost::posix_time::milliseconds(HPX_NETWORK_RETRIES_SLEEP));
        }

        // Give up if we're shutting down.
        if (threads::threadmanager_is(stopping))
        {
            LPT_(debug) << "action_manager: fetch_parcel: dropping late "
                            "parcel " << p;
            return;
        }

        // write this parcel to the log
        LPT_(debug) << "action_manager: fetch_parcel: " << p;

        // decode the action-type in the parcel
        continuation_type cont = p.get_continuation();
        actions::action_type act = p.get_action();
        actions::base_action::action_type acttype = act->get_action_type();
        int comptype = act->get_component_type();
        naming::locality dest = p.get_destination_locality();

        // fetch the set of destinations
        std::vector<naming::address> const& addrs = p.get_destination_addrs();

        // if the parcel carries a continuation it should be directed to a
        // single destination
        BOOST_ASSERT(!cont || addrs.size() == 1);

        // schedule a thread for each of the destinations
        threads::threadmanager_base& tm = appl_.get_thread_manager();
        std::vector<naming::address>::const_iterator end = addrs.end();
        for (std::vector<naming::address>::const_iterator it = addrs.begin();
             it != end; ++it)
        {
            naming::address const& addr = *it;

            // make sure this parcel destination matches the proper locality
            BOOST_ASSERT(dest == addr.locality_);

            // decode the local virtual address of the parcel
            naming::address::address_type lva = addr.address_;

            // by convention, a zero address references the local runtime
            // support component
            if (0 == lva)
                lva = appl_.get_runtime_support_raw_gid().get_lsb();

            // make sure the component_type of the action matches the
            // component type in the destination address
            if (HPX_UNLIKELY(!components::types_are_compatible(
                addr.type_, comptype)))
            {
                hpx::util::osstream strm;
                strm << " types are not compatible: destination_type("
                      << addr.type_ << ") action_type(" << comptype
                      << ") parcel ("  << p << ")";
                HPX_THROW_EXCEPTION(bad_component_type,
                    "action_manager::fetch_parcel",
                    hpx::util::osstream_get_string(strm));
            }

            // either directly execute the action or create a new thread
            if (actions::base_action::direct_action == acttype)
            {
                // direct execution of the action
                if (!cont) {
                    // No continuation is to be executed.
                    act->get_thread_function(lva)(threads::wait_signaled);
                }
                else {
                    // This parcel carries a continuation, we execute a wrapper
                    // handling all related functionality.
                    act->get_thread_function(cont, lva)(threads::wait_signaled);
                }
            }
            else {
                // dispatch action, register work item either with or without
                // continuation support
                if (!cont) {
                    // No continuation is to be executed, register the plain 
                    // action and the local-virtual address with the TM only.
                    threads::thread_init_data data;
                    tm.register_work(
                        act->get_thread_init_data(lva, data),
                        threads::pending);
                }
                else {
                    // This parcel carries a continuation, register a wrapper 
                    // which first executes the original thread function as 
                    // required by the action and triggers the continuations 
                    // afterwards.
                    threads::thread_init_data data;
                    tm.register_work(
                        act->get_thread_init_data(cont, lva, data),
                        threads::pending);
                }
            }
        }
    }
コード例 #17
0
 /// the following functions are not implemented by default, they will
 /// just throw
 virtual void reset_counter_value()
 {
     HPX_THROW_EXCEPTION(invalid_status, "reset_counter_value",
         "reset_counter_value is not implemented for this counter");
 }
コード例 #18
0
ファイル: connection_handler_mpi.cpp プロジェクト: amitkr/hpx
    void connection_handler::handle_messages()
    {
        detail::handling_messages hm(handling_messages_);       // reset on exit

        bool bootstrapping = hpx::is_starting();
        bool has_work = true;
        std::size_t k = 0;

        hpx::util::high_resolution_timer t;
        std::list<std::pair<int, MPI_Request> > close_requests;

        // We let the message handling loop spin for another 2 seconds to avoid the
        // costs involved with posting it to asio
        while(bootstrapping || has_work || (!has_work && t.elapsed() < 2.0))
        {
            if(stopped_) break;

            // break the loop if someone requested to pause the parcelport
            if(!enable_parcel_handling_) break;

            // handle all send requests
            {
                hpx::lcos::local::spinlock::scoped_lock l(senders_mtx_);
                for(
                    senders_type::iterator it = senders_.begin();
                    !stopped_ && enable_parcel_handling_ && it != senders_.end();
                    /**/)
                {
                    if((*it)->done())
                    {
                        it = senders_.erase(it);
                    }
                    else
                    {
                        ++it;
                    }
                }
                has_work = !senders_.empty();
            }

            // Send the pending close requests
            {
                hpx::lcos::local::spinlock::scoped_lock l(close_mtx_);
                typedef std::pair<int, int> pair_type;

                BOOST_FOREACH(pair_type p, pending_close_requests_)
                {
                    header close_request = header::close(p.first, p.second);
                    close_requests.push_back(std::make_pair(p.first, MPI_Request()));
                    MPI_Isend(
                        close_request.data(),         // Data pointer
                        close_request.data_size_,     // Size
                        close_request.type(),         // MPI Datatype
                        close_request.rank(),         // Destination
                        0,                            // Tag
                        communicator_,                // Communicator
                        &close_requests.back().second
                    );
                }
                pending_close_requests_.clear();
            }

            // add new receive requests
            std::pair<bool, header> next(acceptor_.next_header());
            if(next.first)
            {
                boost::shared_ptr<receiver> rcv;
                header h = next.second;

                receivers_tag_map_type & tag_map = receivers_map_[h.rank()];

                receivers_tag_map_type::iterator jt = tag_map.find(h.tag());

                if(jt != tag_map.end())
                {
                    rcv = jt->second;
                }
                else
                {
                    rcv = boost::make_shared<receiver>(
                        communicator_
                      , get_next_tag()
                      , h.tag()
                      , h.rank()
                      , *this);
                    tag_map.insert(std::make_pair(h.tag(), rcv));
                }

                if(h.close_request())
                {
                    rcv->close();
                }
                else
                {
                    h.assert_valid();
                    if (static_cast<std::size_t>(h.size()) > this->get_max_message_size())
                    {
                        // report this problem ...
                        HPX_THROW_EXCEPTION(boost::asio::error::operation_not_supported,
                            "mpi::connection_handler::handle_messages",
                            "The size of this message exceeds the maximum inbound data size");
                        return;
                    }
                    if(rcv->async_read(h))
                    {
#ifdef HPX_DEBUG
                        receivers_type::iterator it = std::find(receivers_.begin(), receivers_.end(), rcv);
                        HPX_ASSERT(it == receivers_.end());

#endif
                        receivers_.push_back(rcv);
                    }
                }
            }

            // handle all receive requests
            for(receivers_type::iterator it = receivers_.begin();
                it != receivers_.end(); /**/)
            {
                boost::shared_ptr<receiver> rcv = *it;
                if(rcv->done())
                {
                    HPX_ASSERT(rcv->sender_tag() != -1);
                    if(rcv->closing())
                    {
                        receivers_tag_map_type & tag_map = receivers_map_[rcv->rank()];

                        receivers_tag_map_type::iterator jt = tag_map.find(rcv->sender_tag());
                        HPX_ASSERT(jt != tag_map.end());
                        tag_map.erase(jt);
                        {
                            hpx::lcos::local::spinlock::scoped_lock l(tag_mtx_);
                            free_tags_.push_back(rcv->tag());
                        }
                    }
                    it = receivers_.erase(it);
                }
                else
                {
                    ++it;
                }
            }
            if(!has_work) has_work = !receivers_.empty();

            // handle completed close requests
            for(
                std::list<std::pair<int, MPI_Request> >::iterator it = close_requests.begin();
                !stopped_ && enable_parcel_handling_ && it != close_requests.end();
            )
            {
                int completed = 0;
                MPI_Status status;
                int ret = 0;
                ret = MPI_Test(&it->second, &completed, &status);
                HPX_ASSERT(ret == MPI_SUCCESS);
                if(completed && status.MPI_ERROR != MPI_ERR_PENDING)
                {
                    hpx::lcos::local::spinlock::scoped_lock l(tag_mtx_);
                    free_tags_.push_back(it->first);
                    it = close_requests.erase(it);
                }
                else
                {
                    ++it;
                }
            }
            if(!has_work)
                has_work = !close_requests.empty();

            if (bootstrapping)
                bootstrapping = hpx::is_starting();

            if(has_work)
            {
                t.restart();
                k = 0;
            }
            else
            {
                if(enable_parcel_handling_)
                {
                    hpx::lcos::local::spinlock::yield(k);
                    ++k;
                }
            }
        }
コード例 #19
0
void hpx_thread_func()
{
    HPX_THROW_EXCEPTION(hpx::invalid_status, "hpx_thread_func", "test");
}
コード例 #20
0
ファイル: applier.cpp プロジェクト: parsa/hpx
    // schedule threads based on given parcel
    void applier::schedule_action(parcelset::parcel p, std::size_t num_thread)
    {
        // fetch the set of destinations
#if !defined(HPX_SUPPORT_MULTIPLE_PARCEL_DESTINATIONS)
        std::size_t const size = 1ul;
#else
        std::size_t const size = p.size();
#endif
        naming::id_type const* ids = p.destinations();
        naming::address const* addrs = p.addrs();

        // decode the action-type in the parcel
        std::unique_ptr<actions::continuation> cont = p.get_continuation();
        actions::base_action * act = p.get_action();

#if defined(HPX_HAVE_SECURITY)
        // we look up the certificate of the originating locality, no matter
        // whether this parcel was routed through another locality or not
        boost::uint32_t locality_id =
            naming::get_locality_id_from_gid(p.get_parcel_id());
        error_code ec(lightweight);
        components::security::signed_certificate const& cert =
            get_locality_certificate(locality_id, ec);

        if (verify_capabilities_ && ec) {
            // we should have received the sender's certificate by now
            HPX_THROW_EXCEPTION(security_error,
                "applier::schedule_action",
                boost::str(boost::format("couldn't extract sender's "
                    "certificate (sender locality id: %1%)") % locality_id));
            return;
        }

        components::security::capability caps_sender;
        if (verify_capabilities_)
            caps_sender = cert.get_type().get_capability();
#endif
        int comptype = act->get_component_type();
        naming::gid_type dest = p.destination_locality();

        // if the parcel carries a continuation it should be directed to a
        // single destination
        HPX_ASSERT(!cont || size == 1);

        naming::resolver_client& client = hpx::naming::get_agas_client();

        // schedule a thread for each of the destinations
        for (std::size_t i = 0; i != size; ++i)
        {
            naming::address const& addr = addrs[i];

            // make sure this parcel destination matches the proper locality
            HPX_ASSERT(dest == addr.locality_);

            // decode the local virtual address of the parcel
            naming::address::address_type lva = addr.address_;

            // by convention, a zero address references either the local
            // runtime support component or one of the AGAS components
            if (0 == lva)
            {
                switch(comptype)
                {
                case components::component_runtime_support:
                    lva = get_runtime_support_raw_gid().get_lsb();
                    break;

                case components::component_agas_primary_namespace:
                    lva = get_agas_client().get_primary_ns_lva();
                    break;

                case components::component_agas_symbol_namespace:
                    lva = get_agas_client().get_symbol_ns_lva();
                    break;

                case components::component_plain_function:
                    break;

                default:
                    HPX_ASSERT(false);
                }
            }
            else if (comptype == components::component_memory)
            {
                HPX_ASSERT(naming::refers_to_virtual_memory(ids[i].get_gid()));
                lva = get_memory_raw_gid().get_lsb();
            }

            // make sure the target has not been migrated away
            auto r = act->was_object_migrated(ids[i], lva);
            if (r.first)
            {
#if defined(HPX_SUPPORT_MULTIPLE_PARCEL_DESTINATIONS)
                // it's unclear at this point what could be done if there is
                // more than one destination
                HPX_ASSERT(size == 1);
#endif
                // set continuation in outgoing parcel
                if (cont)
                    p.set_continuation(std::move(cont));

                // route parcel to new locality of target
                client.route(
                    std::move(p),
                    util::bind(&detail::parcel_sent_handler,
                        boost::ref(parcel_handler_),
                        util::placeholders::_1, util::placeholders::_2),
                    threads::thread_priority_normal);
                break;
            }

#if defined(HPX_HAVE_SECURITY)
            if (verify_capabilities_) {
                components::security::capability caps_action =
                    act->get_required_capabilities(lva);

                if (caps_action.verify(caps_sender) == false) {
                    HPX_THROW_EXCEPTION(security_error,
                        "applier::schedule_action",
                        boost::str(boost::format("sender has insufficient capabilities "
                            "to execute the action (%1%, sender: %2%, action %3%)") %
                            act->get_action_name() % caps_sender % caps_action));
                    return;
                }
            }
#endif
            // make sure the component_type of the action matches the
            // component type in the destination address
            if (HPX_UNLIKELY(!components::types_are_compatible(
                addr.type_, comptype)))
            {
                std::ostringstream strm;
                strm << " types are not compatible: destination_type("
                      << addr.type_ << ") action_type(" << comptype
                      << ") parcel ("  << p << ")";
                HPX_THROW_EXCEPTION(bad_component_type,
                    "applier::schedule_action",
                    strm.str());
            }

            // dispatch action, register work item either with or without
            // continuation support
            if (!cont) {
                // No continuation is to be executed, register the plain
                // action and the local-virtual address.
                act->schedule_thread(ids[i], lva, threads::pending, num_thread);
            }
            else {
                // This parcel carries a continuation, register a wrapper
                // which first executes the original thread function as
                // required by the action and triggers the continuations
                // afterwards.
                act->schedule_thread(std::move(cont), ids[i], lva,
                    threads::pending, num_thread);
            }
        }
    }
コード例 #21
0
ファイル: decode_parcels.hpp プロジェクト: sharmaar12/hpx
    void decode_message(Parcelport & pp,
        boost::shared_ptr<Buffer> buffer,
        std::vector<util::serialization_chunk> const *chunks,
        bool first_message = false)
    {
        unsigned archive_flags = boost::archive::no_header;
        if (!pp.allow_array_optimizations()) {
            archive_flags |= util::disable_array_optimization;
            archive_flags |= util::disable_data_chunking;
        }
        else if (!pp.allow_zero_copy_optimizations()) {
            archive_flags |= util::disable_data_chunking;
        }
        boost::uint64_t inbound_data_size = buffer->data_size_;

        // protect from un-handled exceptions bubbling up
        try {
            try {
                // mark start of serialization
                util::high_resolution_timer timer;
                boost::int64_t overall_add_parcel_time = 0;
                performance_counters::parcels::data_point& data =
                    buffer->data_point_;

                {
                    // De-serialize the parcel data
                    util::portable_binary_iarchive archive(buffer->data_,
                        chunks, inbound_data_size, archive_flags);

                    std::size_t parcel_count = 0;
                    archive >> parcel_count; //-V128
                    for(std::size_t i = 0; i != parcel_count; ++i)
                    {
#if defined(HPX_HAVE_SECURITY)
                        naming::gid_type parcel_id;
                        if (pp.enable_security())
                        {
                            // handle certificate and verify parcel suffix once
                            first_message = deserialize_certificate(archive,
                                first_message);
                            if (!first_message && i == 0)
                            {
                                verify_message_suffix(buffer->data_,
                                    buffer->data_point_, parcel_id);
                            }
                        }

                        // de-serialize parcel and add it to incoming parcel queue
                        parcel p;
                        archive >> p;

                        // verify parcel id, but only once while handling the
                        // first parcel
                        if (pp.enable_security() && !first_message && i == 0 &&
                            parcel_id != p.get_parcel_id())
                        {
                            // again, all hell breaks loose
                            HPX_THROW_EXCEPTION(security_error,
                                "decode_message", "parcel id mismatch");
                            return;
                        }
#else
                        // de-serialize parcel and add it to incoming parcel queue
                        parcel p;
                        archive >> p;
#endif
                        // make sure this parcel ended up on the right locality
                        HPX_ASSERT(p.get_destination_locality() == pp.here());

                        // be sure not to measure add_parcel as serialization time
                        boost::int64_t add_parcel_time = timer.elapsed_nanoseconds();
                        pp.add_received_parcel(p);
                        overall_add_parcel_time += timer.elapsed_nanoseconds() -
                            add_parcel_time;
                    }

                    // complete received data with parcel count
                    data.num_parcels_ = parcel_count;
                    data.raw_bytes_ = archive.bytes_read();
                }

                // store the time required for serialization
                data.serialization_time_ = timer.elapsed_nanoseconds() -
                    overall_add_parcel_time;

                pp.add_received_data(data);
            }
            catch (hpx::exception const& e) {
                LPT_(error)
                    << "decode_message: caught hpx::exception: "
                    << e.what();
                hpx::report_error(boost::current_exception());
            }
            catch (boost::system::system_error const& e) {
                LPT_(error)
                    << "decode_message: caught boost::system::error: "
                    << e.what();
                hpx::report_error(boost::current_exception());
            }
            catch (boost::exception const&) {
                LPT_(error)
                    << "decode_message: caught boost::exception.";
                hpx::report_error(boost::current_exception());
            }
            catch (std::exception const& e) {
                // We have to repackage all exceptions thrown by the
                // serialization library as otherwise we will loose the
                // e.what() description of the problem, due to slicing.
                boost::throw_exception(boost::enable_error_info(
                    hpx::exception(serialization_error, e.what())));
            }
        }
        catch (...) {
            LPT_(error)
                << "decode_message: caught unknown exception.";
            hpx::report_error(boost::current_exception());
        }
    }
コード例 #22
0
ファイル: thread_pool.cpp プロジェクト: wzugang/hpx
    bool thread_pool<Scheduler>::run(boost::unique_lock<boost::mutex>& l,
        std::size_t num_threads)
    {
        HPX_ASSERT(l.owns_lock());

        LTM_(info) //-V128
            << "thread_pool::run: " << pool_name_
            << " number of processing units available: " //-V128
            << threads::hardware_concurrency();
        LTM_(info) //-V128
            << "thread_pool::run: " << pool_name_
            << " creating " << num_threads << " OS thread(s)"; //-V128

        if (0 == num_threads) {
            HPX_THROW_EXCEPTION(bad_parameter,
                "thread_pool::run", "number of threads is zero");
        }

#if defined(HPX_HAVE_THREAD_CUMULATIVE_COUNTS) && \
    defined(HPX_HAVE_THREAD_IDLE_RATES)
        // scale timestamps to nanoseconds
        boost::uint64_t base_timestamp = util::hardware::timestamp();
        boost::uint64_t base_time = util::high_resolution_clock::now();
        boost::uint64_t curr_timestamp = util::hardware::timestamp();
        boost::uint64_t curr_time = util::high_resolution_clock::now();

        while ((curr_time - base_time) <= 100000)
        {
            curr_timestamp = util::hardware::timestamp();
            curr_time = util::high_resolution_clock::now();
        }

        if (curr_timestamp - base_timestamp != 0)
        {
            timestamp_scale_ = double(curr_time - base_time) /
                double(curr_timestamp - base_timestamp);
        }

        LTM_(info)
            << "thread_pool::run: " << pool_name_
            << " timestamp_scale: " << timestamp_scale_; //-V128
#endif

        if (!threads_.empty() || sched_.has_reached_state(state_running))
            return true;    // do nothing if already running

        executed_threads_.resize(num_threads);
        executed_thread_phases_.resize(num_threads);
        tfunc_times_.resize(num_threads);
        exec_times_.resize(num_threads);

        try {
            HPX_ASSERT(startup_.get() == 0);
            startup_.reset(
                new boost::barrier(static_cast<unsigned>(num_threads+1))
            );

            // run threads and wait for initialization to complete
            sched_.set_all_states(state_running);

            topology const& topology_ = get_topology();

            std::size_t thread_num = num_threads;
            while (thread_num-- != 0) {
                threads::mask_cref_type mask =
                    sched_.Scheduler::get_pu_mask(topology_, thread_num);

                LTM_(info) //-V128
                    << "thread_pool::run: " << pool_name_
                    << " create OS thread " << thread_num //-V128
                    << ": will run on processing units within this mask: "
#if !defined(HPX_WITH_MORE_THAN_64_THREADS) || \
    (defined(HPX_HAVE_MAX_CPU_COUNT) && HPX_HAVE_MAX_CPU_COUNT <= 64)
                    << std::hex << "0x" << mask;
#else
                    << "0b" << mask;
#endif

                // create a new thread
                threads_.push_back(new boost::thread(
                        util::bind(&thread_pool::thread_func, this, thread_num,
                            boost::ref(topology_), boost::ref(*startup_))
                    ));

                // set the new threads affinity (on Windows systems)
                if (any(mask))
                {
                    error_code ec(lightweight);
                    topology_.set_thread_affinity_mask(threads_.back(), mask, ec);
                    if (ec)
                    {
                        LTM_(warning) //-V128
                            << "thread_pool::run: " << pool_name_
                            << " setting thread affinity on OS thread " //-V128
                            << thread_num << " failed with: "
                            << ec.get_message();
                    }
                }
                else
                {
                    LTM_(debug) //-V128
                        << "thread_pool::run: " << pool_name_
                        << " setting thread affinity on OS thread " //-V128
                        << thread_num << " was explicitly disabled.";
                }
            }

            // the main thread needs to have a unique thread_num
            init_tss(num_threads);
            startup_->wait();
        }
コード例 #23
0
ファイル: one_size_heap_list.cpp プロジェクト: biddisco/hpx
    void* one_size_heap_list::alloc(std::size_t count)
    {
        unique_lock_type guard(mtx_);

        if (HPX_UNLIKELY(0 == count))
        {
            guard.unlock();
            HPX_THROW_EXCEPTION(bad_parameter,
                name() + "::alloc",
                "cannot allocate 0 objects");
        }

        //std::size_t size = 0;
        void* p = nullptr;
        {
            if (!heap_list_.empty())
            {
                //size = heap_list_.size();
                for (auto & heap : heap_list_)
                {
                    bool allocated = false;

                    {
                        util::unlock_guard<unique_lock_type> ul(guard);
                        allocated = heap->alloc(&p, count);
                    }

                    if (allocated)
                    {
#if defined(HPX_DEBUG)
                        // Allocation succeeded, update statistics.
                        alloc_count_ += count;
                        if (alloc_count_ - free_count_ > max_alloc_count_)
                            max_alloc_count_ = alloc_count_- free_count_;
#endif
                        return p;
                    }

#if defined(HPX_DEBUG)
                    LOSH_(info) << hpx::util::format(
                        "{1}::alloc: failed to allocate from heap[{2}] "
                        "(heap[{2}] has allocated {3} objects and has "
                        "space for {4} more objects)",
                        name(),
                        heap->heap_count(),
                        heap->size(),
                        heap->free_size());
#endif
                }
            }
        }

        // Create new heap.
        bool did_create = false;
        {
#if defined(HPX_DEBUG)
            heap_list_.push_front(create_heap_(
                class_name_.c_str(), heap_count_ + 1, parameters_));
#else
            heap_list_.push_front(create_heap_(
                class_name_.c_str(), 0, parameters_));
#endif

            iterator itnew = heap_list_.begin();
            typename list_type::value_type heap = *itnew;
            bool result = false;

            {
                util::unlock_guard<unique_lock_type> ul(guard);
                result = heap->alloc((void**)&p, count);
            }

            if (HPX_UNLIKELY(!result || nullptr == p))
            {
                // out of memory
                guard.unlock();
                HPX_THROW_EXCEPTION(out_of_memory,
                    name() + "::alloc",
                    hpx::util::format(
                        "new heap failed to allocate {1} objects",
                        count));
            }

#if defined(HPX_DEBUG)
            alloc_count_ += count;
            ++heap_count_;

            LOSH_(info) << hpx::util::format(
                "{1}::alloc: creating new heap[{2}], size is now {3}",
                name(),
                heap_count_,
                heap_list_.size());
#endif
            did_create = true;
        }

        if (did_create)
            return p;

        guard.unlock();

        // Try again, we just got a new heap, so we should be good.
        return alloc(count);
    }
コード例 #24
0
ファイル: parcelport.cpp プロジェクト: Stevejohntest/hpx
    void parcelport::put_parcel(parcel const& p, write_handler_type f)
    {
        typedef pending_parcels_map::iterator iterator;
        naming::locality locality_id = p.get_destination_locality();

        parcelport_connection_ptr client_connection;

        // enqueue the incoming parcel ...
        {
            util::spinlock::scoped_lock l(mtx_);
            pending_parcels_[locality_id].first.push_back(p);
            pending_parcels_[locality_id].second.push_back(f);
        }

        // Get a connection or reserve space for a new connection. 
        if (!connection_cache_.get_or_reserve(locality_id, client_connection))
            return;

        // Check if we need to create the new connection.
        if (!client_connection)
        {
            client_connection.reset(new parcelport_connection(
                io_service_pool_.get_io_service(), locality_id,
                connection_cache_, timer_, parcels_sent_));

            // Connect to the target locality, retry if needed.
            boost::system::error_code error = boost::asio::error::try_again;
            for (int i = 0; i < HPX_MAX_NETWORK_RETRIES; ++i)
            {
                try {
                    naming::locality::iterator_type end = locality_id.connect_end();
                    for (naming::locality::iterator_type it =
                            locality_id.connect_begin(io_service_pool_.get_io_service());
                         it != end; ++it)
                    {
                        client_connection->socket().close();
                        client_connection->socket().connect(*it, error);
                        if (!error)
                            break;
                    }
                    if (!error)
                        break;

                    // we wait for a really short amount of time
                    // TODO: Should this be an hpx::threads::suspend?
                    boost::this_thread::sleep(boost::get_system_time() +
                        boost::posix_time::milliseconds(HPX_NETWORK_RETRIES_SLEEP));
                }
                catch (boost::system::error_code const& e) {
                    HPX_THROW_EXCEPTION(network_error,
                        "parcelport::send_parcel", e.message());
                }
            }

            if (error) {
                client_connection->socket().close();

                hpx::util::osstream strm;
                strm << error.message() << " (while trying to connect to: "
                     << locality_id << ")";
                HPX_THROW_EXCEPTION(network_error,
                    "parcelport::send_parcel",
                    hpx::util::osstream_get_string(strm));
            }
#if defined(HPX_DEBUG)
            else {
                std::string connection_addr = 
                    client_connection->socket().remote_endpoint().address().to_string();
                boost::uint16_t connection_port = 
                    client_connection->socket().remote_endpoint().port();
                BOOST_ASSERT(locality_id.get_address() == connection_addr);
                BOOST_ASSERT(locality_id.get_port() == connection_port);
            }
#endif
        }
#if defined(HPX_DEBUG)
        else {
            //LPT_(info) << "parcelport: reusing existing connection to: "
            //           << addr.locality_;
            BOOST_ASSERT(locality_id == client_connection->destination());

            std::string connection_addr = client_connection->socket().remote_endpoint().address().to_string();
            boost::uint16_t connection_port = client_connection->socket().remote_endpoint().port();
            BOOST_ASSERT(locality_id.get_address() == connection_addr);
            BOOST_ASSERT(locality_id.get_port() == connection_port);
        }
#endif

        std::vector<parcel> parcels;
        std::vector<write_handler_type> handlers;

        util::spinlock::scoped_lock l(mtx_);
        iterator it = pending_parcels_.find(locality_id);

        if (it != pending_parcels_.end())
        {
            BOOST_ASSERT(it->first == locality_id);
            std::swap(parcels, it->second.first);
            std::swap(handlers, it->second.second);
        }

        // If the parcels didn't get sent by another connection ...
        if (!parcels.empty() && !handlers.empty())
        {
            send_pending_parcels(client_connection, parcels, handlers);
        }
        else
        {
            // ... or re-add the stuff to the cache
            BOOST_ASSERT(locality_id == client_connection->destination());
            connection_cache_.reclaim(locality_id, client_connection);
        }
    }
コード例 #25
0
ファイル: component_base.cpp プロジェクト: K-ballo/hpx
    naming::gid_type base_component::get_base_gid_dynamic(
        naming::gid_type const& assign_gid, naming::address const& addr,
        naming::gid_type (*f)(naming::gid_type)) const
    {
        if (!gid_)
        {
            if (!assign_gid)
            {
                if (f != nullptr)
                {
                    gid_ = f(hpx::detail::get_next_id());
                }
                else
                {
                    gid_ = hpx::detail::get_next_id();
                }

                if (!applier::bind_gid_local(gid_, addr))
                {
                    std::ostringstream strm;
                    strm << "failed to bind id " << gid_
                            << "to locality: " << hpx::get_locality();

                    gid_ = naming::invalid_gid;    // invalidate GID

                    HPX_THROW_EXCEPTION(duplicate_component_address,
                        "component_base<Component>::get_base_gid",
                        strm.str());
                }
            }
            else
            {
                applier::applier& appl = hpx::applier::get_applier();
                gid_ = assign_gid;
                naming::detail::strip_credits_from_gid(gid_);

                if (!agas::bind(
                        launch::sync, gid_, addr, appl.get_locality_id()))
                {
                    std::ostringstream strm;
                    strm << "failed to rebind id " << gid_
                            << "to locality: " << hpx::get_locality();

                    gid_ = naming::invalid_gid;    // invalidate GID

                    HPX_THROW_EXCEPTION(duplicate_component_address,
                        "component_base<Component>::get_base_gid",
                        strm.str());
                }
            }
        }

        std::unique_lock<naming::gid_type::mutex_type> l(gid_.get_mutex());

        if (!naming::detail::has_credits(gid_))
        {
            naming::gid_type gid = gid_;
            return gid;
        }

        // on first invocation take all credits to avoid a self reference
        naming::gid_type gid = gid_;

        naming::detail::strip_credits_from_gid(
            const_cast<naming::gid_type&>(gid_));

        HPX_ASSERT(naming::detail::has_credits(gid));

        // We have to assume this credit was split as otherwise the gid
        // returned at this point will control the lifetime of the
        // component.
        naming::detail::set_credit_split_mask_for_gid(gid);
        return gid;
    }
コード例 #26
0
// remote call to AGAS
void register_worker(registration_header const& header)
{
    // This lock acquires the bbb mutex on creation. When it goes out of scope,
    // it's dtor calls big_boot_barrier::notify().
    big_boot_barrier::scoped_lock lock(get_big_boot_barrier());

    naming::resolver_client& agas_client = get_runtime().get_agas_client();

    if (HPX_UNLIKELY(agas_client.is_connecting()))
    {
        HPX_THROW_EXCEPTION(internal_server_error
            , "agas::register_worker"
            , "runtime_mode_connect can't find running application.");
    }

    if (HPX_UNLIKELY(!agas_client.is_bootstrap()))
    {
        HPX_THROW_EXCEPTION(internal_server_error
            , "agas::register_worker"
            , "registration parcel received by non-bootstrap locality.");
    }

    naming::gid_type prefix
                   , parcel_lower, parcel_upper
                   , heap_lower, heap_upper;

    agas_client.register_locality(header.locality, prefix);

    agas_client.get_id_range(header.locality, header.parcelport_allocation
                           , parcel_lower, parcel_upper);
    agas_client.get_id_range(header.locality, header.response_allocation
                           , heap_lower, heap_upper);

    naming::gid_type runtime_support_gid(prefix.get_msb()
                                       , header.component_runtime_support_ptr)
                   , memory_gid(prefix.get_msb()
                              , header.component_memory_ptr);

    naming::address runtime_support_address
        (header.locality,
         components::get_component_type<components::server::runtime_support>(),
         header.component_runtime_support_ptr);

    naming::address memory_address
        (header.locality,
         components::get_component_type<components::server::memory>(),
         header.component_memory_ptr);

    agas_client.bind(runtime_support_gid, runtime_support_address);
    agas_client.bind(memory_gid, memory_address);

    agas_client.bind_range(heap_lower, header.response_allocation
                         , header.response_heap_address
                         , header.response_heap_offset);

    naming::address primary_addr(get_runtime().here(),
        server::primary_namespace::get_component_type(),
            static_cast<void*>(&agas_client.bootstrap->primary_ns_server));
    naming::address component_addr(get_runtime().here(),
        server::component_namespace::get_component_type(),
            static_cast<void*>(&agas_client.bootstrap->component_ns_server));
    naming::address symbol_addr(get_runtime().here(),
        server::symbol_namespace::get_component_type(),
            static_cast<void*>(&agas_client.bootstrap->symbol_ns_server));

    actions::base_action* p =
        new actions::transfer_action<notify_console_action>(
            notification_header(
                prefix, header.response_heap_address, header.response_heap_ptr,
                heap_lower, heap_upper, parcel_lower, parcel_upper,
                primary_addr, component_addr, symbol_addr));

    // FIXME: This could screw with startup.

    // TODO: Handle cases where localities try to connect to AGAS while it's
    // shutting down.
    if (agas_client.status() != starting)
    {
        // We can just send the parcel now, the connecting locality isn't a part
        // of startup synchronization.
        get_big_boot_barrier().apply(naming::get_locality_id_from_gid(prefix)
                                   , naming::address(header.locality), p);
    }

    else // AGAS is starting up; this locality is participating in startup
    {    // synchronization.
        HPX_STD_FUNCTION<void()>* thunk = new HPX_STD_FUNCTION<void()>
            (boost::bind(&big_boot_barrier::apply
                       , boost::ref(get_big_boot_barrier())
                       , naming::get_locality_id_from_gid(prefix)
                       , naming::address(header.locality)
                       , p));

        get_big_boot_barrier().add_thunk(thunk);
    }
}