From 2f74f91ac103afe7d92f594c6c57049e1829c773 Mon Sep 17 00:00:00 2001 From: Kevin Tang Date: Fri, 11 Sep 2015 19:40:25 -0700 Subject: [PATCH] Crash fix with MsgTask API change Removed tCreate and tAssociate from MsgTask. LocThread now can optionally take a tCreate method. Associator is replaced with *firstMsg* option to MsgTask, which is a more generic option, that can associate or do other set up job at the create of a MsgTask. The current MsgTask doesn't use tCreate, which exposes a slight time window for Location HAL when its MsgTask is NOT associated to DVM heap but a message delivery to DVM could be attempted during this time. Change-Id: Iafd5b91b693baacb9b7064463f8c44f74026f54c CRs-Fixed: 902350 --- core/LocDualContext.cpp | 76 ++++++---------------- core/LocDualContext.h | 26 ++++---- loc_api/libloc_api_50001/LocEngAdapter.cpp | 6 +- loc_api/libloc_api_50001/LocEngAdapter.h | 2 +- loc_api/libloc_api_50001/loc_eng.cpp | 3 +- utils/LocSharedLock.h | 58 +++++++++++++++++ utils/LocThread.cpp | 50 ++++++++------ utils/LocThread.h | 7 +- utils/LocTimer.cpp | 22 +------ utils/LocTimer.h | 4 +- utils/MsgTask.cpp | 48 +++----------- utils/MsgTask.h | 17 +---- 12 files changed, 151 insertions(+), 168 deletions(-) create mode 100644 utils/LocSharedLock.h diff --git a/core/LocDualContext.cpp b/core/LocDualContext.cpp index d68cb3bc..578421cd 100644 --- a/core/LocDualContext.cpp +++ b/core/LocDualContext.cpp @@ -63,34 +63,28 @@ const char* LocDualContext::mLBSLibName = "liblbs_core.so"; pthread_mutex_t LocDualContext::mGetLocContextMutex = PTHREAD_MUTEX_INITIALIZER; -const MsgTask* LocDualContext::getMsgTask(MsgTask::tCreate tCreator, - const char* name) +const MsgTask* LocDualContext::getMsgTask(LocThread::tCreate tCreator, + const char* name, bool joinable) { if (NULL == mMsgTask) { - mMsgTask = new MsgTask(tCreator, name); + mMsgTask = new MsgTask(tCreator, name, joinable); } return mMsgTask; } -const MsgTask* LocDualContext::getMsgTask(MsgTask::tAssociate tAssociate, - const char* name) -{ - if (NULL == mMsgTask) { - mMsgTask = new MsgTask(tAssociate, name); - } else if (tAssociate) { - mMsgTask->associate(tAssociate); - } - return mMsgTask; +inline +const MsgTask* LocDualContext::getMsgTask(const char* name, bool joinable) { + return getMsgTask((LocThread::tCreate)NULL, name, joinable); } -ContextBase* LocDualContext::getLocFgContext(MsgTask::tCreate tCreator, - const char* name) +ContextBase* LocDualContext::getLocFgContext(LocThread::tCreate tCreator, + LocMsg* firstMsg, const char* name, bool joinable) { pthread_mutex_lock(&LocDualContext::mGetLocContextMutex); LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__); if (NULL == mFgContext) { LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__); - const MsgTask* msgTask = getMsgTask(tCreator, name); + const MsgTask* msgTask = getMsgTask(tCreator, name, joinable); mFgContext = new LocDualContext(msgTask, mFgExclMask); } @@ -100,37 +94,22 @@ ContextBase* LocDualContext::getLocFgContext(MsgTask::tCreate tCreator, injectFeatureConfig(mInjectContext); } pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); + + if (firstMsg) { + mFgContext->sendMsg(firstMsg); + } + return mFgContext; } -ContextBase* LocDualContext::getLocFgContext(MsgTask::tAssociate tAssociate, - const char* name) -{ - pthread_mutex_lock(&LocDualContext::mGetLocContextMutex); - LOC_LOGD("%s:%d]: querying ContextBase with tAssociate", __func__, __LINE__); - if (NULL == mFgContext) { - LOC_LOGD("%s:%d]: creating msgTask with tAssociate", __func__, __LINE__); - const MsgTask* msgTask = getMsgTask(tAssociate, name); - mFgContext = new LocDualContext(msgTask, - mFgExclMask); - } - if(NULL == mInjectContext) { - LOC_LOGD("%s:%d]: mInjectContext is FgContext", __func__, __LINE__); - mInjectContext = mFgContext; - injectFeatureConfig(mInjectContext); - } - pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); - return mFgContext; -} - -ContextBase* LocDualContext::getLocBgContext(MsgTask::tCreate tCreator, - const char* name) +ContextBase* LocDualContext::getLocBgContext(LocThread::tCreate tCreator, + LocMsg* firstMsg, const char* name, bool joinable) { pthread_mutex_lock(&LocDualContext::mGetLocContextMutex); LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__); if (NULL == mBgContext) { LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__); - const MsgTask* msgTask = getMsgTask(tCreator, name); + const MsgTask* msgTask = getMsgTask(tCreator, name, joinable); mBgContext = new LocDualContext(msgTask, mBgExclMask); } @@ -140,26 +119,11 @@ ContextBase* LocDualContext::getLocBgContext(MsgTask::tCreate tCreator, injectFeatureConfig(mInjectContext); } pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); - return mBgContext; -} -ContextBase* LocDualContext::getLocBgContext(MsgTask::tAssociate tAssociate, - const char* name) -{ - pthread_mutex_lock(&LocDualContext::mGetLocContextMutex); - LOC_LOGD("%s:%d]: querying ContextBase with tAssociate", __func__, __LINE__); - if (NULL == mBgContext) { - LOC_LOGD("%s:%d]: creating msgTask with tAssociate", __func__, __LINE__); - const MsgTask* msgTask = getMsgTask(tAssociate, name); - mBgContext = new LocDualContext(msgTask, - mBgExclMask); + if (firstMsg) { + mBgContext->sendMsg(firstMsg); } - if(NULL == mInjectContext) { - LOC_LOGD("%s:%d]: mInjectContext is BgContext", __func__, __LINE__); - mInjectContext = mBgContext; - injectFeatureConfig(mInjectContext); - } - pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); + return mBgContext; } diff --git a/core/LocDualContext.h b/core/LocDualContext.h index 1e96ea56..ce77a1aa 100644 --- a/core/LocDualContext.h +++ b/core/LocDualContext.h @@ -41,10 +41,9 @@ class LocDualContext : public ContextBase { static ContextBase* mFgContext; static ContextBase* mBgContext; static ContextBase* mInjectContext; - static const MsgTask* getMsgTask(MsgTask::tCreate tCreator, - const char* name); - static const MsgTask* getMsgTask(MsgTask::tAssociate tAssociate, - const char* name); + static const MsgTask* getMsgTask(LocThread::tCreate tCreator, + const char* name, bool joinable = true); + static const MsgTask* getMsgTask(const char* name, bool joinable = true); static pthread_mutex_t mGetLocContextMutex; protected: @@ -58,14 +57,17 @@ public: static const LOC_API_ADAPTER_EVENT_MASK_T mBgExclMask; static const char* mLocationHalName; - static ContextBase* getLocFgContext(MsgTask::tCreate tCreator, - const char* name); - static ContextBase* getLocFgContext(MsgTask::tAssociate tAssociate, - const char* name); - static ContextBase* getLocBgContext(MsgTask::tCreate tCreator, - const char* name); - static ContextBase* getLocBgContext(MsgTask::tAssociate tAssociate, - const char* name); + static ContextBase* getLocFgContext(LocThread::tCreate tCreator, LocMsg* firstMsg, + const char* name, bool joinable = true); + inline static ContextBase* getLocFgContext(const char* name, bool joinable = true) { + return getLocFgContext(NULL, NULL, name, joinable); + } + static ContextBase* getLocBgContext(LocThread::tCreate tCreator, LocMsg* firstMsg, + const char* name, bool joinable = true); + inline static ContextBase* getLocBgContext(const char* name, bool joinable = true) { + return getLocBgContext(NULL, NULL, name, joinable); + } + static void injectFeatureConfig(ContextBase *context); }; diff --git a/loc_api/libloc_api_50001/LocEngAdapter.cpp b/loc_api/libloc_api_50001/LocEngAdapter.cpp index d1b8f8fc..a092fbe8 100644 --- a/loc_api/libloc_api_50001/LocEngAdapter.cpp +++ b/loc_api/libloc_api_50001/LocEngAdapter.cpp @@ -55,13 +55,15 @@ void LocInternalAdapter::getZppInt() { LocEngAdapter::LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask, void* owner, ContextBase* context, - MsgTask::tCreate tCreator) : + LocThread::tCreate tCreator) : LocAdapterBase(mask, //Get the AFW context if VzW context has not already been intialized in //loc_ext context == NULL? LocDualContext::getLocFgContext(tCreator, - LocDualContext::mLocationHalName) + NULL, + LocDualContext::mLocationHalName, + false) :context), mOwner(owner), mInternalAdapter(new LocInternalAdapter(this)), mUlp(new UlpProxyBase()), mNavigating(false), diff --git a/loc_api/libloc_api_50001/LocEngAdapter.h b/loc_api/libloc_api_50001/LocEngAdapter.h index e1d8f098..5eff6f36 100644 --- a/loc_api/libloc_api_50001/LocEngAdapter.h +++ b/loc_api/libloc_api_50001/LocEngAdapter.h @@ -88,7 +88,7 @@ public: LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask, void* owner, ContextBase* context, - MsgTask::tCreate tCreator); + LocThread::tCreate tCreator); virtual ~LocEngAdapter(); virtual void setUlpProxy(UlpProxyBase* ulp); diff --git a/loc_api/libloc_api_50001/loc_eng.cpp b/loc_api/libloc_api_50001/loc_eng.cpp index 917c2ae2..258db3e9 100644 --- a/loc_api/libloc_api_50001/loc_eng.cpp +++ b/loc_api/libloc_api_50001/loc_eng.cpp @@ -223,7 +223,6 @@ static void* noProc(void* data) return NULL; } - /********************************************************************* * definitions of the static messages used in the file *********************************************************************/ @@ -1768,7 +1767,7 @@ int loc_eng_init(loc_eng_data_s_type &loc_eng_data, LocCallbacks* callbacks, loc_eng_data.adapter = new LocEngAdapter(event, &loc_eng_data, context, - (MsgTask::tCreate)callbacks->create_thread_cb); + (LocThread::tCreate)callbacks->create_thread_cb); LOC_LOGD("loc_eng_init created client, id = %p\n", loc_eng_data.adapter); diff --git a/utils/LocSharedLock.h b/utils/LocSharedLock.h new file mode 100644 index 00000000..6b9e27f1 --- /dev/null +++ b/utils/LocSharedLock.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __LOC_SHARED_LOCK__ +#define __LOC_SHARED_LOCK__ + +#include +#include + +// This is a utility created for use cases such that there are more than +// one client who need to share the same lock, but it is not predictable +// which of these clients is to last to go away. This shared lock deletes +// itself when the last client calls its drop() method. To add a cient, +// this share lock's share() method has to be called, so that the obj +// can maintain an accurate client count. +class LocSharedLock { + uint32_t mRef; + pthread_mutex_t mMutex; + inline ~LocSharedLock() { pthread_mutex_destroy(&mMutex); } +public: + // first client to create this LockSharedLock + inline LocSharedLock() : mRef(1) { pthread_mutex_init(&mMutex, NULL); } + // following client(s) are to *share()* this lock created by the first client + inline LocSharedLock* share() { mRef++; return this; } + // whe a client no longer needs this shared lock, drop() shall be called. + inline void drop() { if (0 == --mRef) delete this; } + // locking the lock to enter critical section + inline void lock() { pthread_mutex_lock(&mMutex); } + // unlocking the lock to leave the critical section + inline void unlock() { pthread_mutex_unlock(&mMutex); } +}; + +#endif //__LOC_SHARED_LOCK__ diff --git a/utils/LocThread.cpp b/utils/LocThread.cpp index ec1e0719..19bf101a 100644 --- a/utils/LocThread.cpp +++ b/utils/LocThread.cpp @@ -37,12 +37,12 @@ class LocThreadDelegate { pthread_mutex_t mMutex; int mRefCount; ~LocThreadDelegate(); - LocThreadDelegate(const char* threadName, + LocThreadDelegate(LocThread::tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable); void destroy(); public: - static LocThreadDelegate* create(const char* threadName, - LocRunnable* runnable, bool joinable); + static LocThreadDelegate* create(LocThread::tCreate creator, + const char* threadName, LocRunnable* runnable, bool joinable); void stop(); // bye() is for the parent thread to go away. if joinable, // parent must stop the spawned thread, join, and then @@ -62,19 +62,28 @@ public: // However, upon pthread_create failure, the data members // must be set to indicate failure, e.g. mRunnable, and // threashold approprietly for destroy(), e.g. mRefCount. -LocThreadDelegate::LocThreadDelegate(const char* threadName, - LocRunnable* runnable, bool joinable) : - mRunnable(runnable), mJoinable(joinable), +LocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator, + const char* threadName, LocRunnable* runnable, bool joinable) : + mRunnable(runnable), mJoinable(joinable), mThandle(NULL), mMutex(PTHREAD_MUTEX_INITIALIZER), mRefCount(2) { + + // set up thread name, if nothing is passed in + if (!threadName) { + threadName = "LocThread"; + } + // create the thread here, then if successful // and a name is given, we set the thread name - if (!pthread_create(&mThandle, NULL, threadMain, this)) { + if (creator) { + mThandle = creator(threadName, threadMain, this); + } else if (pthread_create(&mThandle, NULL, threadMain, this)) { + // pthread_create() failed + mThandle = NULL; + } + + if (mThandle) { // set thread name char lname[16]; - const char* defaultName = "LocThread"; - if (!threadName) { - threadName = defaultName; - } int len = sizeof(lname) - 1; memcpy(lname, threadName, len); lname[len] = 0; @@ -99,11 +108,11 @@ LocThreadDelegate::~LocThreadDelegate() { } // factory method so that we could return NULL upon failure -LocThreadDelegate* LocThreadDelegate::create(const char* threadName, - LocRunnable* runnable, bool joinable) { +LocThreadDelegate* LocThreadDelegate::create(LocThread::tCreate creator, + const char* threadName, LocRunnable* runnable, bool joinable) { LocThreadDelegate* thread = NULL; if (runnable) { - thread = new LocThreadDelegate(threadName, runnable, joinable); + thread = new LocThreadDelegate(creator, threadName, runnable, joinable); if (thread && !thread->isRunning()) { thread->destroy(); thread = NULL; @@ -199,11 +208,14 @@ LocThread::~LocThread() { } } -bool LocThread::start(const char* threadName, LocRunnable* runnable, bool joinable) { - mThread = LocThreadDelegate::create(threadName, runnable, joinable); - - // true only if thread is created successfully - return (NULL != mThread); +bool LocThread::start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable) { + bool success = false; + if (!mThread) { + mThread = LocThreadDelegate::create(creator, threadName, runnable, joinable); + // true only if thread is created successfully + success = (NULL != mThread); + } + return success; } void LocThread::stop() { diff --git a/utils/LocThread.h b/utils/LocThread.h index 490d3099..2a65d8fa 100644 --- a/utils/LocThread.h +++ b/utils/LocThread.h @@ -30,6 +30,7 @@ #define __LOC_THREAD__ #include +#include // abstract class to be implemented by client to provide a runnable class // which gets scheduled by LocThread @@ -64,6 +65,7 @@ public: inline LocThread() : mThread(NULL) {} virtual ~LocThread(); + typedef pthread_t (*tCreate)(const char* name, void* (*start)(void*), void* arg); // client starts thread with a runnable, which implements // the logics to fun in the created thread context. // The thread could be either joinable or detached. @@ -74,7 +76,10 @@ public: // returns true. Else it is client's responsibility // to delete the object // Returns 0 if success; false if failure. - bool start(const char* threadName, LocRunnable* runnable, bool joinable = true); + bool start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable = true); + inline bool start(const char* threadName, LocRunnable* runnable, bool joinable = true) { + return start(NULL, threadName, runnable, joinable); + } // NOTE: if this is a joinable thread, this stop may block // for a while until the thread is joined. diff --git a/utils/LocTimer.cpp b/utils/LocTimer.cpp index 0f698c54..c992e7c2 100644 --- a/utils/LocTimer.cpp +++ b/utils/LocTimer.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #ifdef __HOST_UNIT_TEST__ @@ -46,22 +46,6 @@ #define CLOCK_BOOTTIME_ALARM CLOCK_MONOTONIC #endif -using namespace loc_core; - -// a shared lock until, place it here for now. -class LocUtilSharedLock { - uint32_t mRef; - pthread_mutex_t mMutex; - inline ~LocUtilSharedLock() { pthread_mutex_destroy(&mMutex); } -public: - inline LocUtilSharedLock() : mRef(1) { pthread_mutex_init(&mMutex, NULL); } - inline LocUtilSharedLock* share() { mRef++; return this; } - inline void drop() { if (0 == --mRef) delete this; } - inline void lock() { pthread_mutex_lock(&mMutex); } - inline void unlock() { pthread_mutex_unlock(&mMutex); } -}; - - /* There are implementations of 5 classes in this file: LocTimer, LocTimerDelegate, LocTimerContainer, LocTimerPollTask, LocTimerWrapper @@ -191,7 +175,7 @@ class LocTimerDelegate : public LocRankable { friend class LocTimerContainer; friend class LocTimer; LocTimer* mClient; - LocUtilSharedLock* mLock; + LocSharedLock* mLock; struct timespec mFutureTime; LocTimerContainer* mContainer; // not a complete obj, just ctor for LocRankable comparisons @@ -548,7 +532,7 @@ void LocTimerDelegate::expire() { /***************************LocTimer methods***************************/ -LocTimer::LocTimer() : mTimer(NULL), mLock(new LocUtilSharedLock()) { +LocTimer::LocTimer() : mTimer(NULL), mLock(new LocSharedLock()) { } LocTimer::~LocTimer() { diff --git a/utils/LocTimer.h b/utils/LocTimer.h index 9606fe53..c1468524 100644 --- a/utils/LocTimer.h +++ b/utils/LocTimer.h @@ -35,14 +35,14 @@ // opaque class to provide service implementation. class LocTimerDelegate; -class LocUtilSharedLock; +class LocSharedLock; // LocTimer client must extend this class and implementthe callback. // start() / stop() methods are to arm / disarm timer. class LocTimer { LocTimerDelegate* mTimer; - LocUtilSharedLock* mLock; + LocSharedLock* mLock; // don't really want mLock to be manipulated by clients, yet LocTimer // has to have a reference to the lock so that the delete of LocTimer // and LocTimerDelegate can work together on their share resources. diff --git a/utils/MsgTask.cpp b/utils/MsgTask.cpp index 8b645dd5..fdb11026 100644 --- a/utils/MsgTask.cpp +++ b/utils/MsgTask.cpp @@ -36,12 +36,19 @@ #include #include -namespace loc_core { - static void LocMsgDestroy(void* msg) { delete (LocMsg*)msg; } +MsgTask::MsgTask(LocThread::tCreate tCreator, + const char* threadName, bool joinable) : + mQ(msg_q_init2()), mThread(new LocThread()) { + if (!mThread->start(tCreator, threadName, this, joinable)) { + delete mThread; + mThread = NULL; + } +} + MsgTask::MsgTask(const char* threadName, bool joinable) : mQ(msg_q_init2()), mThread(new LocThread()) { if (!mThread->start(threadName, this, joinable)) { @@ -93,40 +100,3 @@ bool MsgTask::run() { return true; } - -// TODO: remove the below in the next patch -void MsgTask::associate(tAssociate tAssociator) const { - struct LocAssociateMsg : public LocMsg { - tAssociate mAssociator; - LocAssociateMsg(tAssociate associator) : - mAssociator(associator) {} - inline virtual void proc() const { - static bool sAssociated = false; - if (!sAssociated) { - sAssociated = true; - mAssociator(); - } - } - }; - sendMsg(new LocAssociateMsg(tAssociator)); -} - -MsgTask::MsgTask(tCreate tCreator, const char* threadName) : - mQ(msg_q_init2()), mThread(new LocThread()) { - if (!mThread->start(threadName, this, false)) { - delete mThread; - mThread = NULL; - } -} - -MsgTask::MsgTask(tAssociate tAssociator, const char* threadName) : - mQ(msg_q_init2()), mThread(new LocThread()) { - if (!mThread->start(threadName, this, false)) { - delete mThread; - mThread = NULL; - } else { - associate(tAssociator); - } -} - -} // namespace loc_core diff --git a/utils/MsgTask.h b/utils/MsgTask.h index c397ee10..9eb1f567 100644 --- a/utils/MsgTask.h +++ b/utils/MsgTask.h @@ -30,10 +30,6 @@ #define __MSG_TASK__ #include -// TODO: remove this include in the next patch -#include - -namespace loc_core { struct LocMsg { inline LocMsg() {} @@ -42,13 +38,14 @@ struct LocMsg { inline virtual void log() const {} }; -class MsgTask : public LocRunnable{ +class MsgTask : public LocRunnable { const void* mQ; LocThread* mThread; friend class LocThreadDelegate; protected: virtual ~MsgTask(); public: + MsgTask(LocThread::tCreate tCreator, const char* threadName = NULL, bool joinable = true); MsgTask(const char* threadName = NULL, bool joinable = true); // this obj will be deleted once thread is deleted void destroy(); @@ -65,16 +62,6 @@ public: // The method to be run after thread loop (conditionally repeatedly) // calls run() inline virtual void postrun() {} - - // TODO: remove the below in the next patch - typedef void* (*tStart)(void*); - typedef pthread_t (*tCreate)(const char* name, tStart start, void* arg); - typedef int (*tAssociate)(); - MsgTask(tCreate tCreator, const char* threadName); - MsgTask(tAssociate tAssociator, const char* threadName); - void associate(tAssociate tAssociator) const; }; -} // namespace loc_core - #endif //__MSG_TASK__