2022-02-10 23:07:11 +01:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
2020-06-09 10:10:56 +02:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
* \ingroup bli
|
|
|
|
*
|
2020-06-09 10:27:24 +02:00
|
|
|
* This file contains slot types that are supposed to be used with blender::VectorSet.
|
2020-06-09 10:10:56 +02:00
|
|
|
*
|
|
|
|
* Every slot type has to be able to hold an integer index and state information.
|
|
|
|
* A vector set slot has three possible states: empty, occupied and removed.
|
|
|
|
*
|
|
|
|
* A vector slot type has to implement a couple of methods that are explained in
|
|
|
|
* SimpleVectorSetSlot.
|
|
|
|
* A vector slot type is assumed to be trivially destructible, when it is in empty or removed
|
|
|
|
* state.
|
|
|
|
*
|
|
|
|
* Possible Improvements:
|
|
|
|
* - Implement a slot type that stores the hash.
|
|
|
|
* - Implement a slot type that stores the key. That means that the key would be stored in two
|
|
|
|
* places: the key vector and the slot itself. Maybe storing the key in the slot as well, can
|
|
|
|
* result in better performance, due to better cache utilization.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "BLI_sys_types.h"
|
|
|
|
|
2020-06-09 10:27:24 +02:00
|
|
|
namespace blender {
|
2020-06-09 10:10:56 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The simplest possible vector set slot. It stores the index and state in a signed integer. If the
|
|
|
|
* value is negative, it represents empty or occupied state. Otherwise it represents the index.
|
|
|
|
*/
|
|
|
|
template<typename Key> class SimpleVectorSetSlot {
|
|
|
|
private:
|
|
|
|
#define s_is_empty -1
|
|
|
|
#define s_is_removed -2
|
|
|
|
|
|
|
|
/**
|
|
|
|
* After the default constructor has run, the slot has to be in the empty state.
|
|
|
|
*/
|
2020-07-20 12:16:20 +02:00
|
|
|
int64_t state_ = s_is_empty;
|
2020-06-09 10:10:56 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Return true if this slot contains an index to a key.
|
|
|
|
*/
|
|
|
|
bool is_occupied() const
|
|
|
|
{
|
2020-07-03 14:15:05 +02:00
|
|
|
return state_ >= 0;
|
2020-06-09 10:10:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return true if the slot is empty, i.e. it does not contain an index.
|
|
|
|
*/
|
|
|
|
bool is_empty() const
|
|
|
|
{
|
2020-07-03 14:15:05 +02:00
|
|
|
return state_ == s_is_empty;
|
2020-06-09 10:10:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the stored index. It is assumed that the slot is occupied.
|
|
|
|
*/
|
2020-07-20 12:16:20 +02:00
|
|
|
int64_t index() const
|
2020-06-09 10:10:56 +02:00
|
|
|
{
|
|
|
|
BLI_assert(this->is_occupied());
|
2020-07-20 12:16:20 +02:00
|
|
|
return state_;
|
2020-06-09 10:10:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return true if the slot contains the given key, i.e. its index points to a key that compares
|
|
|
|
* equal to it. The hash can be used by other implementations to determine inequality faster.
|
|
|
|
*/
|
|
|
|
template<typename ForwardKey, typename IsEqual>
|
|
|
|
bool contains(const ForwardKey &key,
|
|
|
|
const IsEqual &is_equal,
|
2020-07-20 12:16:20 +02:00
|
|
|
uint64_t UNUSED(hash),
|
2020-06-09 10:10:56 +02:00
|
|
|
const Key *keys) const
|
|
|
|
{
|
2020-07-03 14:15:05 +02:00
|
|
|
if (state_ >= 0) {
|
|
|
|
return is_equal(key, keys[state_]);
|
2020-06-09 10:10:56 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Change the state of this slot from empty/removed to occupied. The hash can be used by other
|
|
|
|
* slot implementations.
|
|
|
|
*/
|
2020-07-20 12:16:20 +02:00
|
|
|
void occupy(int64_t index, uint64_t UNUSED(hash))
|
2020-06-09 10:10:56 +02:00
|
|
|
{
|
|
|
|
BLI_assert(!this->is_occupied());
|
2020-07-20 12:16:20 +02:00
|
|
|
state_ = index;
|
2020-06-09 10:10:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The key has changed its position in the vector, so the index has to be updated. This method
|
|
|
|
* can assume that the slot is currently occupied.
|
|
|
|
*/
|
2020-07-20 12:16:20 +02:00
|
|
|
void update_index(int64_t index)
|
2020-06-09 10:10:56 +02:00
|
|
|
{
|
|
|
|
BLI_assert(this->is_occupied());
|
2020-07-20 12:16:20 +02:00
|
|
|
state_ = index;
|
2020-06-09 10:10:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Change the state of this slot from occupied to removed.
|
|
|
|
*/
|
|
|
|
void remove()
|
|
|
|
{
|
|
|
|
BLI_assert(this->is_occupied());
|
2020-07-03 14:15:05 +02:00
|
|
|
state_ = s_is_removed;
|
2020-06-09 10:10:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return true if this slot is currently occupied and its corresponding key has the given index.
|
|
|
|
*/
|
2020-07-20 12:16:20 +02:00
|
|
|
bool has_index(int64_t index) const
|
2020-06-09 10:10:56 +02:00
|
|
|
{
|
2020-07-20 12:16:20 +02:00
|
|
|
return state_ == index;
|
2020-06-09 10:10:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the hash of the currently stored key. In this simple set slot implementation, we just
|
|
|
|
* compute the hash here. Other implementations might store the hash in the slot instead.
|
|
|
|
*/
|
2020-07-20 12:16:20 +02:00
|
|
|
template<typename Hash> uint64_t get_hash(const Key &key, const Hash &hash) const
|
2020-06-09 10:10:56 +02:00
|
|
|
{
|
|
|
|
BLI_assert(this->is_occupied());
|
|
|
|
return hash(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef s_is_empty
|
|
|
|
#undef s_is_removed
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Key> struct DefaultVectorSetSlot;
|
|
|
|
|
|
|
|
template<typename Key> struct DefaultVectorSetSlot {
|
|
|
|
using type = SimpleVectorSetSlot<Key>;
|
|
|
|
};
|
|
|
|
|
2020-06-09 10:27:24 +02:00
|
|
|
} // namespace blender
|