Flow 1.0.0
Flow project: Public API.
Public Types | Public Member Functions | Static Public Member Functions | List of all members
flow::util::Unique_id_holder Class Reference

Each object of this class stores (at construction) and returns (on demand) a numeric ID unique from all other objects of the same class ever constructed, across all time from program start to end. More...

#include <uniq_id_holder.hpp>

Inheritance diagram for flow::util::Unique_id_holder:
[legend]

Public Types

using id_t = uint64_t
 Raw integer type to uniquely identify a thing. 64-bit width should make overflow extremely hard to reach.
 

Public Member Functions

 Unique_id_holder ()
 Thread-safely construct an ID whose value is different from any other object of this class, past or future.
 
 Unique_id_holder (const Unique_id_holder &)
 This copy constructor is identical in behavior to Unique_id_holder(), the default ctor. More...
 
id_t unique_id () const
 Raw unique ID identifying this object as well as any object of a derived type. More...
 
const Unique_id_holderoperator= (const Unique_id_holder &) const
 This assignment operator is a const no-op. More...
 

Static Public Member Functions

static id_t create_unique_id ()
 Short-hand for Unique_id_holder().unique_id(); useful when all you want is the unique integer itself. More...
 

Detailed Description

Each object of this class stores (at construction) and returns (on demand) a numeric ID unique from all other objects of the same class ever constructed, across all time from program start to end.

To be clear, the uniqueness is not just for all existing objects at a given point in time (for which this could simply be used instead) but across all time.

Copying behavior

For obvious reasons, Unique_id_holder cannot have standard copy construction and assignment semantics. It was contemplated to simply make class noncopyable (forbidding copy construction). However, then no derived type could use auto-generated copy construction and/or operator=(), making the deriving usage pattern (see below) considerably less concise for such types.

Therefore, it defines a (somewhat unusual) copy constructor: It is simply equal to the default constructor and simply generates a unique ID. The reason: a common pattern (see below) will involve type C deriving from Unique_id_holder. If C happens to use the auto-generated copy constructor implementation, Unique_id_holder's copy constructor will be invoked by this implementation. Since equal (by value) objects are still separate objects, the correct behavior is for the constructed object to gain a new ID.

The assignment operator operator=() similarly has unusual behavior: it does nothing, for similar reasons.

Thread safety, performance

All operations safe for simultaneous execution on 2+ separate objects or on the same object. The ID accessor is a totally trivial accessor. Only construction requires any concurrent-access protection and internally uses an atomic for good efficiency.

Usage patterns

This can be used, in particular, to uniquely identify (over all time) objects of any type (across all types). The most concise usage pattern is probably via public (or possibly private) inheritance. Another is simply via composition (storage).

void Widget_store::store_in_table(Widget* obj, const Unique_id_holder& obj_id_holder)
{
m_unordered_map[obj_id_holder.unique_id()] = obj;
}
// Usage pattern 1: Inheritance.
class Widget : ..., public Unique_id_holder // Can change to private inheritance if we always register internally.
{
private:
// Example of an object registering itself.
void some_private_method()
{
...
s_widget_store.store_in_table(this, *this); // `*this` is itself a Unique_id_holder.
...
}
static Widget_store s_widget_store;
};
...
// Example of outside code registering an object.
Widget_store widget_store;
Widget widget;
widget_store::store_in_table(&widget, widget); // `widget` is itself a Unique_id_holder.
...
// Usage pattern 2: Composition.
class Widget : ...
{
private:
// Example of an object registering itself.
void some_private_method()
{
...
s_widget_store.store_in_table(this, m_uniq_id_holder);
...
}
Unique_id_holder m_uniq_id_holder;
static Widget_store s_widget_store;
};
Each object of this class stores (at construction) and returns (on demand) a numeric ID unique from a...
Definition: uniq_id_holder.hpp:107
id_t unique_id() const
Raw unique ID identifying this object as well as any object of a derived type.
Definition: uniq_id_holder.cpp:53
Unique_id_holder()
Thread-safely construct an ID whose value is different from any other object of this class,...
Definition: uniq_id_holder.cpp:31

Update: A simplified pattern is now possible: If you just want the raw unique number itself and don't even want to keep Unique_id_holder objects around or refer to them, call the static create_unique_id() which returns a new raw id_t integer. The above 2 usage patterns can be rewritten to pass around id_t values. The "Example of outside code registering an object" sub-case is the one exception to that, as for that either store_in_table() must continue to take a Unique_id_holder and not a raw integer, or I suppose m_uniq_id_holder must be made public which some would not like.

Constructor & Destructor Documentation

◆ Unique_id_holder()

flow::util::Unique_id_holder::Unique_id_holder ( const Unique_id_holder )
explicit

This copy constructor is identical in behavior to Unique_id_holder(), the default ctor.

Unique_id_holder doc header explains this behavior and why copy construction is not disallowed entirely.

Member Function Documentation

◆ create_unique_id()

Unique_id_holder::id_t flow::util::Unique_id_holder::create_unique_id ( )
static

Short-hand for Unique_id_holder().unique_id(); useful when all you want is the unique integer itself.

Returns
See unique_id().

◆ operator=()

const Unique_id_holder & flow::util::Unique_id_holder::operator= ( const Unique_id_holder ) const

This assignment operator is a const no-op.

Unique_id_holder doc header explains this behavior, and why assignment is not disallowed entirely.

Returns
*this.

◆ unique_id()

Unique_id_holder::id_t flow::util::Unique_id_holder::unique_id ( ) const

Raw unique ID identifying this object as well as any object of a derived type.

Returns
Numeric ID. Can be used as a key for most classic associative containers without extra code.

The documentation for this class was generated from the following files: