void test_timed_executor(std::array<std::size_t, 4> expected)
{
    typedef typename hpx::traits::executor_execution_category<
            Executor
        >::type execution_category;

    HPX_TEST((std::is_same<
            hpx::parallel::execution::sequenced_execution_tag,
            execution_category
        >::value));

    count_sync.store(0);
    count_apply.store(0);
    count_sync_at.store(0);
    count_apply_at.store(0);

    Executor exec;

    test_timed_apply(exec);
    test_timed_sync(exec);
    test_timed_async(exec);

    HPX_TEST_EQ(expected[0], count_sync.load());
    HPX_TEST_EQ(expected[1], count_apply.load());
    HPX_TEST_EQ(expected[2], count_sync_at.load());
    HPX_TEST_EQ(expected[3], count_apply_at.load());
}
Beispiel #2
0
/**
 * The environment should be initialised exactly once during shared library initialisation.
 * Prior to that, all operations work in pass-through mode.
 * To overcome undefined global initialisation order, we use a local static variable.
 * This variable is accesd by a single writer (lib (de)initialisation), and multiple readers (exported operations).
 * Writer: toggle == true (toggles is_initialised)
 * Reader: toggle == false (returns the current value of is_initialised)
 *
 * NOTE: pthread_once initialisation for the overlay leads to a deadlock due to a re-entry situation:
 * - environment ctor is called the first time via pthread_once
 * - which leads a write somewhere (probably to a socket during client initialisation)
 * - which then enters the pthread_once initialisation mechanism again and blocks deadlocks
 */
bool overlay_initialized(bool toggle /* defaults to: false */) {
  static boost::atomic<bool> is_initilized(false);

  // writer
  if(toggle) {
    return is_initilized.exchange(!is_initilized.load());
  }

  // reader
  return is_initilized.load();
}
Beispiel #3
0
    scheduled_executor default_executor()
    {
        if (!default_executor_instance.load())
        {
            scheduled_executor& default_exec =
                scheduled_executor::default_executor();
            scheduled_executor empty_exec;

            default_executor_instance.compare_exchange_strong(
                empty_exec, default_exec);
        }
        return default_executor_instance.load();
    }
void calc_block(
    hpxla::local_matrix_view<boost::int64_t>& H 
  , hpxla::local_matrix_view<hpx::future<void> >& C // Control matrix.
  , coords start   // The start of our cell block. 
  , coords end     // The end of our cell block.
  , coords control // Our location in the control matrix.
  , std::string const& a
  , std::string const& b
    )
{
    // TODO: Handle this with hpx::wait_all?
    C(control.i,   control.j-1).get(); 
    C(control.i-1, control.j-1).get(); 
    C(control.i-1, control.j  ).get(); 

    winner local_best = H_best.load();

    // Generate scores.
    for (boost::uint32_t i = start.i; i < end.i; ++i)
    {
        for (boost::uint32_t j = start.j; j < end.j; ++j)
        {
            H(i, j) = calc_cell(i, j, a[i-1], b[j-1]
              , H(i,   j-1) // left
              , H(i-1, j-1) // diagonal 
              , H(i-1, j  ) // up
            ); 

            if (H(i, j) > local_best.value)
            {
                local_best.value = H(i, j);
                local_best.i = i;
                local_best.j = j;
            } 
        }
    }

    winner H_best_old = H_best.load(); 

    while (true)
    {
        if (local_best.value > H_best_old.value)
        {
            if (H_best.compare_exchange_weak(H_best_old, local_best))
                break;
        }
        else
            break;
    }
}
int hpx_main(int argc, char** argv_init)
{
    hpx::new_<test_server>(hpx::find_here(), moveonly()).get();
    HPX_TEST_EQ(constructed_from_moveonly.load(), 1);

    moveable o;
    hpx::new_<test_server>(hpx::find_here(), o).get();
    HPX_TEST_EQ(constructed_from_moveable.load(), 1);

    hpx::new_<test_server>(hpx::find_here(), moveable()).get();
    HPX_TEST_EQ(constructed_from_moveable.load(), 2);

    return hpx::finalize();
}
void increment(hpx::id_type const& there, boost::int32_t i)
{
    locality_id = hpx::get_locality_id();

    accumulator += i;
    hpx::apply(receive_result_action(), there, accumulator.load());
}
Beispiel #7
0
 inline T get_and_reset_value(boost::atomic<T>& value, bool reset)
 {
     T result = value.load();
     if (reset)
         value.store(0);
     return result;
 }
