File: object.cpp

package info (click to toggle)
sight 25.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 43,252 kB
  • sloc: cpp: 310,629; xml: 17,622; ansic: 9,960; python: 1,379; sh: 144; makefile: 33
file content (146 lines) | stat: -rw-r--r-- 4,490 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/************************************************************************
 *
 * Copyright (C) 2009-2024 IRCAD France
 * Copyright (C) 2012-2021 IHU Strasbourg
 *
 * This file is part of Sight.
 *
 * Sight is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Sight is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Sight. If not, see <https://www.gnu.org/licenses/>.
 *
 ***********************************************************************/

// cspell:ignore NOLINT

#include "object.hpp"

#include "tools/uuid.hpp"

#include <map>
#include <mutex>

namespace sight::core
{

static std::map<const object*, std::string> s_ptr_to_uuid;
static std::map<std::string, object::wptr> s_uuid_to_wptr;
static std::mutex s_maps_mutex;

//------------------------------------------------------------------------------

object::sptr object::from_uuid(const std::string& _uuid)
{
    // Find the weak pointer associated to this uuid
    std::lock_guard guard(s_maps_mutex);
    const auto found = s_uuid_to_wptr.find(_uuid);

    if(found != s_uuid_to_wptr.cend())
    {
        // If we found it, return it now
        return found->second.lock();
    }

    return {};
}

//------------------------------------------------------------------------------

std::string object::get_uuid() const
{
    // First, try to find the uuid
    std::lock_guard guard(s_maps_mutex);
    const auto found = s_ptr_to_uuid.find(this);

    if(found != s_ptr_to_uuid.cend())
    {
        // If we found it, return it now
        return found->second;
    }

    // If not found, generate a new one
    std::string uuid;

    // Since we can manually set an uuid, we must ensure that the generated one did not generate an existing one.
    // Almost impossible, but possible
    do
    {
        uuid = tools::uuid::generate();
    }
    while(s_uuid_to_wptr.find(uuid) != s_uuid_to_wptr.end());

    // Store the uuid
    s_ptr_to_uuid[this] = uuid;

    // Store also a weak pointer
    // As we don't modify the underlying object, but only store a non const weak pointer,
    // the "const" contract is not really broken in this method.
    // This is a compromise to allow a "lazy" uuid generation
    s_uuid_to_wptr[uuid] = const_cast<object*>(this)->get_sptr(); // NOLINT(cppcoreguidelines-pro-type-const-cast)

    return uuid;
}

//------------------------------------------------------------------------------

void object::set_uuid(const std::string& _uuid, const bool _force)
{
    std::lock_guard guard(s_maps_mutex);

    if(!_force)
    {
        // Look if the uuid has already been used
        const auto found_wptr = s_uuid_to_wptr.find(_uuid);
        if(found_wptr != s_uuid_to_wptr.cend())
        {
            // Try to see if the object is different
            object::sptr old = found_wptr->second.lock();

            if(old && this != old.get())
            {
                /// That's no good, we set an already used uuid
                SIGHT_FATAL("UUID '" << _uuid << "' is already used for object '" << old->get_id() << "'");
            }
        }

        // Look if the object has already been registered
        const auto found_uuid = s_ptr_to_uuid.find(this);
        if(found_uuid != s_ptr_to_uuid.cend())
        {
            // Try to see if the uuid is different
            const std::string& old = found_uuid->second;
            if(!old.empty() && _uuid != old)
            {
                /// That's no good, the object has already be registered with a different uuid
                SIGHT_FATAL("Object '" << get_id() << "' is already registered with UUID '" << old << "'");
            }
        }
    }

    s_ptr_to_uuid[this]   = _uuid;
    s_uuid_to_wptr[_uuid] = get_sptr();
}

object::~object()
{
    std::lock_guard guard(s_maps_mutex);
    const auto found = s_ptr_to_uuid.find(this);

    // If we found it, erase us.
    if(found != s_ptr_to_uuid.cend())
    {
        s_uuid_to_wptr.erase(found->second);
        s_ptr_to_uuid.erase(found);
    }
}

} //namespace sight::core