Skip to content
This repository was archived by the owner on Mar 22, 2023. It is now read-only.
This repository was archived by the owner on Mar 22, 2023. It is now read-only.

Code duplication reported by PMD #1191

Description

@KFilipek

ISSUE: Code duplication reported by PMD

Environment Information

  • libpmemobj-cpp version(s): e844778

Please provide a reproduction of the bug:

Get the tool from PMD site

./bin/run.sh cpd --minimum-tokens 100 --files ~/Development/work/libpmemobj-cpp/include/ --language cpp

How often bug is revealed:

(always, often, rare)

Details

./bin/run.sh cpd --minimum-tokens 100 --files ~/Development/work/libpmemobj-cpp/include/ --language cpp
Found a 34 line (240 tokens) duplication in the following files: 
Starting at line 597 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/container/segment_vector.hpp
Starting at line 133 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/container/vector.hpp

	slice<const_iterator> crange(size_type start, size_type n) const;

	/* Capacity */
	constexpr bool empty() const noexcept;
	size_type size() const noexcept;
	constexpr size_type max_size() const noexcept;
	void reserve(size_type capacity_new);
	size_type capacity() const noexcept;
	void shrink_to_fit();

	/* Modifiers */
	void clear();
	void free_data();
	iterator insert(const_iterator pos, const T &value);
	iterator insert(const_iterator pos, T &&value);
	iterator insert(const_iterator pos, size_type count, const T &value);
	template <typename InputIt,
		  typename std::enable_if<
			  detail::is_input_iterator<InputIt>::value,
			  InputIt>::type * = nullptr>
	iterator insert(const_iterator pos, InputIt first, InputIt last);
	iterator insert(const_iterator pos, std::initializer_list<T> ilist);
	template <class... Args>
	iterator emplace(const_iterator pos, Args &&... args);
	template <class... Args>
	reference emplace_back(Args &&... args);
	iterator erase(const_iterator pos);
	iterator erase(const_iterator first, const_iterator last);
	void push_back(const T &value);
	void push_back(T &&value);
	void pop_back();
	void resize(size_type count);
	void resize(size_type count, const value_type &value);
	void swap(segment_vector &other);
=====================================================================
Found a 56 line (148 tokens) duplication in the following files: 
Starting at line 61 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/make_persistent_array.hpp
Starting at line 121 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/make_persistent_array.hpp

	       static_cast<std::size_t>(std::numeric_limits<ptrdiff_t>::max()));

	if (pmemobj_tx_stage() != TX_STAGE_WORK)
		throw pmem::transaction_scope_error(
			"refusing to allocate memory outside of transaction scope");

	persistent_ptr<T> ptr = pmemobj_tx_xalloc(
		sizeof(I) * N, detail::type_num<I>(), flag.value);

	if (ptr == nullptr) {
		const char *msg = "Failed to allocate persistent memory array";
		if (errno == ENOMEM)
			throw detail::exception_with_errormsg<
				pmem::transaction_out_of_memory>(msg);
		else
			throw detail::exception_with_errormsg<
				pmem::transaction_alloc_error>(msg);
	}

	/*
	 * cache raw pointer to data - using persistent_ptr.get() in a loop
	 * is expensive.
	 */
	auto data = ptr.get();

	/*
	 * When an exception is thrown from one of the constructors
	 * we don't perform any cleanup - i.e. we don't call destructors
	 * (unlike new[] operator), we only rely on transaction abort.
	 * This approach was taken to ensure consistent behaviour for
	 * case when transaction is aborted after make_persistent completes and
	 * we have no way to call destructors.
	 */
	for (std::ptrdiff_t i = 0; i < static_cast<std::ptrdiff_t>(N); ++i)
		detail::create<I>(data + i);

	return ptr;
}

/**
 * Transactionally allocate and construct an array of objects of type T.
 *
 * This function can be used to *transactionally* allocate an array.
 * This overload only participates in overload resolution if T is an array.
 *
 * @param[in] flag affects behaviour of allocator
 *
 * @return persistent_ptr<T[N]> on success
 *
 * @throw transaction_scope_error if called outside of an active
 * transaction
 * @throw transaction_alloc_error on transactional allocation failure.
 * @throw rethrow exception from T constructor
 * @ingroup allocation
 */
