C++程序  |  188行  |  3.39 KB

/*****************************************************************************/
// 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--;

				}

			}

		}
	}

/*****************************************************************************/