docs: protected boolean call(Object... paramListIn) {
          m_perCallStats = m_statsCollector.beginProcedure();
  
          // if we're keeping track, calculate parameter size
          if (m_perCallStats.samplingProcedure()) {
              ParameterSet params = ParameterSet.fromArrayNoCopy(paramListIn);
              m_perCallStats.setParameterSize(params.getSerializedSize());
          }
  
          ClientResponseImpl response = coreCall(paramListIn);
  
          // null response means this procedure isn't over and has some async component
          if (response == null) {
              return false;
          }
  
          // if the whole call is done (no async bits)
  
          // if we're keeping track, calculate result size
          if (m_perCallStats.samplingProcedure()) {
              m_perCallStats.setResultSize(response.getResults());
          }
          m_statsCollector.endProcedure(response.getStatus() == ClientResponse.USER_ABORT,
                                        (response.getStatus() != ClientResponse.USER_ABORT) &&
                                        (response.getStatus() != ClientResponse.SUCCESS),
                                        m_perCallStats);
          // allow the GC to collect per-call stats if this proc isn't called for a while
          m_perCallStats = null;
  
          // send the response to caller
          // must be done as IRM to CI mailbox for backpressure accounting
          response.setClientHandle(m_clientHandle);
          InitiateResponseMessage irm = InitiateResponseMessage.messageForNTProcResponse(m_ciHandle,
                                                                                         m_ccxn.connectionId(),
                                                                                         response);
          m_mailbox.deliver(irm);
  
          // remove record of this procedure in NTPS
          // only done if procedure is really done
          m_ntProcService.handleNTProcEnd(this);
  
          return true;
      }