private void sendPendingHaves() {
    if (destroyed) {

      return;
    }

    try {
      pending_haves_mon.enter();

      int num_haves = pending_haves.size();

      if (num_haves == 0) {

        return;
      }

      // single have -> use BT

      if (num_haves == 1 || az_have_version < BTMessageFactory.MESSAGE_VERSION_SUPPORTS_PADDING) {

        for (int i = 0; i < num_haves; i++) {

          Integer piece_num = (Integer) pending_haves.get(i);

          outgoing_message_q.addMessage(new BTHave(piece_num.intValue(), bt_have_version), true);
        }
      } else {

        int[] piece_numbers = new int[num_haves];

        for (int i = 0; i < num_haves; i++) {

          piece_numbers[i] = ((Integer) pending_haves.get(i)).intValue();
        }

        outgoing_message_q.addMessage(new AZHave(piece_numbers, az_have_version), true);
      }

      outgoing_message_q.doListenerNotifications();

      pending_haves.clear();

    } finally {

      pending_haves_mon.exit();
    }
  }
  /**
   * Create a new aggregator, which will send messages out the given queue.
   *
   * @param outgoing_message_q
   */
  public OutgoingBTHaveMessageAggregator(
      OutgoingMessageQueue outgoing_message_q, byte _bt_have_version, byte _az_have_version) {
    this.outgoing_message_q = outgoing_message_q;
    bt_have_version = _bt_have_version;
    az_have_version = _az_have_version;

    outgoing_message_q.registerQueueListener(added_message_listener);
  }
  /**
   * Queue a new have message for aggregated sending.
   *
   * @param piece_number of the have message
   * @param force if true, send this and any other pending haves right away
   */
  public void queueHaveMessage(int piece_number, boolean force) {
    if (destroyed) return;

    try {
      pending_haves_mon.enter();

      pending_haves.add(new Integer(piece_number));
      if (force) {
        sendPendingHaves();
      } else {
        int pending_bytes = pending_haves.size() * 9;
        if (pending_bytes >= outgoing_message_q.getMssSize()) {
          // System.out.println("enough pending haves for a full packet!");
          // there's enough pending bytes to fill a packet payload
          sendPendingHaves();
        }
      }
    } finally {

      pending_haves_mon.exit();
    }
  }