2011/06/30


javascript:for (var b=document.getElementsByTagName("*"), n = 0; n < b.length; n++) { if (b[n].getAttribute("g:type") == "plusone" && b[n].getAttribute("aria-pressed") != "true") b[n].click() }
Posted at by



2011/06/28


ダウンロード配布物となっている mingw の c++config.h では /* Define if gthreads library is available. */
/* #undef _GLIBCXX_HAS_GTHREADS */
となっていて、下記の様なthreadを使ったコードはコンパイル出来ないのですが #include <atomic>
#include <thread>
#include <iostream>

std::mutex m ;
int x ; 

void thread()
{
    std::lock_guard<std::mutex> guard(m) ;
    ++x ; // 非アトミック操作
}

int main()
{
    x = 0 ; // 初期値0

    std::thread A( thread ) ;
    std::thread B( thread ) ;

    A.join() ; B.join() ;

    std::cout << x << std::endl ; // 2であるべき
}
本の虫: C++0xのマルチスレッドとデータ競合が非常に難しい

「バリアー!」「デュクシ!」「ちょっ、お前、オレ、バリアー張...

http://cpplover.blogspot.com/2011/06/c0x.html
手を加えてやる事でビルド出来る事が分かった。まずはオプションを上書きしてやる。 #define _GLIBCXX_HAS_GTHREADS 1
#define _GLIBCXX__PTHREADS 1
#define _POSIX_TIMEOUTS 1
次に、gthreadsが内部処理の為に定義しているスレッド識別子による比較関数を定義する #include <pthread.h>
inline bool
operator<(const pthread_t& lhs, const pthread_t& rhs) { 
  return lhs < rhs;
}
この状態でとりあえずコンパイルは出来る。ただしgthreads無効でビルドされているのでスレッド操作関数の実体が無い。そこでthread.ccからコードを拝借する。 namespace std
{
  namespace
  {
    extern "C" void*
    execute_native_thread_routine(void* __p)
    {
      thread::_Impl_base* __t = static_cast<thread::_Impl_base*>(__p);
      thread::__shared_base_type __local;
      __local.swap(__t->_M_this_ptr);

      __try
        {
          __t->_M_run();
        }
      __catch(...)
        {
          std::terminate();
        }

      return 0;
    }
  }
  void
  thread::_M_start_thread(__shared_base_type __b)
  {
    if (!__gthread_active_p())
      __throw_system_error(int(errc::operation_not_permitted));

    __b->_M_this_ptr = __b;
    int __e = __gthread_create(&_M_id._M_thread,
                               &execute_native_thread_routine, __b.get());
    if (__e)
    {
      __b->_M_this_ptr.reset();
      __throw_system_error(__e);
    }
  }
  void
  thread::join()
  {
    int __e = EINVAL;

    if (_M_id != id())
      __e = __gthread_join(_M_id._M_thread, 0);

    if (__e)
      __throw_system_error(__e);

    _M_id = id();
  }
}
全体のソースだとこんな感じ。 // {{{
// vi:set ts=8 sts=2 sw=2 tw=0:
// vim:fdm=marker fdl=0 fdc=0 fdo+=jump,search:
// vim:fdt=substitute(getline(v\:foldstart),'\\(.\*\\){\\{3}','\\1',''):
#define _GLIBCXX_HAS_GTHREADS 1
#define _GLIBCXX__PTHREADS 1
#define _POSIX_TIMEOUTS 1
#include <pthread.h>
inline bool
operator<(const pthread_t& lhs, const pthread_t& rhs) { 
  return lhs < rhs;
}
// }}}

#include <atomic>
#include <thread>
#include <iostream>

// {{{
namespace std
{
  namespace
  {
    extern "C" void*
    execute_native_thread_routine(void* __p)
    {
      thread::_Impl_base* __t = static_cast<thread::_Impl_base*>(__p);
      thread::__shared_base_type __local;
      __local.swap(__t->_M_this_ptr);

      __try
        {
          __t->_M_run();
        }
      __catch(...)
        {
          std::terminate();
        }

      return 0;
    }
  }
  void
  thread::_M_start_thread(__shared_base_type __b)
  {
    if (!__gthread_active_p())
      __throw_system_error(int(errc::operation_not_permitted));

    __b->_M_this_ptr = __b;
    int __e = __gthread_create(&_M_id._M_thread,
                               &execute_native_thread_routine, __b.get());
    if (__e)
    {
      __b->_M_this_ptr.reset();
      __throw_system_error(__e);
    }
  }
  void
  thread::join()
  {
    int __e = EINVAL;

    if (_M_id != id())
      __e = __gthread_join(_M_id._M_thread, 0);

    if (__e)
      __throw_system_error(__e);

    _M_id = id();
  }
}
// }}}