Beispiel #8
0
 bool try_recursive_lock(thread_id_type current_thread_id)
 {
     if (locking_thread_id.load(boost::memory_order_acquire) ==
         current_thread_id)
     {
         util::register_lock(this);
         ++recursion_count;
         return true;
     }
     return false;
 }
    void call_void()
    {
        ++count_call_void;

        // make sure this function is not concurrently invoked
        HPX_TEST_EQ(count_active_call_void.fetch_add(1) + 1, 1);

        hpx::this_thread::suspend(boost::chrono::microseconds(100));

        --count_active_call_void;
        HPX_TEST_EQ(count_active_call_void.load(), 0);
    }
Beispiel #10
0
int main()
{
    {
        hpx::threads::executors::local_priority_queue_executor exec(4);
        for (int i = 0; i != 100; ++i)
            hpx::async(exec, &doit);
    }

    HPX_TEST_EQ(counter.load(), 100);

    return hpx::util::report_errors();
}
Beispiel #11
0
 inline bool interlocked_bit_test_and_set(boost::atomic<T>& x, long bit)
 {
     T const value = 1u << bit;
     boost::uint32_t old = x.load(boost::memory_order_acquire);
     do {
         boost::uint32_t tmp = old;
         if (x.compare_exchange_strong(tmp, T(old | value)))
             break;
         old = tmp;
     } while(true);
     return (old & value) != 0;
 }
