1 /*****************************************************************************/
2 // Copyright 2006-2019 Adobe Systems Incorporated
3 // All Rights Reserved.
4 //
5 // NOTICE:  Adobe permits you to use, modify, and distribute this file in
6 // accordance with the terms of the Adobe license agreement accompanying it.
7 /*****************************************************************************/
8 
9 #include <new>
10 
11 #include "dng_ref_counted_block.h"
12 
13 #include "dng_exceptions.h"
14 
15 /*****************************************************************************/
16 
dng_ref_counted_block()17 dng_ref_counted_block::dng_ref_counted_block ()
18 
19 	:	fBuffer (NULL)
20 
21 	{
22 
23 	}
24 
25 /*****************************************************************************/
26 
dng_ref_counted_block(uint32 size)27 dng_ref_counted_block::dng_ref_counted_block (uint32 size)
28 
29 	:	fBuffer (NULL)
30 
31 	{
32 
33 	Allocate (size);
34 
35 	}
36 
37 /*****************************************************************************/
38 
~dng_ref_counted_block()39 dng_ref_counted_block::~dng_ref_counted_block ()
40 	{
41 
42 	Clear ();
43 
44 	}
45 
46 /*****************************************************************************/
47 
Allocate(uint32 size)48 void dng_ref_counted_block::Allocate (uint32 size)
49 	{
50 
51 	Clear ();
52 
53 	if (size)
54 		{
55 
56 		fBuffer = malloc (size + sizeof (header));
57 
58 		if (!fBuffer)
59 			{
60 
61 			ThrowMemoryFull ();
62 
63 			}
64 
65 		new (fBuffer) header (size);
66 
67 		}
68 
69 	}
70 
71 /*****************************************************************************/
72 
Clear()73 void dng_ref_counted_block::Clear ()
74 	{
75 
76 	if (fBuffer)
77 		{
78 
79 		bool doFree = false;
80 
81 		header *blockHeader = (struct header *)fBuffer;
82 
83 			{
84 
85 			dng_lock_std_mutex lock (blockHeader->fMutex);
86 
87 			if (--blockHeader->fRefCount == 0)
88 				doFree = true;
89 
90 			}
91 
92 		if (doFree)
93 			{
94 
95 			blockHeader->~header ();
96 
97 			free (fBuffer);
98 
99 			}
100 
101 		fBuffer = NULL;
102 
103 		}
104 
105 	}
106 
107 /*****************************************************************************/
108 
dng_ref_counted_block(const dng_ref_counted_block & data)109 dng_ref_counted_block::dng_ref_counted_block (const dng_ref_counted_block &data)
110 
111 	:   fBuffer (NULL)
112 
113 	{
114 
115 	header *blockHeader = (struct header *) data.fBuffer;
116 
117     if (blockHeader)
118         {
119 
120 		dng_lock_std_mutex lock (blockHeader->fMutex);
121 
122         blockHeader->fRefCount++;
123 
124         fBuffer = blockHeader;
125 
126         }
127 
128 	}
129 
130 /*****************************************************************************/
131 
operator =(const dng_ref_counted_block & data)132 dng_ref_counted_block & dng_ref_counted_block::operator= (const dng_ref_counted_block &data)
133 	{
134 
135 	if (this != &data)
136 		{
137 
138 		Clear ();
139 
140 		header *blockHeader = (struct header *) data.fBuffer;
141 
142         if (blockHeader)
143             {
144 
145             dng_lock_std_mutex lock (blockHeader->fMutex);
146 
147             blockHeader->fRefCount++;
148 
149             fBuffer = blockHeader;
150 
151             }
152 
153 		}
154 
155 	return *this;
156 
157 	}
158 
159 /*****************************************************************************/
160 
EnsureWriteable()161 void dng_ref_counted_block::EnsureWriteable ()
162 	{
163 
164 	if (fBuffer)
165 		{
166 
167 		header *possiblySharedHeader = (header *) fBuffer;
168 
169 			{
170 
171 			dng_lock_std_mutex lock (possiblySharedHeader->fMutex);
172 
173 			if (possiblySharedHeader->fRefCount > 1)
174 				{
175 
176 				fBuffer = NULL;
177 
178 				Allocate ((uint32)possiblySharedHeader->fSize);
179 
180 				memcpy (Buffer (),
181 					((char *)possiblySharedHeader) + sizeof (struct header), // could just do + 1 w/o cast, but this makes the type mixing more explicit
182 					possiblySharedHeader->fSize);
183 
184 				possiblySharedHeader->fRefCount--;
185 
186 				}
187 
188 			}
189 
190 		}
191 
192 	}
193 
194 /*****************************************************************************/
195