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