Beispiel #12
0
void test_remote_async_cb(hpx::id_type const& target)
{
    typedef hpx::components::client<decrement_server> decrement_client;

    {
        decrement_client dec_f =
            hpx::components::new_<decrement_client>(target);

        call_action call;

        callback_called.store(0);
        hpx::future<std::int32_t> f1 = hpx::async_cb(call, dec_f, &cb, 42);
        HPX_TEST_EQ(f1.get(), 41);
        HPX_TEST_EQ(callback_called.load(), 1);

        callback_called.store(0);
        hpx::future<std::int32_t> f2 =
            hpx::async_cb(hpx::launch::all, call, dec_f, &cb, 42);
        HPX_TEST_EQ(f2.get(), 41);
        HPX_TEST_EQ(callback_called.load(), 1);
    }

    {
        decrement_client dec_f =
            hpx::components::new_<decrement_client>(target);
        hpx::id_type dec = dec_f.get_id();

        callback_called.store(0);
        hpx::future<std::int32_t> f1 =
            hpx::async_cb<call_action>(dec_f, &cb, 42);
        HPX_TEST_EQ(f1.get(), 41);
        HPX_TEST_EQ(callback_called.load(), 1);

        callback_called.store(0);
        hpx::future<std::int32_t> f2 =
            hpx::async_cb<call_action>(hpx::launch::all, dec_f, &cb, 42);
        HPX_TEST_EQ(f2.get(), 41);
        HPX_TEST_EQ(callback_called.load(), 1);
    }
}
Beispiel #13
0
TORRENT_NO_RETURN TORRENT_EXPORT void assert_fail(char const* expr, int line
	, char const* file, char const* function, char const* value, int kind)
{
#ifdef TORRENT_PRODUCTION_ASSERTS
	// no need to flood the assert log with infinite number of asserts
	if (assert_counter.fetch_add(1) + 1 > 500) return;
#endif

	char stack[8192];
	stack[0] = '\0';
	print_backtrace(stack, sizeof(stack), 0);

	char const* message = "assertion failed. Please file a bugreport at "
		"http://code.google.com/p/libtorrent/issues\n"
		"Please include the following information:\n\n"
		"version: " LIBTORRENT_VERSION "\n"
		LIBTORRENT_REVISION "\n";

	switch (kind)
	{
		case 1:
			message = "A precondition of a libtorrent function has been violated.\n"
				"This indicates a bug in the client application using libtorrent\n";
	}
	  
	assert_print("%s\n"
#ifdef TORRENT_PRODUCTION_ASSERTS
		"#: %d\n"
#endif
		"file: '%s'\n"
		"line: %d\n"
		"function: %s\n"
		"expression: %s\n"
		"%s%s\n"
		"stack:\n"
		"%s\n"
		, message
#ifdef TORRENT_PRODUCTION_ASSERTS
		, assert_counter.load()
#endif
		, file, line, function, expr
		, value ? value : "", value ? "\n" : ""
		, stack);

	// if production asserts are defined, don't abort, just print the error
#ifndef TORRENT_PRODUCTION_ASSERTS
 	// send SIGINT to the current process
 	// to break into the debugger
 	raise(SIGINT);
 	abort();
#endif
}
void random_outlets(double spawn_every=0.0, double duration=0.0, string name=string(), string type=string(), int numchan=0, lsl::channel_format_t fmt=lsl::cf_undefined, double srate=0.0, double seconds_between_failures=0.0, int chunk_len=0) {
	if (spawn_every == 0.0)
		spawn_every = spawn_outlet_interval;
	while(true) {
        try {
			if (num_outlets.load() < max_inlets)
				boost::thread tmp(&run_outlet,duration,name,type,numchan,fmt,srate,seconds_between_failures,chunk_len);
		} catch(std::exception &e) {
			std::cerr << "Could not spawn a new outlet thread: " << e.what() << std::endl;
        }		
		boost::this_thread::sleep(boost::posix_time::millisec((boost::int64_t)(1000*spawn_every)));
	}
}
void random_inlets(double spawn_every=0.0, double duration=0.0, string name=string(), string type=string(), int in_chunks=-1, int request_info=-1, int request_time=-1, double seconds_between_failures=0.0) {
	if (spawn_every == 0.0)
		spawn_every = spawn_inlet_interval;
	while(true) {
        try {
			if (num_inlets.load() < max_outlets)
				boost::thread tmp(&run_inlet,duration,name,type,in_chunks,request_info,request_time,seconds_between_failures);
		} catch(std::exception &e) {
			std::cerr << "Could not spawn a new inlet thread: " << e.what() << std::endl;
        }		
		boost::this_thread::sleep(boost::posix_time::millisec((boost::int64_t)(1000*spawn_every)));
	}
}
static void streamWriterThread() {
    try {
        while (true) {
            boost::this_thread::sleep_for(boost::chrono::seconds(2));
            
            int lastStatus = 200;
            auto lastRowIndex = writeRowIndex.load();
            
            while (readRowIndex < lastRowIndex) {
                for (auto i = readRowIndex; i < lastRowIndex; ++i) {
                    auto& row = logRows[i % maxLogRows];

                    if (row.status != lastStatus) {
                        if (row.status >= 500) {
                            std::cout << termcolor::red;
                        } else if (row.status >= 400) {
                            std::cout << termcolor::grey << termcolor::bold;
                        } else if (row.status >= 300) {
                            std::cout << termcolor::yellow;
                        } else {
                            std::cout << termcolor::reset;
                        }

                        lastStatus = row.status;
                    }

                    std::cout << row.data << "\n";
                }

                readRowIndex = lastRowIndex;
                lastRowIndex = writeRowIndex.load();
            }                        
            
            std::cout << termcolor::reset << std::flush;                        
        }
    } catch (boost::thread_interrupted&) {
    }
}
hpx::future<void> plain_future_void()
{
    ++count_plain_future_void;

    // make sure this function is not concurrently invoked
    HPX_TEST_EQ(count_active_plain_future_void.fetch_add(1) + 1, 1);

    hpx::this_thread::suspend(boost::chrono::microseconds(100));

    --count_active_plain_future_void;
    HPX_TEST_EQ(count_active_plain_future_void.load(), 0);

    return hpx::make_ready_future();
}
    //! 再生用データの準備と
    //! WAVEHDRの入れ替えを延々と行うワーカースレッド
	void ProcessThread()
	{
		{
			boost::unique_lock<boost::mutex> lock(initial_lock_mutex_);
		}
		for( ; ; ) {
			if(terminated_.load()) { break; }

            //! 使用済みWAVEHDRの確認
			for(auto &header: headers_ | boost::adaptors::indirected) {
				DWORD_PTR status = NULL;

				EnterCriticalSection(&cs_);
				status = header.get()->dwUser;
				LeaveCriticalSection(&cs_);

                //! 使用済みWAVEHDRはUnprepareして、未使用フラグを立てる。
				if(status == WaveHeader::DONE) {
					waveOutUnprepareHeader(hwo_, header.get(), sizeof(WAVEHDR));
					header.get()->dwUser = WaveHeader::UNUSED;
				}
			}

            //! 未使用WAVEHDRを確認
			for(auto &header: headers_ | boost::adaptors::indirected) {
				DWORD_PTR status = NULL;

				EnterCriticalSection(&cs_);
				status = header.get()->dwUser;
				LeaveCriticalSection(&cs_);

				if(status == WaveHeader::UNUSED) {
                    //! 再生用データを準備
					PrepareData(header.get());
					header.get()->dwUser = WaveHeader::USING;
                    //! waveOutPrepareHeaderを呼び出す前に、dwFlagsは必ず0にする。
					header.get()->dwFlags = 0;

                    //! WAVEHDRをPrepare
					waveOutPrepareHeader(hwo_, header.get(), sizeof(WAVEHDR));
                    //! デバイスへ書き出し(されるように登録)
					waveOutWrite(hwo_, header.get(), sizeof(WAVEHDR));
				}
			}

			Sleep(1);
		}
	}
