<commit_before>#include "util/sync_etcd.h"

#include <condition_variable>
#include <event2/event.h>
#include <memory>

#include "base/notification.h"
#include "util/libevent_wrapper.h"
#include "util/status.h"

using std::bind;
using std::condition_variable;
using std::pair;
using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;
using std::shared_ptr;
using std::string;
using std::vector;
using util::Status;

namespace cert_trans {

namespace {


struct DoneFunctor1 {
  typedef void result_type;
  template <class P1>
  void operator()(Notification* done, P1* p1_out, const P1& p1_in) const {
    *p1_out = p1_in;
    done->Notify();
  }
};


struct DoneFunctor2 {
  typedef void result_type;
  template <class P1, class P2>
  void operator()(Notification* done, P1* p1_out, P2* p2_out, const P1& p1_in,
                  const P2& p2_in) const {
    *p1_out = p1_in;
    *p2_out = p2_in;
    done->Notify();
  }
};


struct DoneFunctor3 {
  typedef void result_type;
  template <class P1, class P2, class P3>
  void operator()(Notification* done, P1* p1_out, P2* p2_out, P3* p3_out,
                  const P1& p1_in, const P2& p2_in, const P3& p3_in) const {
    *p1_out = p1_in;
    *p2_out = p2_in;
    *p3_out = p3_in;
    done->Notify();
  }
};


template <class F>
Status BlockingCall(F async_method) {
  Notification done;
  Status status;
  async_method(bind(DoneFunctor1(), &done, &status, _1));
  done.WaitForNotification();
  return status;
}


template <class F, class P1>
Status BlockingCall(F async_method, P1* p1) {
  Notification done;
  Status status;
  async_method(bind(DoneFunctor2(), &done, &status, p1, _1, _2));
  done.WaitForNotification();
  return status;
}


template <class F, class P1, class P2>
Status BlockingCall(F async_method, P1* p1, P2* p2) {
  Notification done;
  Status status;
  async_method(bind(DoneFunctor3(), &done, &status, p1, p2, _1, _2, _3));
  done.WaitForNotification();
  return status;
}


}  // namespace


SyncEtcdClient::SyncEtcdClient(EtcdClient* client) : client_(client) {
}


Status SyncEtcdClient::Get(const string& key, EtcdClient::Node* node) const {
  return BlockingCall(bind(&EtcdClient::Get, client_, key, _1), node);
}
<commit_msg>Fix spurious hang on notify.<commit_after>#include "util/sync_etcd.h"

#include <condition_variable>
#include <event2/event.h>
#include <memory>

#include "base/notification.h"
#include "util/libevent_wrapper.h"
#include "util/status.h"

using std::bind;
using std::condition_variable;
using std::pair;
using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;
using std::shared_ptr;
using std::string;
using std::vector;
using util::Status;

namespace cert_trans {

namespace {


struct DoneFunctor1 {
  typedef void result_type;
  template <class P1>
  void operator()(Notification* done, P1* p1_out, const P1& p1_in) const {
    *p1_out = p1_in;
    done->Notify();
  }
};


struct DoneFunctor2 {
  typedef void result_type;
  template <class P1, class P2>
  void operator()(Notification* done, P1* p1_out, P2* p2_out, const P1& p1_in,
                  const P2& p2_in) const {
    *p1_out = p1_in;
    *p2_out = p2_in;
    done->Notify();
  }
};


struct DoneFunctor3 {
  typedef void result_type;
  template <class P1, class P2, class P3>
  void operator()(Notification* done, P1* p1_out, P2* p2_out, P3* p3_out,
                  const P1& p1_in, const P2& p2_in, const P3& p3_in) const {
    *p1_out = p1_in;
    *p2_out = p2_in;
    *p3_out = p3_in;
    done->Notify();
  }
};


template <class F>
Status BlockingCall(const F& async_method) {
  Notification done;
  Status status;
  DoneFunctor1 functor;
  async_method(bind(functor, &done, &status, _1));
  done.WaitForNotification();
  return status;
}


template <class F, class P1>
Status BlockingCall(const F& async_method, P1* p1) {
  Notification done;
  Status status;
  DoneFunctor2 functor;
  async_method(bind(functor, &done, &status, p1, _1, _2));
  done.WaitForNotification();
  return status;
}


template <class F, class P1, class P2>
Status BlockingCall(const F& async_method, P1* p1, P2* p2) {
  Notification done;
  Status status;
  DoneFunctor3 functor;
  async_method(bind(functor, &done, &status, p1, p2, _1, _2, _3));
  done.WaitForNotification();
  return status;
}


}  // namespace


SyncEtcdClient::SyncEtcdClient(EtcdClient* client) : client_(client) {
}


Status SyncEtcdClient::Get(const string& key, EtcdClient::Node* node) const {
  return BlockingCall(bind(&EtcdClient::Get, client_, key, _1), node);
}

{'fraction_non_alphanumeric': 0.1305110769905681, 'fraction_numerical': 0.0311471813994297, 'mean_word_length': 4.38370720188902, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4400750', 'n_tokens_mistral': 1746, 'n_tokens_neox': 1700, 'n_words': 433}