Skip to content

Commit

Permalink
Merge pull request cocos2d#3763 from minggo/merge-thread-safe
Browse files Browse the repository at this point in the history
make CCImage::initWithImageFileThreadSafe() thread-safe
  • Loading branch information
minggo committed Sep 24, 2013
2 parents 18e7e41 + bc8d028 commit db30f4a
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 36 deletions.
9 changes: 9 additions & 0 deletions cocos2dx/platform/CCImageCommon_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ THE SOFTWARE.
#include "png.h"
#include "jpeglib.h"
#include "tiffio.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "platform/android/CCFileUtilsAndroid.h"
#endif

#include <string>
#include <ctype.h>

Expand Down Expand Up @@ -136,7 +140,12 @@ bool CCImage::initWithImageFileThreadSafe(const char *fullpath, EImageFormat ima
{
bool bRet = false;
unsigned long nSize = 0;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
CCFileUtilsAndroid *fileUitls = (CCFileUtilsAndroid*)CCFileUtils::sharedFileUtils();
unsigned char *pBuffer = fileUitls->getFileDataForAsync(fullpath, "rb", &nSize);
#else
unsigned char *pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullpath, "rb", &nSize);
#endif
if (pBuffer != NULL && nSize > 0)
{
bRet = initWithImageData(pBuffer, nSize, imageType);
Expand Down
40 changes: 28 additions & 12 deletions cocos2dx/platform/android/CCFileUtilsAndroid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,51 +111,67 @@ bool CCFileUtilsAndroid::isAbsolutePath(const std::string& strPath)

unsigned char* CCFileUtilsAndroid::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize)
{
unsigned char * pData = 0;
return doGetFileData(pszFileName, pszMode, pSize, false);
}

unsigned char* CCFileUtilsAndroid::getFileDataForAsync(const char* pszFileName, const char* pszMode, unsigned long * pSize)
{
return doGetFileData(pszFileName, pszMode, pSize, true);
}

unsigned char* CCFileUtilsAndroid::doGetFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize, bool forAsync)
{
unsigned char * pData = 0;

if ((! pszFileName) || (! pszMode) || 0 == strlen(pszFileName))
{
return 0;
}

string fullPath = fullPathForFilename(pszFileName);

if (fullPath[0] != '/')
{
//CCLOG("GETTING FILE RELATIVE DATA: %s", pszFileName);
pData = s_pZipFile->getFileData(fullPath.c_str(), pSize);
if (forAsync)
{
pData = s_pZipFile->getFileData(fullPath.c_str(), pSize, s_pZipFile->_dataThread);
}
else
{
pData = s_pZipFile->getFileData(fullPath.c_str(), pSize);
}
}
else
{
do
do
{
// read rrom other path than user set it
//CCLOG("GETTING FILE ABSOLUTE DATA: %s", pszFileName);
FILE *fp = fopen(fullPath.c_str(), pszMode);
CC_BREAK_IF(!fp);

unsigned long size;
fseek(fp,0,SEEK_END);
size = ftell(fp);
fseek(fp,0,SEEK_SET);
pData = new unsigned char[size];
size = fread(pData,sizeof(unsigned char), size,fp);
fclose(fp);

if (pSize)
{
*pSize = size;
}
} while (0);
}
} while (0);
}

if (! pData)
{
std::string msg = "Get data from file(";
msg.append(pszFileName).append(") failed!");
CCLOG("%s", msg.c_str());
}

return pData;
}

Expand Down
8 changes: 8 additions & 0 deletions cocos2dx/platform/android/CCFileUtilsAndroid.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ class CC_DLL CCFileUtilsAndroid : public CCFileUtils
virtual std::string getWritablePath();
virtual bool isFileExist(const std::string& strFilePath);
virtual bool isAbsolutePath(const std::string& strPath);

/** This function is android specific. It is used for CCTextureCache::addImageAsync().
Don't use it in your codes.
*/
unsigned char* getFileDataForAsync(const char* pszFileName, const char* pszMode, unsigned long * pSize);

private:
unsigned char* doGetFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize, bool forAsync);
};

// end of platform group
Expand Down
63 changes: 40 additions & 23 deletions cocos2dx/support/zip_support/ZipUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,46 +455,53 @@ class ZipFilePrivate
};

ZipFile::ZipFile(const std::string &zipFile, const std::string &filter)
: m_data(new ZipFilePrivate)
: _data(new ZipFilePrivate)
, _dataThread(new ZipFilePrivate)
{
m_data->zipFile = unzOpen(zipFile.c_str());
if (m_data->zipFile)
_data->zipFile = unzOpen(zipFile.c_str());
_dataThread->zipFile = unzOpen(zipFile.c_str());
if (_data->zipFile && _dataThread->zipFile)
{
setFilter(filter);
}
}

ZipFile::~ZipFile()
{
if (m_data && m_data->zipFile)
if (_data && _data->zipFile)
{
unzClose(m_data->zipFile);
unzClose(_data->zipFile);
}
CC_SAFE_DELETE(m_data);
if (_dataThread && _dataThread->zipFile)
{
unzClose(_dataThread);
}
CC_SAFE_DELETE(_data);
CC_SAFE_DELETE(_dataThread);
}

