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()17dng_ref_counted_block::dng_ref_counted_block () 18 19 : fBuffer (NULL) 20 21 { 22 23 } 24 25 /*****************************************************************************/ 26 dng_ref_counted_block(uint32 size)27dng_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()39dng_ref_counted_block::~dng_ref_counted_block () 40 { 41 42 Clear (); 43 44 } 45 46 /*****************************************************************************/ 47 Allocate(uint32 size)48void 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()73void 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)109dng_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)132dng_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()161void 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