template <typename T>
=====================================================================
Found a 19 line (130 tokens) duplication in the following files: 
Starting at line 2644 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/container/basic_string.hpp
Starting at line 2860 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/container/basic_string.hpp

	auto count2 = static_cast<size_type>(std::distance(first2, last2));

	count = (std::min)(count, sz - index);

	if (sz - count + count2 > max_size())
		throw std::length_error("Count exceeds max size.");

	auto new_size = sz - count + count2;

	auto pop = get_pool();

	flat_transaction::run(pop, [&] {
		if (is_sso_used() && new_size <= sso_capacity) {
			add_sso_to_tx(index, new_size - index + 1);

			assert(count2 < new_size + 1);
			traits_type::move(&sso_data()._data[index + count2],
					  &sso_data()._data[index + count],
					  sz - index - count);
=====================================================================
Found a 52 line (123 tokens) duplication in the following files: 
Starting at line 56 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/mutex.hpp
Starting at line 59 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/timed_mutex.hpp

	~mutex() = default;

	/**
	 * Locks the mutex, blocks if already locked.
	 *
	 * If a different thread already locked this mutex, the calling
	 * thread will block. If the same thread tries to lock a mutex
	 * it already owns, the behavior is undefined.
	 *
	 * @throw lock_error when an error occurs, this includes all
	 * system related errors with the underlying implementation of
	 * the mutex.
	 */
	void
	lock()
	{
		PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
		if (int ret = pmemobj_mutex_lock(pop, &this->plock))
			throw pmem::lock_error(ret, std::system_category(),
					       "Failed to lock a mutex.")
				.with_pmemobj_errormsg();
	}

	/**
	 * Tries to lock the mutex, returns regardless if the lock
	 * succeeds.
	 *
	 * If the same thread tries to lock a mutex it already owns,
	 * the behavior is undefined.
	 *
	 * @return `true` on successful lock acquisition, `false`
	 * otherwise.
	 *
	 * @throw lock_error when an error occurs, this includes all
	 * system related errors with the underlying implementation of
	 * the mutex.
	 */
	bool
	try_lock()
	{
		PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
		int ret = pmemobj_mutex_trylock(pop, &this->plock);

		if (ret == 0)
			return true;
		else if (ret == EBUSY)
			return false;
		else
			throw pmem::lock_error(ret, std::system_category(),
					       "Failed to lock a mutex.")
				.with_pmemobj_errormsg();
	}
=====================================================================
Found a 24 line (111 tokens) duplication in the following files: 
Starting at line 182 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/make_persistent_array.hpp
Starting at line 229 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/make_persistent_array.hpp

	typedef typename detail::pp_array_type<T>::type I;

	if (pmemobj_tx_stage() != TX_STAGE_WORK)
		throw pmem::transaction_scope_error(
			"refusing to free memory outside of transaction scope");

	if (ptr == nullptr)
		return;

	/*
	 * cache raw pointer to data - using persistent_ptr.get() in a loop
	 * is expensive.
	 */
	auto data = ptr.get();

	for (std::ptrdiff_t i = 0; i < static_cast<std::ptrdiff_t>(N); ++i)
		detail::destroy<I>(
			data[static_cast<std::ptrdiff_t>(N) - 1 - i]);

	if (pmemobj_tx_free(*ptr.raw_ptr()) != 0)
		throw detail::exception_with_errormsg<
			pmem::transaction_free_error>(
			"failed to delete persistent memory object");
}
=====================================================================
Found a 12 line (107 tokens) duplication in the following files: 
Starting at line 3514 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/experimental/radix_tree.hpp
Starting at line 3536 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/experimental/radix_tree.hpp

						      detail::pair<K, V> &&p)
{
	return make(parent, std::piecewise_construct,
		    std::forward_as_tuple(std::move(p.first)),
		    std::forward_as_tuple(std::move(p.second)));
}

template <typename Key, typename Value, typename BytesView, bool MtMode>
template <typename K, typename V>
persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
radix_tree<Key, Value, BytesView, MtMode>::leaf::make(
	pointer_type parent, const detail::pair<K, V> &p)

Additional information about Priority and Help Requested:

Are you willing to submit a pull request with a proposed change? Yes

Requested priority: Low

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions