1// Aseprite Document Library
2// Copyright (C) 2019-2022 Igara Studio S.A.
3// Copyright (C) 2001-2016 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "doc/object.h"
13
14#include "base/debug.h"
15
16#include <map>
17#include <mutex>
18
19namespace doc {
20
21static std::mutex g_mutex;
22static ObjectId newId = 0;
23// TODO Profile this and see if an unordered_map is better
24static std::map<ObjectId, Object*> objects;
25
26Object::Object(ObjectType type)
27 : m_type(type)
28 , m_id(0)
29 , m_version(0)
30{
31}
32
33Object::Object(const Object& other)
34 : m_type(other.m_type)
35 , m_id(0) // We don't copy the ID
36 , m_version(0) // We don't copy the version
37{
38}
39
40Object::~Object()
41{
42 if (m_id)
43 setId(0);
44}
45
46int Object::getMemSize() const
47{
48 return sizeof(Object);
49}
50
51const ObjectId Object::id() const
52{
53 // The first time the ID is request, we store the object in the
54 // "objects" hash table.
55 if (!m_id) {
56 std::lock_guard lock(g_mutex);
57 m_id = ++newId;
58 objects.insert(std::make_pair(m_id, const_cast<Object*>(this)));
59 }
60 return m_id;
61}
62
63void Object::setId(ObjectId id)
64{
65 std::lock_guard lock(g_mutex);
66
67 if (m_id) {
68 auto it = objects.find(m_id);
69 ASSERT(it != objects.end());
70 ASSERT(it->second == this);
71 if (it != objects.end())
72 objects.erase(it);
73 }
74
75 m_id = id;
76
77 if (m_id) {
78#ifdef _DEBUG
79 if (objects.find(m_id) != objects.end()) {
80 Object* obj = objects.find(m_id)->second;
81 if (obj) {
82 TRACEARGS("ASSERT FAILED: Object with id", m_id,
83 "of kind", int(obj->type()),
84 "version", obj->version(), "should not exist");
85 }
86 else {
87 TRACEARGS("ASSERT FAILED: Object with id", m_id,
88 "registered as nullptr should not exist");
89 }
90 }
91 ASSERT(objects.find(m_id) == objects.end());
92#endif
93 objects.insert(std::make_pair(m_id, this));
94 }
95}
96
97void Object::setVersion(ObjectVersion version)
98{
99 m_version = version;
100}
101
102Object* get_object(ObjectId id)
103{
104 std::lock_guard lock(g_mutex);
105 auto it = objects.find(id);
106 if (it != objects.end())
107 return it->second;
108 else
109 return nullptr;
110}
111
112} // namespace doc
113