嗨,我最近看cc.loader的jsb相关代码
void __JSDownloaderDelegator::downloadAsync(uint32_t countOfMaxProcessingTasks, uint32_t timeoutInSeconds)
{
retain();
auto t = std::thread(&__JSDownloaderDelegator::startDownload, this, countOfMaxProcessingTasks, timeoutInSeconds);
t.detach();
}
发现这里面并没有对线程加锁,多个线程同时执行startDownload函数,如果是Android环境,会同时创建多个DownloaderAndroid,
_downloader = std::make_sharedcocos2d::network::Downloader(hints);
而在DownloaderAndroid的构造函数中,会执行++操作,以及sDownloaderMap.insert,这些在多线程环境下不会有啥问题吗?
DownloaderAndroid::DownloaderAndroid(const DownloaderHints& hints)
: _id(++sDownloaderCounter)
, _impl(nullptr)
{
DLLOG(“Construct DownloaderAndroid: %p”, this);
JniMethodInfo methodInfo;
if (JniHelper::getStaticMethodInfo(methodInfo,
JCLS_DOWNLOADER,
“createDownloader”,
“(II” JARG_STR “I)” JARG_DOWNLOADER))
{
jobject jStr = methodInfo.env->NewStringUTF(hints.tempFileNameSuffix.c_str());
jobject jObj = methodInfo.env->CallStaticObjectMethod(
methodInfo.classID,
methodInfo.methodID,
_id,
hints.timeoutInSeconds,
jStr,
hints.countOfMaxProcessingTasks
);
_impl = methodInfo.env->NewGlobalRef(jObj);
DLLOG(“android downloader: jObj: %p, _impl: %p”, jObj, _impl);
sDownloaderMap.insert(make_pair(_id, this));
methodInfo.env->DeleteLocalRef(jStr);
methodInfo.env->DeleteLocalRef(jObj);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
}
另外,每个DownloaderAndroid又会通过JNI的createDownloader创建一个Java层的Cocos2dxDownloader,然后给再调用JNI的createTask创建下载任务。也就是说一个Cocos2dxDownloader仅仅执行一次createTask,不会有一个Cocos2dxDownloader执行多次createTask的情况。那么Cocos2dxDownloader里面的enqueueTask里面的_runningTaskCount作用,在cc.loader下载网络数据的时候,就没什么意义了。
public void enqueueTask(Runnable taskRunnable) {
synchronized (_taskQueue) {
if (_runningTaskCount < _countOfMaxProcessingTasks) {
Cocos2dxHelper.getActivity().runOnUiThread(taskRunnable);
_runningTaskCount++;
} else {
_taskQueue.add(taskRunnable);
}
}
}