From 35020c7c71cf53cbd6e8b447d3e71d8beea96028 Mon Sep 17 00:00:00 2001 From: yangxiao Date: Wed, 26 Nov 2014 11:28:14 +0800 Subject: [PATCH] async task pool --- build/cocos2d_libs.xcodeproj/project.pbxproj | 12 ++ cocos/base/CCAsyncTaskPool.cpp | 91 ++++++++++++++ cocos/base/CCAsyncTaskPool.h | 121 +++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 cocos/base/CCAsyncTaskPool.cpp create mode 100644 cocos/base/CCAsyncTaskPool.h diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj b/build/cocos2d_libs.xcodeproj/project.pbxproj index 452e52b591..4f0b4766d4 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj @@ -1949,6 +1949,10 @@ B60C5BD519AC68B10056FBDE /* CCBillBoard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B60C5BD219AC68B10056FBDE /* CCBillBoard.cpp */; }; B60C5BD619AC68B10056FBDE /* CCBillBoard.h in Headers */ = {isa = PBXBuildFile; fileRef = B60C5BD319AC68B10056FBDE /* CCBillBoard.h */; }; B60C5BD719AC68B10056FBDE /* CCBillBoard.h in Headers */ = {isa = PBXBuildFile; fileRef = B60C5BD319AC68B10056FBDE /* CCBillBoard.h */; }; + B63703141A256A0200A83662 /* CCAsyncTaskPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63703121A256A0200A83662 /* CCAsyncTaskPool.cpp */; }; + B63703151A256A0200A83662 /* CCAsyncTaskPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63703121A256A0200A83662 /* CCAsyncTaskPool.cpp */; }; + B63703161A256A0200A83662 /* CCAsyncTaskPool.h in Headers */ = {isa = PBXBuildFile; fileRef = B63703131A256A0200A83662 /* CCAsyncTaskPool.h */; }; + B63703171A256A0200A83662 /* CCAsyncTaskPool.h in Headers */ = {isa = PBXBuildFile; fileRef = B63703131A256A0200A83662 /* CCAsyncTaskPool.h */; }; DA8C62A219E52C6400000516 /* ioapi_mem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA8C62A019E52C6400000516 /* ioapi_mem.cpp */; }; DA8C62A319E52C6400000516 /* ioapi_mem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA8C62A019E52C6400000516 /* ioapi_mem.cpp */; }; DA8C62A419E52C6400000516 /* ioapi_mem.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8C62A119E52C6400000516 /* ioapi_mem.h */; }; @@ -3011,6 +3015,8 @@ B3AF019F1842FBA400A98B85 /* b2MotorJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2MotorJoint.h; sourceTree = ""; }; B60C5BD219AC68B10056FBDE /* CCBillBoard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCBillBoard.cpp; sourceTree = ""; }; B60C5BD319AC68B10056FBDE /* CCBillBoard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCBillBoard.h; sourceTree = ""; }; + B63703121A256A0200A83662 /* CCAsyncTaskPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CCAsyncTaskPool.cpp; path = ../base/CCAsyncTaskPool.cpp; sourceTree = ""; }; + B63703131A256A0200A83662 /* CCAsyncTaskPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCAsyncTaskPool.h; path = ../base/CCAsyncTaskPool.h; sourceTree = ""; }; B67C624319D4186F00F11FC6 /* ccShader_3D_ColorNormal.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_ColorNormal.frag; sourceTree = ""; }; B67C624419D4186F00F11FC6 /* ccShader_3D_ColorNormalTex.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_ColorNormalTex.frag; sourceTree = ""; }; B67C624519D4186F00F11FC6 /* ccShader_3D_PositionNormalTex.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_PositionNormalTex.vert; sourceTree = ""; }; @@ -3222,6 +3228,8 @@ 1A5700A2180BC5E60088DEC7 /* base */ = { isa = PBXGroup; children = ( + B63703121A256A0200A83662 /* CCAsyncTaskPool.cpp */, + B63703131A256A0200A83662 /* CCAsyncTaskPool.h */, 299CF1F919A434BC00C378C1 /* ccRandom.cpp */, 299CF1FA19A434BC00C378C1 /* ccRandom.h */, 464AD6E3197EBB1400E502D8 /* pvr.cpp */, @@ -5153,6 +5161,7 @@ 15AE1B6F19AADA9900C27E9E /* GUIDefine.h in Headers */, 3828C0E519EB8ACA002AB57B /* type_traits.h in Headers */, 15AE1A8119AAD40300C27E9E /* b2FrictionJoint.h in Headers */, + B63703161A256A0200A83662 /* CCAsyncTaskPool.h in Headers */, 15AE18DD19AAD35000C27E9E /* CocoLoader.h in Headers */, 46A170EB1807CECA005B8026 /* CCPhysicsJoint.h in Headers */, 15AE191E19AAD35000C27E9E /* CCTween.h in Headers */, @@ -6135,6 +6144,7 @@ 15AE1B8519AADA9A00C27E9E /* UITextField.h in Headers */, 1A01C69318F57BE800EFE3A6 /* CCDouble.h in Headers */, B29A7E1019EE1B7700872B35 /* SkeletonJson.h in Headers */, + B63703171A256A0200A83662 /* CCAsyncTaskPool.h in Headers */, 15AE184B19AAD30500C27E9E /* Export.h in Headers */, 3828C0AC19EB8ACA002AB57B /* zero_copy_stream_impl.h in Headers */, 15AE196019AAD35100C27E9E /* CCSpriteFrameCacheHelper.h in Headers */, @@ -6681,6 +6691,7 @@ 50ABBD381925AB0000A911A9 /* CCAffineTransform.cpp in Sources */, 46C02E0718E91123004B7456 /* xxhash.c in Sources */, 15AE1B6B19AADA9900C27E9E /* UIWidget.cpp in Sources */, + B63703141A256A0200A83662 /* CCAsyncTaskPool.cpp in Sources */, 50ABBE931925AB6F00A911A9 /* CCProfiling.cpp in Sources */, 15AE188819AAD33D00C27E9E /* CCControlButtonLoader.cpp in Sources */, 15AE18A419AAD33D00C27E9E /* CCScale9SpriteLoader.cpp in Sources */, @@ -7077,6 +7088,7 @@ 3828C0B219EB8ACA002AB57B /* message_lite.cc in Sources */, 503DD8E71926736A00CD74DD /* CCEAGLView-ios.mm in Sources */, 3E2BDAEC19C0436F0055CDCD /* AudioEngine.cpp in Sources */, + B63703151A256A0200A83662 /* CCAsyncTaskPool.cpp in Sources */, 15B3707919EE414C00ABE682 /* AssetsManagerEx.cpp in Sources */, 50ABBDA41925AB4100A911A9 /* CCQuadCommand.cpp in Sources */, 15AE18C319AAD33D00C27E9E /* CCLayerGradientLoader.cpp in Sources */, diff --git a/cocos/base/CCAsyncTaskPool.cpp b/cocos/base/CCAsyncTaskPool.cpp new file mode 100644 index 0000000000..a7f6146240 --- /dev/null +++ b/cocos/base/CCAsyncTaskPool.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +Copyright (c) 2010 cocos2d-x.org +Copyright (c) 2013-2014 Chukong Technologies Inc. + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#include "base/CCAsyncTaskPool.h" + +NS_CC_BEGIN + +AsyncTaskPool* AsyncTaskPool::s_asyncTaskPool = nullptr; + +AsyncTaskPool* AsyncTaskPool::getInstance() +{ + if (s_asyncTaskPool == nullptr) + { + s_asyncTaskPool = new (std::nothrow) AsyncTaskPool(); + } + return s_asyncTaskPool; +} + +void AsyncTaskPool::destoryInstance() +{ + delete s_asyncTaskPool; + s_asyncTaskPool = nullptr; +} + +AsyncTaskPool::AsyncTaskPool() +{ + +} + +AsyncTaskPool::~AsyncTaskPool() +{ + +} + +template +auto AsyncTaskPool::enqueue(AsyncTaskPool::TaskType type, F&& f, Args&&... args) +-> std::future::type> +{ + auto& threadTask = _threadTasks[(int)type]; + //return _threadTasks[taskType].enqueue(f, args); + + using return_type = typename std::result_of::type; + + auto task = std::make_shared< std::packaged_task >( + std::bind(std::forward(f), std::forward(args)...) + ); + auto& queue_mutex = threadTask._queue_mutex; + auto& stop = threadTask._stop; + auto& tasks = threadTask._tasks; + auto& condition = threadTask._condition; + std::future res = task->get_future(); + { + std::unique_lock lock(queue_mutex); + + // don't allow enqueueing after stopping the pool + if(stop) + { + CC_ASSERT(0 && "already stop"); + return res; + } + + tasks.emplace([task](){ (*task)(); }); + } + condition.notify_one(); + + return res; +} + +NS_CC_END diff --git a/cocos/base/CCAsyncTaskPool.h b/cocos/base/CCAsyncTaskPool.h new file mode 100644 index 0000000000..e92e48224b --- /dev/null +++ b/cocos/base/CCAsyncTaskPool.h @@ -0,0 +1,121 @@ +/**************************************************************************** +Copyright (c) 2010 cocos2d-x.org +Copyright (c) 2013-2014 Chukong Technologies Inc. + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#ifndef __CCSYNC_TASK_POOL_H_ +#define __CCSYNC_TASK_POOL_H_ + +#include "platform/CCPlatformMacros.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +NS_CC_BEGIN +///////////////////////////////////////////////////////////////////////////// + +class AsyncTaskPool +{ +public: + enum class TaskType + { + TASK_IO, + TASK_NETWORK, + TASK_MAX_TYPE, + }; + static AsyncTaskPool* getInstance(); + + static void destoryInstance(); + + template + auto enqueue(TaskType type, F&& f, Args&&... args) + -> std::future::type>; + +CC_CONSTRUCTOR_ACCESS: + AsyncTaskPool(); + ~AsyncTaskPool(); + +protected: + // thread tasks internally used + class ThreadTasks { + friend class AsyncTaskPool; + public: + ThreadTasks() + : _stop(false) + { + _thread = std::thread( + [this] + { + for(;;) + { + std::function task; + + { + std::unique_lock lock(this->_queue_mutex); + this->_condition.wait(lock, + [this]{ return this->_stop || !this->_tasks.empty(); }); + if(this->_stop && this->_tasks.empty()) + return; + task = std::move(this->_tasks.front()); + this->_tasks.pop(); + } + + task(); + } + } + ); + } + ~ThreadTasks() + { + std::unique_lock lock(_queue_mutex); + _stop = true; + _condition.notify_all(); + _thread.join(); + } + private: + // need to keep track of thread so we can join them + std::thread _thread; + // the task queue + std::queue< std::function > _tasks; + + // synchronization + std::mutex _queue_mutex; + std::condition_variable _condition; + bool _stop; + }; + + //tasks + ThreadTasks _threadTasks[int(TaskType::TASK_MAX_TYPE)]; + static AsyncTaskPool* s_asyncTaskPool; +}; + + + +NS_CC_END +#endif //__CCSYNC_TASK_POOL_H_