話題のSleep sortのGo言語版(Big Sky :: Sleep sort in Go)を見かけたので、Visual C++ 2010のAsynchronous Agents Libraryで書き直してみました。「完全に一致」感をお楽しみください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <agents.h>
 
int main(int argc, char **argv)
{
  using namespace Concurrency;
  using Concurrency::receive;
 
  auto args = boost::make_iterator_range(&argv[1], &argv[argc]);
 
  unbounded_buffer<std::int64_t> done;
  BOOST_FOREACH(auto arg, args) {
    auto i = boost::lexical_cast<std::int64_t>(arg);
    //go(std::bind([&](std::int64_t i) {
    //  Sleep(i * 1000);
    //  asend(done, i);
    //}, i));*
 
    go([&, i]() {
      Sleep(i * 1000);
      asend(done, i);
    });
  }
 
  BOOST_FOREACH(auto arg, args) {
    std::cout << receive(done) << std::endl;
  };
}

上のコード内、go関数(後述)の呼出はコメントアウトしたものとそうでないもの2つ書いてあります。コメントアウトしているほうがGo言語版の元のコードに忠実なのですが、VC++ 2010のbindはラムダ式に対して使うとエラーになるので、もう1つの書き方(ラムダ式でのキャプチャ)を用意しました。

前回、threadクラスをnewしたまま放置していたことを反省し、今回はスレッドプールで実行するようにしました。それが今回作ったgo関数です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef std::function<void ()> thread_func;
 
DWORD CALLBACK goRunner(void* p)
{
  std::unique_ptr<thread_func> pf(static_cast<thread_func*>(p));
  (*pf)();
  return 0;
}
 
void go(thread_func f)
{
  std::unique_ptr<thread_func> pf(new thread_func(std::move(f)));
  if (QueueUserWorkItem(goRunner, pf.get(), WT_EXECUTEDEFAULT))
  {
    pf.release();
  }
}

完全なソースコードはこちらからどうぞ: sleep_sort_ag.cpp

スポンサード リンク

この記事のカテゴリ

  • ⇒ Sleep sortをVC++ 2010のAsynchronous Agents Libraryで