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 24 dng_ref_counted_block::dng_ref_counted_block () 25 26 : fBuffer (NULL) 27 28 { 29 30 } 31 32 /*****************************************************************************/ 33 34 dng_ref_counted_block::dng_ref_counted_block (uint32 size) 35 36 : fBuffer (NULL) 37 38 { 39 40 Allocate (size); 41 42 } 43 44 /*****************************************************************************/ 45 46 dng_ref_counted_block::~dng_ref_counted_block () 47 { 48 49 Clear (); 50 51 } 52 53 /*****************************************************************************/ 54 55 void 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 80 void 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 116 dng_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 132 dng_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 155 void 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