Beispiel #19
0
    void get_items(void)
    {
        for (;;)
        {
            long id;

            bool got = stk.pop(id);
            if (got)
            {
                bool erased = data.erase(id);
                assert(erased);
                ++pop_count;
            }
            else
                if (not running.load())
                    return;
        }
    }
Beispiel #20
0
	void push_back(T elem) {
		// Construct an element to hold it
		synclist_item<T>* itm = new synclist_item<T>();
		itm->value = elem;
		itm->prev.store(m_last.load(boost::memory_order_release), boost::memory_order_acquire);
		itm->next.store(NULL, boost::memory_order_acquire);

		// Insert the element in the list
		synclist_item<T>* tmpItm = itm;
		synclist_item<T>* prevLast = m_last.exchange(tmpItm, boost::memory_order_consume);
		tmpItm = itm;
		synclist_item<T>* null = NULL;
		m_first.compare_exchange_strong(null, tmpItm, boost::memory_order_consume, boost::memory_order_acquire);
		if(prevLast != NULL) {
			prevLast->next.store(itm, boost::memory_order_consume);
		}
		m_length.fetch_add(1, boost::memory_order_consume);
	}
void ProducerWorker(RocketmqSendAndConsumerArgs *info,
                    DefaultMQProducer *producer) {
  while (!g_quit.load()) {
    if (g_msgCount.load() <= 0) {
      std::unique_lock<std::mutex> lck(g_mtx);
      g_finished.notify_one();
    }
    MQMessage msg(info->topic,  // topic
                  "*",          // tag
                  info->body);  // body

    int orderId = 1;
    SendResult sendResult =
        producer->send(msg, &g_mySelector, static_cast<void *>(&orderId),
                       info->retrytimes, info->SelectUnactiveBroker);
    --g_msgCount;
  }
}
boost::int64_t calc_cell(
    boost::uint32_t i
  , boost::uint32_t j
  , char ai
  , char bj
  , hpx::future<boost::int64_t> const& left      // H(i, j-1)
  , hpx::future<boost::int64_t> const& diagonal  // H(i-1, j-1)
  , hpx::future<boost::int64_t> const& up        // H(i-1, j) 
    )
{
    boost::int64_t match_mismatch = 0;
    if (ai == bj)
    {
        match_mismatch = diagonal.get() + match;
    } 
    else 
    {
        match_mismatch = diagonal.get() + mismatch;
    }
    boost::int64_t deletion = up.get() + gap;
    boost::int64_t insertion = left.get() + gap;        
    
    boost::int64_t ij_value
        = maximum(boost::int64_t(0), match_mismatch, deletion, insertion);

    winner H_best_old = H_best.load(); 

    while (true)
    {
        winner H_best_new(ij_value, i, j);

        if (H_best_new.value > H_best_old.value)
        {
            if (H_best.compare_exchange_weak(H_best_old, H_best_new))
                break;
        }
        else
            break;
    }

    return ij_value;
}
Beispiel #23
0
int main()
{
    hpx::future<hpx::future<void> > fut =
        hpx::async(
            []() -> hpx::future<void> {
                return hpx::async(
                    []() -> void {
                        do_more_work();
                    });
            });

    hpx::util::high_resolution_timer t;

    hpx::future<void> fut2 = std::move(fut);
    fut2.get();

    HPX_TEST(t.elapsed() > 1.0);
    HPX_TEST(was_run.load());

    return hpx::util::report_errors();
}
Beispiel #24
0
 void call(hpx::id_type const& there, boost::int32_t i) const
 {
     accumulator += i;
     hpx::apply(receive_result_action(), there, accumulator.load());
 }
