"Call ~~~~ Pop !"
A folder draws a beautiful arc across four tables, two walls, and one aisle. It passes through the conversation's passer-by and passer-by B without any help, hitting the target accurately. Looking at the company, only solmyr has such a throwing technique, and his goal is naturally zero.
"Alas !", Zero touched the back of his head and sighed half of his life: No need to ask, he must have another handle captured by solmyr.
"Why did I make another mistake this time ?", Zero hurriedly interrupted a pleasant chat with Pisces, the only female programmer within fifty meters, and came to solmyr to see what went wrong.
"The code you just submitted will cause a thread deadlock." solmyr points to a function submitted by zero:
Void some_func ()
{
Pthread_mutex_lock (& CTX );
......
......
Pthread_mutex_unlock (& CTX );
}
"Yes? I obviously released mutex variables at the end of the function ?"
Solmyr looked at zero and said with a clear expression: the arms cannot be carved. He successfully marked two lines of code in the middle of the function:
Void some_func ()
{
Pthread_mutex_lock (& CTX );
......
If (status = e_fail)
Return;
......
Pthread_mutex_unlock (& CTX );
}
"Oops !", Zero slapped his head and said, "I know, I know, I want to change it ."
"Do you know? Let's talk about what mistakes you have made ?"
"I forgot to unlock the function return point in the middle ."
"How are you going to solve this problem?" It is obvious that solmyr is not going to let zero go.
"Well ...... It's easy to add a line of code here, like this :"
If (status = e_fail)
{
Pthread_mutex_unlock (CTX );
Return;
}
Solmyr shook his head: "You are a headache and a pain point. If you have more than one lock and more than one return point in this function, what are you going to do? Is each lock unlocked at each return point ?"
"Well ...... Do you mean that I should follow the principle that a function has only one return point ?", Zero scratched the head, and some were not sure.
"I don't mean this. In some cases, it is hard to make the function have only one return point, which will lead to a huge if/else structure and reduce the readability of the Code. Besides, even if your function has only one return point, you may still encounter this problem. Consider this function: ", solmyr quickly typed:
Void some_func ()
{
Pthread_mutex_lock (& CTX );
......
// No other return points in the middle
......
Foo (); // functions implemented by other programmers
......
Pthread_mutex_unlock (& CTX );
}
"It seems that there is no problem at all, but what will happen if the foo function throws an exception ?"
"Well ...... If this exception is not caught in our function ...... It causes the some_func function to interrupt the call to foo ...... ......", Zero found the problem. "Then we can only capture all exceptions at every function call point that may throw exceptions, and then ......", The more you say zero, the more you whisper, "... Then unlock it in the catch and then throw it again ......" Zero stopped, scratched his head with annoyance, and found that he could not even convince himself: This solution is too cumbersome and too easy to introduce errors.
"Hmm ?"
"Okay, I admit I don't know what to do, solmyr. What should I do ?"
"Recall what we discussed at the dinner table two days ago ?" (See the previous issue of "solmyr's article series", "Garbage Collection ")
"Do you mean garbage collection? Ah ...... But ...... Is that used to handle memory leaks? What is the relationship with this question ?"
"I don't mean a specific solution," solmyr shook his head. "The key is the general principle introduced in the previous discussion, that is ......" Solmyr stopped and looked at zero.
"…… ......"
"Alas ......", Solmyr uses the helpless expression that others cannot imitate-according to his own statement, this is the accumulation of many years of training work-sigh: "I said zero, you are still very young, won't memory decline so early?"
...... It's really a hateful guy, and zero's hate in his mind.
The solmyr sound again sounded as zero approached the verge of collapse: "If you want to make sure something happens in pairs, use it ......"
"Constructor and destructor !", Zero was afraid to miss the opportunity to show that it was not a "memory loss.
"You don't have to shout so loud .", Solmyr frowned. "You have frightened the audience in the front row ."
"?!", Zero quickly turned around and found that the company's colleagues were everywhere nearby, and everyone was "normal" doing their own thing, just a little busy ......
After solving the "audience" around, zero returned to the display with full confidence: "I know solmyr, here we can use a very similar method to the last time we processed the allocation/release of memory to deal with locking/unlocking, as long as we write a very simple class, like this: ", zero side said, type:
Class auto_lock
{
Public:
Auto_lock (pthread_mutex_t content): m_content-1 (content-1)
{
Pthread_mutex_lock (& m_ctx); // lock during construction
}
~ Auto_lock ()
{
Pthread_mutex_unlock (& m_ctx); // unlock during Structure Analysis
}
PRIVATE:
Pthread_mutex_t & m_ctx;
}
Void some_func ()
{
Auto_lock (CTX );
......
// Return and foo. Everything works.
......
// Do not unlock at the end
}
"In this way, all the problems I encountered have been solved. I can freely implement my functions, no matter when I return or encounter exceptions, I can be sure that the user can unlock the content of the User-Agent. Don't worry about the thread deadlock."
"Well, good ." Solmyr nodded with approval and began to sum up: "In fact, this is a very common method. In addition to the two situations we have discussed, it can also be used in many occasions. For example, you can establish or disconnect a connection during network access, log on and exit from a database access, and conveniently use it to measure the average running time of a function. However, there is a unified principle behind all these applications ......"
Solmyr paused, and zero was able to pick it up:
"If you want to ensure that something appears in pairs, use constructor and destructor ."