Returns the handle of a RawArray created from the given numpy array.

        Args:
          arr: A numpy ndarray.

        Returns:
          The handle (int) of the array.

        Raises:
          ValueError: if arr is not a ndarray or of an unsupported dtype. If
            the array is of an unsupported type, using a view of the array to
            another dtype and then converting on get is often a work around.

def _create_array(self, arr: np.ndarray) -> int:
        """Returns the handle of a RawArray created from the given numpy array.

        Args:
          arr: A numpy ndarray.

        Returns:
          The handle (int) of the array.

        Raises:
          ValueError: if arr is not a ndarray or of an unsupported dtype. If
            the array is of an unsupported type, using a view of the array to
            another dtype and then converting on get is often a work around.
        """
        if not isinstance(arr, np.ndarray):
            raise ValueError('Array is not a numpy ndarray.')
        try:
            c_arr = np.ctypeslib.as_ctypes(arr)
        except (KeyError, NotImplementedError):
            raise ValueError(
                'Array has unsupported dtype {}.'.format(arr.dtype))

        # pylint: disable=protected-access
        raw_arr = RawArray(c_arr._type_, c_arr)

        with self._lock:
            if self._count >= len(self._arrays):
                self._arrays += len(self._arrays) * [None]

            self._get_next_free()

            # Note storing the shape is a workaround for an issue encountered
            # when upgrading to numpy 1.15.
            # See https://github.com/numpy/numpy/issues/11636
            self._arrays[self._current] = (raw_arr, arr.shape)

            self._count += 1

        return self._current