Imagine that there is no such requirement:
For each new object, we want it to be automatically destroyed after a certain amount of time, provided that we do not give it a reset signal during this time period.
This demand is in fact some, such as in the film, the protagonist knows a villain does not want to expose the secret, but also need to keep their lives, then you can construct such an object, if the protagonist does not send this object to reset the signal in 24 hours, it will be the secret of the public. For example, in the network application scenario, we want each client to be able to send us a heartbeat packet at regular intervals, if not sent for a long time, we will eliminate this customer.
In the previous article, I tried to use the WIN32 timer, but found that this is cumbersome and error-prone, you need to bind a timer to each object, you need to handle the object when the timer expires, and reset the timer's API and Settings timer API is the same, A little careless will screw it up.
Now, I came up with a relatively simple implementation, although the accuracy is not very ideal, but for the general application, it is enough.
We construct a class that has some private data that can be customized, but some APIs are required:
classclient{Private: // ... Data or somethingint32_t M_life; int32_t M_max_life; DWORD delete_thread_id; HANDLE Count_thread_handle; Public: Client (int32_t, DWORD); voidResetvoid); StaticWin32API DWORD Countdownentry (void*); DWORD Countdown (void); // ... De-cons ...}
1. Constructors:
Client:client (int32_t life, DWORD thread_id) { = M_life = Life ; = thread_id; Count_thread_handle = CreateThread (..., client::countdownentry, this);}
The second parameter is the thread ID that is used to destroy the object, so the design takes into account that the object might be stored in a heap, and if we simply call the destructor, the space occupied by the object itself cannot be freed, so we notify such a thread to complete all the destructors.
Notice that we are using countdownentry () instead of Countdown (), because CreateThread does not accept a non-static member function as a function entry (cannot confirm the address).
2. Reset () method, this method needs to suspend the countdown thread first, mainly to prevent simultaneous access to the same memory situation occurs:
void Client::reset (void) {
SuspendThread (count_thread_handle); = M_max_life;
ResumeThread (Count_thread_handle);}
3. Why is the Countdownentry () method static? Very simple, we need to use it in the constructor to initialize the countdown thread, and its implementation is very simple, we pass the this pointer to the static method in the constructor, and in the static method to retrieve the object of this, call the object's Countdown function can be:
Static Win32API DWORD client::countdownentry (void *pm) { *c = (Client *) pm; return c->countdown ();}
4. While the countdown () method is simpler, you can use the Sleep function to time your life minus 1 per second:
DWORD Client::countdown () { while0) { Sleep (+); M_life--; } Postthreadmessagea (delete_thread_id); return 0 ;}
Above is such an object design idea, the principle is relatively simple, also just wrote a approximate, at the same time need windows.h support.
[C + +] An implementation of a class capable of timing self-destruct