bool ZipFile::setFilter(const std::string &filter)
bool ZipFile::setFilter(const std::string &filter, ZipFilePrivate *data)
{
bool ret = false;
do
{
CC_BREAK_IF(!m_data);
CC_BREAK_IF(!m_data->zipFile);
CC_BREAK_IF(!data);
CC_BREAK_IF(!data->zipFile);

// clear existing file list
m_data->fileList.clear();
data->fileList.clear();

// UNZ_MAXFILENAMEINZIP + 1 - it is done so in unzLocateFile
char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1];
unz_file_info64 fileInfo;

// go through all files and store position information about the required files
int err = unzGoToFirstFile64(m_data->zipFile, &fileInfo,
int err = unzGoToFirstFile64(data->zipFile, &fileInfo,
szCurrentFileName, sizeof(szCurrentFileName) - 1);
while (err == UNZ_OK)
{
unz_file_pos posInfo;
int posErr = unzGetFilePos(m_data->zipFile, &posInfo);
int posErr = unzGetFilePos(data->zipFile, &posInfo);
if (posErr == UNZ_OK)
{
std::string currentFileName = szCurrentFileName;
Expand All @@ -505,11 +512,11 @@ bool ZipFile::setFilter(const std::string &filter)
ZipEntryInfo entry;
entry.pos = posInfo;
entry.uncompressed_size = (uLong)fileInfo.uncompressed_size;
m_data->fileList[currentFileName] = entry;
data->fileList[currentFileName] = entry;
}
}
// next file - also get the information about it
err = unzGoToNextFile64(m_data->zipFile, &fileInfo,
err = unzGoToNextFile64(data->zipFile, &fileInfo,
szCurrentFileName, sizeof(szCurrentFileName) - 1);
}
ret = true;
Expand All @@ -519,20 +526,30 @@ bool ZipFile::setFilter(const std::string &filter)
return ret;
}

bool ZipFile::setFilter(const std::string &filter)
{
return (setFilter(filter, _data) && setFilter(filter, _dataThread));
}

bool ZipFile::fileExists(const std::string &fileName) const
{
bool ret = false;
do
{
CC_BREAK_IF(!m_data);
CC_BREAK_IF(!_data);

ret = m_data->fileList.find(fileName) != m_data->fileList.end();
ret = _data->fileList.find(fileName) != _data->fileList.end();
} while(false);

return ret;
}

unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *pSize)
{
return getFileData(fileName, pSize, _data);
}

unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *pSize, ZipFilePrivate *data)
{
unsigned char * pBuffer = NULL;
if (pSize)
Expand All @@ -542,29 +559,29 @@ unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *

do
{
CC_BREAK_IF(!m_data->zipFile);
CC_BREAK_IF(!data->zipFile);
CC_BREAK_IF(fileName.empty());

ZipFilePrivate::FileListContainer::const_iterator it = m_data->fileList.find(fileName);
CC_BREAK_IF(it == m_data->fileList.end());
ZipFilePrivate::FileListContainer::const_iterator it = data->fileList.find(fileName);
CC_BREAK_IF(it == data->fileList.end());

ZipEntryInfo fileInfo = it->second;

int nRet = unzGoToFilePos(m_data->zipFile, &fileInfo.pos);
int nRet = unzGoToFilePos(data->zipFile, &fileInfo.pos);
CC_BREAK_IF(UNZ_OK != nRet);

nRet = unzOpenCurrentFile(m_data->zipFile);
nRet = unzOpenCurrentFile(data->zipFile);
CC_BREAK_IF(UNZ_OK != nRet);

pBuffer = new unsigned char[fileInfo.uncompressed_size];
int CC_UNUSED nSize = unzReadCurrentFile(m_data->zipFile, pBuffer, fileInfo.uncompressed_size);
int CC_UNUSED nSize = unzReadCurrentFile(data->zipFile, pBuffer, fileInfo.uncompressed_size);
CCAssert(nSize == 0 || nSize == (int)fileInfo.uncompressed_size, "the file size is wrong");

if (pSize)
{
*pSize = fileInfo.uncompressed_size;
}
unzCloseCurrentFile(m_data->zipFile);
unzCloseCurrentFile(data->zipFile);
} while (0);

return pBuffer;
Expand Down
15 changes: 14 additions & 1 deletion cocos2dx/support/zip_support/ZipUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ THE SOFTWARE.
#include <string>
#include "CCPlatformDefine.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "platform/android/CCFileUtilsAndroid.h"
#endif

namespace cocos2d
{
/* XXX: pragma pack ??? */
Expand Down Expand Up @@ -166,6 +170,10 @@ namespace cocos2d
class ZipFile
{
public:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
friend class CCFileUtilsAndroid;
#endif

/**
* Constructor, open zip file and store file list.
*
Expand Down Expand Up @@ -211,8 +219,13 @@ namespace cocos2d
unsigned char *getFileData(const std::string &fileName, unsigned long *pSize);

private:
bool setFilter(const std::string &filer, ZipFilePrivate *data);
unsigned char *getFileData(const std::string &fileName, unsigned long *pSize, ZipFilePrivate *data);

/** Internal data like zip file pointer / file list array and so on */
ZipFilePrivate *m_data;
ZipFilePrivate *_data;
/** Another data used not in main thread */
ZipFilePrivate *_dataThread;
};
} // end of namespace cocos2d
#endif // __SUPPORT_ZIPUTILS_H__
Expand Down

0 comments on commit db30f4a

Please sign in to comment.