Beispiel #25
0
void test_remote_async_cb_colocated(test_client const& target)
{
    {
        increment_action inc;

        callback_called.store(0);
        hpx::future<boost::int32_t> f1 =
            hpx::async_cb(inc, hpx::colocated(target), &cb, 42);
        HPX_TEST_EQ(f1.get(), 43);
        HPX_TEST_EQ(callback_called.load(), 1);

        callback_called.store(0);
        hpx::future<boost::int32_t> f2 =
            hpx::async_cb(hpx::launch::all, inc, hpx::colocated(target), &cb, 42);
        HPX_TEST_EQ(f2.get(), 43);
        HPX_TEST_EQ(callback_called.load(), 1);
    }

    {
        increment_with_future_action inc;

        hpx::promise<boost::int32_t> p;
        hpx::shared_future<boost::int32_t> f = p.get_future();

        callback_called.store(0);
        hpx::future<boost::int32_t> f1 =
            hpx::async_cb(inc, hpx::colocated(target), &cb, f);
        hpx::future<boost::int32_t> f2 =
            hpx::async_cb(hpx::launch::all, inc, hpx::colocated(target), &cb, f);

        p.set_value(42);
        HPX_TEST_EQ(f1.get(), 43);
        HPX_TEST_EQ(f2.get(), 43);
        HPX_TEST_EQ(callback_called.load(), 2);
    }

    {
        callback_called.store(0);
        hpx::future<boost::int32_t> f1 =
            hpx::async_cb<increment_action>(hpx::colocated(target), &cb, 42);
        HPX_TEST_EQ(f1.get(), 43);
        HPX_TEST_EQ(callback_called.load(), 1);

        callback_called.store(0);
        hpx::future<boost::int32_t> f2 = hpx::async_cb<increment_action>(
            hpx::launch::all, hpx::colocated(target), &cb, 42);
        HPX_TEST_EQ(f2.get(), 43);
        HPX_TEST_EQ(callback_called.load(), 1);
    }

    {
        hpx::future<hpx::id_type> dec_f =
            hpx::components::new_<decrement_server>(hpx::colocated(target));
        hpx::id_type dec = dec_f.get();

        call_action call;

        callback_called.store(0);
        hpx::future<boost::int32_t> f1 = hpx::async_cb(call, dec, &cb, 42);
        HPX_TEST_EQ(f1.get(), 41);
        HPX_TEST_EQ(callback_called.load(), 1);

        callback_called.store(0);
        hpx::future<boost::int32_t> f2 =
            hpx::async_cb(hpx::launch::all, call, dec, &cb, 42);
        HPX_TEST_EQ(f2.get(), 41);
        HPX_TEST_EQ(callback_called.load(), 1);
    }

    {
        hpx::future<hpx::id_type> dec_f =
            hpx::components::new_<decrement_server>(hpx::colocated(target));
        hpx::id_type dec = dec_f.get();

        callback_called.store(0);
        hpx::future<boost::int32_t> f1 =
            hpx::async_cb<call_action>(dec, &cb, 42);
        HPX_TEST_EQ(f1.get(), 41);
        HPX_TEST_EQ(callback_called.load(), 1);

        callback_called.store(0);
        hpx::future<boost::int32_t> f2 =
            hpx::async_cb<call_action>(hpx::launch::all, dec, &cb, 42);
        HPX_TEST_EQ(f2.get(), 41);
        HPX_TEST_EQ(callback_called.load(), 1);
    }

    {
        increment_with_future_action inc;
        hpx::shared_future<boost::int32_t> f =
            hpx::async(hpx::launch::deferred, hpx::util::bind(&increment, 42));

        callback_called.store(0);
        hpx::future<boost::int32_t> f1 = hpx::async_cb(
            inc, hpx::colocated(target), &cb, f);
        hpx::future<boost::int32_t> f2 = hpx::async_cb(
            hpx::launch::all, inc, hpx::colocated(target), &cb, f);

        HPX_TEST_EQ(f1.get(), 44);
        HPX_TEST_EQ(f2.get(), 44);
        HPX_TEST_EQ(callback_called.load(), 2);
    }
}
Beispiel #26
0
void increment_with_future(hpx::id_type const& there,
    hpx::shared_future<boost::int32_t> fi)
{
    accumulator += fi.get();
    hpx::apply(receive_result_action(), there, accumulator.load());
}
alignment smith_waterman(
    std::string const& a
  , std::string const& b
  , boost::uint32_t grain_size
    )
{
    // Make sure that a and b have the same size (e.g. m == n), for now.
    BOOST_ASSERT(a.size() == b.size());

    if (a.size() % grain_size)
        throw std::invalid_argument(boost::str(boost::format(
            "grain size of %1% is invalid for a sequence of length %2%")
            % grain_size % a.size()));

    // j is the length of our input sequences plus one. This is number of
    // rows and columns in our square matrix. The extra, zero-filled row is
    // needed because the algorithm backtracks until it reaches a zero number.
    boost::uint32_t k = a.size() + 1; 

    // Create our matrix and fill it with zeros.
    alignment result;

    // k * k matrix
    result.H = hpxla::local_matrix<boost::int64_t>(k, k, 0); 

    // Declare a matrix view (e.g. an "alias") called H which refers to
    // result.H.
    hpxla::local_matrix_view<boost::int64_t> H = result.H.view();

    // Control matrix, for synchronizing the blocked, parallel operations.
    boost::uint32_t g = (grain_size % a.size()) + 1;
    hpxla::local_matrix<hpx::future<void> > control_matrix(g, g); 

    hpxla::local_matrix_view<hpx::future<void> > C = control_matrix.view();

    for (boost::uint32_t x = 0; x < g; ++x)
    {
        C(0, x) = hpx::lcos::create_void();
        C(x, 0) = hpx::lcos::create_void();
    }

    ///////////////////////////////////////////////////////////////////////////
    // Generate scoring matrix.

    for (boost::uint32_t i = 1; i < g; ++i)
    {
        for (boost::uint32_t j = 1; j < g; ++j)
        {
            boost::uint32_t const step = a.size() / grain_size;

            coords const start( ((i-1)*step)+1, ((j-1)*step)+1 ); 
            coords const end(   ((i)*step)+1,   ((j)*step)+1   ); 

            coords const control(i, j);

            C(i, j) = hpx::async(&calc_block, H, C, start, end, control, a, b);
        } 
    }  

    for (boost::uint32_t i = 1; i < g; ++i)
        for (boost::uint32_t j = 1; j < g; ++j)
            C(i, j).get(); 

    ///////////////////////////////////////////////////////////////////////////
    // Backtracking.

    // 0.) Make a vector to hold coords.
    // 1.) We want to start at H_best, or the coordinate of H_best, so
    //     (i_max, j_max).
    // 2.) Then, determine which value is largest (where i is initially i_max,
    //     and j is initially j_max):
    //        (i-1, j-1) for match/mismatch,
    //        (i-1, j)   for an insertion, and
    //        (i, j-1)   for a deletion. 
    // 3.) Reset the current i and j coords to equal next i and j coords. 
   
    winner H_max = H_best.load();
 
    std::vector<coords>& backpath = result.backpath;
    backpath.push_back(coords(H_max.i, H_max.j)); 

    while (true)
    {
        coords last = backpath.back();
        boost::int64_t match_mismatch = H(last.i-1, last.j-1); 
        boost::int64_t insertion = H(last.i, last.j-1);
        boost::int64_t deletion = H(last.i-1, last.j);
    
        boost::int64_t m = maximum(match_mismatch, insertion, deletion);    
    
        if (m == 0)
            break; 

        if (m == match_mismatch)
        {
            backpath.push_back(coords(last.i-1, last.j-1));
        }
        else if (m == insertion)
        {
            backpath.push_back(coords(last.i, last.j-1));
        }
        else // deletion
        {
            backpath.push_back(coords(last.i-1, last.j));
        } 
    }    

    return result;
}
void swap( boost::atomic<T>& lhs, boost::atomic<T>& rhs )
{
    lhs.store(rhs.exchange(lhs.load()));
}
std::size_t get_serial_execution_count()
{
    return serial_execution_count.load();
}
int hpx_main(boost::program_options::variables_map& vm)
{
    // extract command line argument, i.e. fib(N)
    boost::uint64_t n = vm["n-value"].as<boost::uint64_t>();
    std::string test = vm["test"].as<std::string>();
    boost::uint64_t max_runs = vm["n-runs"].as<boost::uint64_t>();

    if (max_runs == 0) {
        std::cerr << "fibonacci_futures_distributed: wrong command "
            "line argument value for "
            "option 'n-runs', should not be zero" << std::endl;
        return hpx::finalize(); // Handles HPX shutdown
    }

    bool executed_one = false;
    boost::uint64_t r = 0;

    if (test == "all" || test == "0")
    {
        // Keep track of the time required to execute.
        boost::uint64_t start = hpx::util::high_resolution_clock::now();

        // Synchronous execution, use as reference only.
        r = fibonacci_serial(n);

//        double d = double(hpx::util::high_resolution_clock::now() - start) / 1.e9;
        boost::uint64_t d = hpx::util::high_resolution_clock::now() - start;
        char const* fmt = "fibonacci_serial(%1%) == %2%,"
            "elapsed time:,%3%,[s]\n";
        std::cout << (boost::format(fmt) % n % r % d);

        executed_one = true;
    }

    if (test == "all" || test == "1")
    {
        // Keep track of the time required to execute.
        boost::uint64_t start = hpx::util::high_resolution_clock::now();

        for (std::size_t i = 0; i != max_runs; ++i)
        {
            // Create a Future for the whole calculation and wait for it.
            next_locality.store(0);
            r = fibonacci_future(n).get();
        }

//        double d = double(hpx::util::high_resolution_clock::now() - start) / 1.e9;
        boost::uint64_t d = hpx::util::high_resolution_clock::now() - start;
        char const* fmt = "fibonacci_future(%1%) == %2%,elapsed time:,%3%,[s],%4%\n";
        std::cout << (boost::format(fmt) % n % r % (d / max_runs)
            % next_locality.load());

        get_serial_execution_count_action serial_count;
        for (hpx::id_type const& loc : hpx::find_all_localities())
        {
            std::size_t count = serial_count(loc);
            std::cout << (boost::format("  serial-count,%1%,%2%\n") %
                loc % (count / max_runs));
        }

        executed_one = true;
    }

    if (!executed_one)
    {
        std::cerr << "fibonacci_futures_distributed: wrong command line argument "
            "value for option 'tests', should be either 'all' or a number between "
            "zero and 1, value specified: " << test << std::endl;
    }

    return hpx::finalize(); // Handles HPX shutdown
}