/*****************************************************************************/ // Copyright 2006 Adobe Systems Incorporated // All Rights Reserved. // // NOTICE: Adobe permits you to use, modify, and distribute this file in // accordance with the terms of the Adobe license agreement accompanying it. /*****************************************************************************/ /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_ref_counted_block.cpp#1 $ */ /* $DateTime: 2012/05/30 13:28:51 $ */ /* $Change: 832332 $ */ /* $Author: tknoll $ */ /*****************************************************************************/ #include <new> #include "dng_ref_counted_block.h" #include "dng_exceptions.h" /*****************************************************************************/ dng_ref_counted_block::dng_ref_counted_block () : fBuffer (NULL) { } /*****************************************************************************/ dng_ref_counted_block::dng_ref_counted_block (uint32 size) : fBuffer (NULL) { Allocate (size); } /*****************************************************************************/ dng_ref_counted_block::~dng_ref_counted_block () { Clear (); } /*****************************************************************************/ void dng_ref_counted_block::Allocate (uint32 size) { Clear (); if (size) { fBuffer = malloc (size + sizeof (header)); if (!fBuffer) { ThrowMemoryFull (); } new (fBuffer) header (size); } } /*****************************************************************************/ void dng_ref_counted_block::Clear () { if (fBuffer) { bool doFree = false; header *blockHeader = (struct header *)fBuffer; { dng_lock_mutex lock (&blockHeader->fMutex); if (--blockHeader->fRefCount == 0) doFree = true; } if (doFree) { blockHeader->~header (); free (fBuffer); } fBuffer = NULL; } } /*****************************************************************************/ dng_ref_counted_block::dng_ref_counted_block (const dng_ref_counted_block &data) : fBuffer (NULL) { header *blockHeader = (struct header *)data.fBuffer; dng_lock_mutex lock (&blockHeader->fMutex); blockHeader->fRefCount++; fBuffer = blockHeader; } /*****************************************************************************/ dng_ref_counted_block & dng_ref_counted_block::operator= (const dng_ref_counted_block &data) { if (this != &data) { Clear (); header *blockHeader = (struct header *)data.fBuffer; dng_lock_mutex lock (&blockHeader->fMutex); blockHeader->fRefCount++; fBuffer = blockHeader; } return *this; } /*****************************************************************************/ void dng_ref_counted_block::EnsureWriteable () { if (fBuffer) { header *possiblySharedHeader = (header *)fBuffer; { dng_lock_mutex lock (&possiblySharedHeader->fMutex); if (possiblySharedHeader->fRefCount > 1) { fBuffer = NULL; Allocate ((uint32)possiblySharedHeader->fSize); memcpy (Buffer (), ((char *)possiblySharedHeader) + sizeof (struct header), // could just do + 1 w/o cast, but this makes the type mixing more explicit possiblySharedHeader->fSize); possiblySharedHeader->fRefCount--; } } } } /*****************************************************************************/