In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the knowledge of "what are the basic components of the micro-service open source framework TARS". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
Thread safe queue: TC_ThreadQueue
Let's take a look at the framework's use of the TC_ThreadQueue class as follows:
Typedef TC_ThreadQueue recv_queue; / / receive queue typedef TC_ThreadQueue send_queue; / / send queue
The implementation of TC_ThreadQueue is relatively simple. In the network layer implementation of TARS, you can find that this class is more important, because the network packets received from the framework will be added to the cache queue, and then the multi-service thread ServantHandle will call waitForRecvQueue to get the network packets from the queue, and then call dispatch to call the corresponding processing function of the protocol message. First, take a look at the framework's implementation of TC_ThreadQueue:
/ * * @ brief thread safety queue * / templateclass TC_ThreadQueue {public: TC_ThreadQueue (): _ size (0) {}; public: typedef D queue_type / * * @ brief gets data from header, no data throw exception * * @ param t * @ return bool: true, get data, false, numerous data * / T front (); / * * @ brief get data from header, wait if there is no data. * * @ param t * @ param millsecond (effective only when wait = true) blocking wait time (ms) * 0 means no blocking *-1 permanent waiting * @ param wait, whether wait * @ return bool: true, get the data, false Countless data * / bool pop_front (T & t, size_t millsecond = 0, bool wait = true) ......}
TC_ThreadQueue uses and implements thread locking and wait in the standard library of Clover 11. Take a look at the queue member function as follows: push_front adds data in front of the queue
Template void TC_ThreadQueue::push_front (const T & t, bool notify) {if (notify) {std::unique_lock lock (_ mutex); _ cond.notify_one (); _ queue.push_front (t); + + _ size;} else {std::lock_guard lock (_ mutex); _ queue.push_front (t); + + _ size;}}
For example, when the push_front function is called in the above figure, std::unique_lock lock (_ mutex) is called to add the lock to avoid the conflict between the data received by the network layer and the data taken from the same queue at the business layer. _ cond.notify_one () notifies that a thread is waiting for the lock to wake up, and the function must be locked before calling the function. For example, a thread in the network layer needs to pick up the packet and distribute it for processing.
Look at another member function, pop_front, which fetches data from the header and waits if there is no data. Millisecond blocking wait time (ms)
0 means no blocking
-1 wait forever
Template bool TC_ThreadQueue::pop_front (T & t, size_t millsecond, bool wait) {if (wait) {std::unique_lock lock (_ mutex); if (_ queue.empty ()) {if (millsecond = = 0) {return false;} if (millsecond = = (size_t)-1) {_ cond.wait (lock) } else {/ / timed out if (_ cond.wait_for (lock, std::chrono::milliseconds (millsecond)) = = std::cv_status::timeout) {return false;} if (_ queue.empty ()) {return false } t = _ queue.front (); _ queue.pop_front (); assert (_ size > 0);-- _ size; return true;} else {std::lock_guard lock (_ mutex); if (_ queue.empty ()) {return false;} t = _ queue.front () _ queue.pop_front (); assert (_ size > 0);-- _ size; return true;}}
The function of BindAdapter::waitForRecvQueue calls the pop_front function, which is used to wait for the receiving queue. The function prototype is as follows:
Bool TC_EpollServer::BindAdapter::waitForRecvQueue (uint32_t handleIndex, shared_ptr & data) {bool bRet = getRecvQueue (handleIndex). Pop_front (data); if (! bRet) {return bRet;}-_ iRecvBufferSize; return bRet;}
Here, BindAdapter::waitForRecvQueue is used by the business thread to process the business packet after waiting for the adapter listening to the server to receive the network packet. The handleIndex passed here means to receive the queue index and get the corresponding _ rbuffer.
Normal thread lock: TC_ThreadLock
The TC_ThreadLock class is defined as follows
Typedef TC_Monitor TC_ThreadLock
TC_Monitor thread lock monitoring template class. Usually thread locks are used through this class, rather than directly using TC_ThreadMutex or TC_ThreadRecMutex.
The definition of the class template class TC_Monitor requires passing in two template parameters, and the TC_Monitor includes the following member variables:
Mutable int _ nnotify; / / number of times locked mutable P _ cond; / / condition variable T _ mutex; / / mutex / * * @ brief defines lock control object * / typedef TC_LockT Lock;typedef TC_TryLockT TryLock
The first parameter, TC_ThreadMutex, represents a thread lock: the same thread cannot be locked repeatedly and contains member variables.
Mutable std::mutex _ mutex
To extend the reading, tc_thread_mutex.h also includes another loop lock class TC_ThreadRecMutex, that is, a thread can add locks multiple times, as defined as follows:
/ / typedef TC_Monitor TC_ThreadRecLock is defined in tc_monitor.h
The second parameter, TC_ThreadCond, represents the thread signal condition class: all locks can wait for the signal to occur, including thread condition member variables:
Mutable std::condition_variable_any _ cond
Combined with the actual usage scenario, TC_Monitor::timedWait () calls the timedWait function of the TC_ThreadCond object, and the next step is to call the milliseconds;TC_ThreadCond::signal () implementation of the chrono library to send a signal, and a thread waiting on this condition will wake up.
TC_LockT class definition: template class TC_LockT lock template class, used in conjunction with other concrete locks, locked when constructed, and unlocked when parsing is enough.
TC_LockT constructor, which initializes the member variable _ mutex,TC_LockT constructor by passing in mutexes:
TC_LockT (const T & mutex): _ mutex (mutex) {_ mutex.lock (); _ acquired = true;}
Here you can see the typedef TC_LockT Lock defined by TC_Monitor, where the template parameters of the Lock type use the TC_Monitor class.
The actual usage scenarios are as follows:
Lock lock (* this)
The constructor of TC_LockT. The parameter this is a subclass object of TC_Monitor. The constructor of TC_LockT calls _ mutex.lock (). In fact, the lock function of TC_Monitor object is called and the lock function of TC_Monitor is implemented:
Void lock () const {_ mutex.lock (); _ nnotify = 0;}
Here _ mutex is the TC_ThreadMutex object, and the TC_ThreadRecMutex::lock () member function is further called, which is implemented as follows:
Void TC_ThreadMutex::lock () const {_ mutex.lock ();}
Then the destructor of TC_LockT is called when the lock stack variable defined above exits the function: the implementation is as follows:
Virtual ~ TC_LockT () {if (_ acquired) {_ mutex.unlock (); / / the unlock function of TC_Monitor will be called}}
The unlock function implementation of TC_Monitor:
Void unlock () const {notifyImpl (_ nnotify); _ mutex.unlock (); / / unlock in the C++ standard library will be called here.
The notifyImpl function is called here because the TC_Monitor class can not only implement the simple mutex function, but also implement the conditional variable Condition function, where the implementation of notifyImpl is
Void notifyImpl (int nnotify) const {if (nnotify! = 0) {if (nnotify = =-1) {_ cond.broadcast (); return;} else {while (nnotify > 0) {_ cond.signal ();-- nnotify } Thread Base Class: TC_Thread
As usual, take a look at the actual use of the thread base class by the project. In the actual project, we encapsulate TC_Thread and implement a BasicThread class. Let's take a look at the definition of BasicThread:
Class BasicThread: public tars::TC_Thread, public tars::TC_ThreadLock {... Void terminate () {_ bTerm = true; {Lock lock (* this); notifyAll ();} getThreadControl (). Join ();}}
The BasicThread class inherits TC_Thread and TC_ThreadLock, and the second point of TC_ThreadLock has already been explained, so here we focus on the use of the TC_Thread class and the definition of TC_Thread.
Class TC_Thread: public TC_Runable {. / * uses the standard thread library std::thread of thread 11. The constructor passes the parameter thread function, * returns TC_ThreadControl (_ th), where _ th is the std::thread object * / TC_ThreadControl start (); static void threadEntry (TC_Thread * thread); / / static function, thread entry virtual void run () = 0 ...}
Next, take a look at the definition of the thread control class TC_ThreadControl:
Class TC_ThreadControl {. Explicit TC_ThreadControl (std::thread * th); / / construct, pass in the std::thread object void join (); / / call the join () of std::thread to block the current thread until another thread ends running; / / the thread calling the std::this_thread::sleep function will suspend execution.}
Next, take a look at the definition of TC_Runable:
Class TC_Runable {public: virtual ~ TC_Runable () {}; virtual void run () = 0; / / defines the run pure virtual function}
Finally, take a look at the use of thread classes in the actual project.
Class AntiSdkSyncThread: public BasicThread / / here equals to inheriting the pure virtual function {Lock lock (* this) of the base class {void run () / / implementing the base class of TC_Thread and TC_ThreadLock; timedWait (10 * 1000) (interval execution time, realizing the function of timing execution of threads) if (NULL! = g_busi_interf) {Int32 ret = groombusitioning interf-> proc_ (); / / functions that need to be executed periodically}
After defining the AntiSdkSyncThread gaggregantiSdkSyncThread; class, execute g_antiSdkSyncThread.start () when you need to start the thread; then the thread is created naturally, and the threadEntry thread function calls the pThread- > run () polymorphic function, and g_antiSdkSyncThread.terminate () is called when the process exits.
Smart pointer class: TC_AutoPtr
The smart pointer here can be placed in the container, and the thread-safe smart pointer. The auto_ptr of the CPP11 standard library cannot be placed in the container, which seems to have been eliminated. At present, most of them use the shared_ptr of the CPP11 standard library, but the compiler needs to support CPP11.
The TC_HandleBase smart pointer base class is defined as follows, and all classes that require smart pointers need to inherit from this object, where atomic counting is used in the Cellular pointer 11 standard library.
Class UTIL_DLL_API TC_HandleBase {public: / * @ brief replication * * @ return TC_HandleBase& * / TC_HandleBase& operator= (const TC_HandleBase&) {return * this;} / * * @ brief increase count * / void incRef () {+ _ atomic } / * * @ brief reduce the count * / void decRef () {if ((--_ atomic) = = 0 & &! _ bNoDelete) {_ bNoDelete = true; delete this;}} / * @ brief to get the count. The * * @ return int count * / int getRef () const {return _ atomic;} / * * @ brief setting is not automatically released. * * @ param b is automatically deleted, true or false * / void setNoDelete (bool b) {_ bNoDelete = b } protected: / * * @ brief constructor * / TC_HandleBase (): _ atomic (0), _ bNoDelete (false) {} / * @ brief copy construction * / TC_HandleBase (const TC_HandleBase&): _ atomic (0) _ bNoDelete (false) {} / * @ brief destructing * / virtual ~ TC_HandleBase () {} protected: std::atomic _ atomic / / reference count bool _ bNoDelete; / / whether to delete automatically}
Next, take a look at the TC_AutoPtr smart pointer template class, which can be placed in a container and is thread-safe. The smart pointer is implemented through reference counting, and its constructor and destructor are defined as follows:
Template class TC_AutoPtr {TC_AutoPtr (T* p = 0) {_ ptr = p; if (_ ptr) {_ ptr- > incRef (); / / Constructor reference calculation plus 1}}. ~ TC_AutoPtr () {if (_ ptr) {_ ptr- > decRef () / / Destructor reference calculation minus 1} example: actual combat project uses struct ConnStruct: public TC_HandleBase {...} typedef TC_AutoPtr ConnStructPtr
TC_AutoPtr copy construction call _ ptr- > incRef (); here ptr is ConnStruct,ConnStruct inherited from TC_HandleBase, which equals to calling TC_HandleBaseT::incRef () {+ _ atomic;}
The reference count atomic operation is added by 1, and the destructed reference count atomic operation is subtracted by 1. When the reference count is reduced to 0, the delete is triggered according to whether the set switch is deleted or not.
Example: this is a typical example of TARS using asynchronous rpc callback, where the callback class uses smart pointer / / to define the callback function smart pointer, where the SessionCallback parent class inherits from TC_HandleBasetypedef TC_AutoPtr SessionCallbackPtr; / / to create the callback class SessionCallbackPtr, and passes in the initialization parameter uin gameid, etc. SessionCallbackPtr cb = new SessionCallback (iUin, iGameId, iSeqID, iCmd,sSessionID, theServant, current, cs, this); / / asynchronously call sessionserver remote interface getSessionPrx ()-> async_getSession (cb, iUin, iGameId)
The API returns completion, and the SessionCallback::callback_getSession (tars::Int32 ret, const MGComm::SessionValue& retValue) function is called back to receive the returned SessionValue structure of the sessionserver interface.
Because SessionCallbackPtr uses smart pointers, the business does not need to manually release the SessionCallbackPtr from the previous new, which is more convenient.
MySQL operation class: TC_Mysql
TC_Mysql encapsulated mysql operation class, non-thread safe, for insert/update can have a better function encapsulation to prevent SQL injection
Mode of use:
TC_Mysql mysql;// does not link when initializing mysql,init, and links are established automatically upon request; / / the database can be empty; / / the port defaults to 3306mysql.init ("192.168.1.2", "pc", "pc@sn", "db_tars_demo")
Commonly used: void init (const TC_DBConf& tcDBConf); initialize the database directly. For example: stDirectMysql.init (_ stZoneDirectDBConf)
Look at the definition of TC_DBConf
Struct TC_DBConf {string _ host; string _ user; string _ password; string _ database; string _ charset; int _ port; int _ flag; / / client ID TC_DBConf (): _ port (0), _ flag (0) {} / * * @ brief reads the database configuration. * * @ param mpParam stores the map * dbhost of the database configuration: host address * dbuser: user name * dbpass: password * dbname: database name * dbport: port * / void loadFromMap (const map & mpParam) {map mpTmp = mpParam; _ host = mpTmp ["dbhost"] _ user = mpTmp ["dbuser"]; _ password = mpTmp ["dbpass"]; _ database = mpTmp ["dbname"]; _ charset = mpTmp ["charset"]; _ port = atoi (mpTmp ["dbport"]. C_str ()); _ flag = 0 If (mpTmp ["dbport"] = "") {_ port = 3306;}; / / take a closer look at the use of getting data TC_Mysql::MysqlData data;data = mysql.queryRecord ("select * from t_app_users"); for (size_t I = 0; I < data.size ()) {/ / if the ID field does not exist, throw an exception cout
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.