std::mutex m ;
int x ; 

void thread()
{
    std::lock_guard<std::mutex> guard(m) ;
    ++x ; // 非アトミック操作
}

int main()
{
    x = 0 ; // 初期値0

    std::thread A( thread ) ;
    std::thread B( thread ) ;

    A.join() ; B.join() ;

    std::cout << x << std::endl ; // 2であるべき
}
これ、vimmerならfoldを使ってやれば //                                                                               

#include <atomic>
#include <thread>
#include <iostream>

//                                                                               

int main() {
  std::mutex m;
  int x = 0;

  std::thread A([&] {
    for (int n = 0; n < 100; n++)  {
      std::lock_guard<std::mutex> guard(m);
      ++x;
      std::cout << x << std::endl;
    }
  });
  std::thread B([&] {
    for (int n = 0; n < 100; n++)  {
      std::lock_guard<std::mutex> guard(m);
      ++x;
      std::cout << x << std::endl;
    }
  });

  A.join();
  B.join();
}

こんな風に見えてちょっとはマシになる。これでmingw使ってthreadなプログラミングが出来ますね!
lambda使えばこんなのも出来て、たのしーーーー!

#include <atomic>
#include <thread>
#include <iostream>

int main() {
  std::mutex m;
  int x = 0;

  std::thread A([&] {
    for (int n = 0; n < 100; n++)  {
      std::lock_guard<std::mutex> guard(m);
      ++x;
      std::cout << x << std::endl;
    }
  });
  std::thread B([&] {
    for (int n = 0; n < 100; n++)  {
      std::lock_guard<std::mutex> guard(m);
      ++x;
      std::cout << x << std::endl;
    }
  });

  A.join();
  B.join();
}

Posted at by



2011/06/24


Go言語フリークの皆さんこんばんわ。
テンポラリ的にキャプチャ画像をアップロードする際にはgyazoが一般的ですよね。僕もよく利用しています。
今日はこのgyazoに画像をアップロードするクライアントと、サーバを書きました。
mattn/gyago - GitHub

Gyazo application written in go

https://github.com/mattn/gyago
Gyago

Gyazo on AppEngine

http://gyazo.compile-error.net/
コマンドラインで動くクライアントと、GoogleAppEngineで動くサーバです。クライアントはキャプチャ動作はしませんが、引数で与えたpngファイルをgyazoサーバにアップロード出来ます。またサーバはdatastoreを使って画像データをblobに格納する事でgyazoサーバを実現しています。

タイトルページはGoogle WebFont APIを使ってなんなーくカッコいい感じにしてみました。ほんとになんとなーくです。
Google Web Fonts

Google Web Fonts lets you browse all the fonts available via theGoogle Web Fonts API. All fonts in t...

http://www.google.com/webfonts
GoogleAppEngineの無料枠なので、すぐMax Quotaになっちゃうかも知れませんが、良かったら遊んでみて下さい。
なお、クライアントはデフォルトではgyazo.comにアップロードしちゃうので # gyago -e=http://gyazo.compile-error.net/ imagefile.png
という感じにアップロード先のエンドポイントを指定してあげて下さい。 ちなみに、sendさんがsinatraで書いたgyazoサーバにアップロードしたい場合は # gyago -e=http://gyazo.send.sh/ imagefile.png
と指定すれば動きますが、現状のGoはmultipartの処理で、先頭に空白行が1行入る動作になっていて、rack-1.2と相性が悪い(先頭に空白行があるとマッチしない)ので、golang-devにパッチを投げてあります。
と書いた所で再度見たら、もうsubmitされてましたので、hg pullしてtipsにすると入ってます。

ちなみに、rack-1.3では先頭に空白行が入っていても正しく読める様な修正が入っている模様です。

Posted at by